Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DRAFT: extract ciruit_options when using public call interface #65

Conversation

skorbut
Copy link

@skorbut skorbut commented Dec 1, 2023

When providing circuit options while using the public call interface, these should be taken into account.

In order to do this we filter out known circuit options before merging all into the options.

Open question: Is there a definitive source for circuit_options keys?

Also I noticed, when using call with the circuit interface the circuit options are picked up, but get lost later in the process. See added specs in call_test.rb

@apotonick
Copy link
Member

Hi Karsten,
thanks for looking into this! Have you seen this commit where I try to fix that very problem? ac2fa2b

There is no defined set for circuit_options, unfortunately!

@apotonick
Copy link
Member

BTW, when using the public interface you're not supposed to provide circuit_options! The signature of Operation.call may suggest that, but you may only pass ctx and optional flow_options. Could you tell us why you need the public interface in combo with low-level options? 🍻

@skorbut
Copy link
Author

skorbut commented Dec 1, 2023

Hi,

we currently have several operations that were implemented quite optimistically. In order to add more detail when reporting failed operations I'd like to supply a protocol that will upload to our error reporting tool. In this protocol I list all steps with its result and runtime. The protocol is created using a TaskWrap extension and added to every operation via some BaseOperation class were I override the call method like

def self.call(*args, **kwargs)
    puts "BaseOperation#call"
    # register protocol extension
    protocol_extension = Trailblazer::Activity::TaskWrap::Extension(
      [::OperationsProtocol.method(:start_task),  id: "protocol.start_task",  prepend: "task_wrap.call_task"],
      [::OperationsProtocol.method(:end_task), id: "protocol.end_task", append: "task_wrap.call_task"],
    )
    protocol_wrap = Hash.new(protocol_extension)
    ctx = kwargs || {}
    byebug
    #super([ctx, {}], wrap_runtime: protocol_wrap)
  end

I also tried switching from public interface to circuit interface here, but it didn't call the extension. It's like the spec I added in this PR for testing the circuit interface with wrap_runtime.

@apotonick
Copy link
Member

This looks like you should definitely switch to the circuit interface: Operation.([{ctx}, {flow_options}], **your_options).

My plan has been (for a long time) to make as many users as possible invoke an endpoint that then calls the operation with appropriate options. The public Operation.call interface was a short-sighted idea to encourage service objects.

Can you check if the above signature works for you? Alternatively, try using the private method directly https://github.com/trailblazer/trailblazer-operation/blob/master/lib/trailblazer/operation/public_call.rb#L69

)

# public interface invocation using call
result = operation.(seq: [], wrap_runtime: Hash.new(my_extension))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is - per design - not supposed to work as it's impossible for us to know which keyword argument is flow_options and what is circuit_options. It was a design mistake to try and make the public #call the swiss army knife of TRB...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should, but I'm afraid it doesn't. I tried to debug, where my wrap_runtime got lost. But got lost myself. Somehow it doesn't get called. Test is there to document this behaviour.

@skorbut
Copy link
Author

skorbut commented Dec 1, 2023

Can you have a look at this spec? It is basically the same as the public interface spec, but it fails. Somehow the extension doesn't get called. If I get this to succeed, I wouldn't need the public interface change.

@skorbut skorbut marked this pull request as draft December 1, 2023 10:02
@apotonick
Copy link
Member

Sorry I was busy with the new website, I will figure out where we lose your :wrap_runtime tomorrow!

@skorbut
Copy link
Author

skorbut commented Dec 5, 2023

Thanks a lot, new Website looks great.

apotonick added a commit that referenced this pull request Dec 7, 2023
@apotonick
Copy link
Member

@skorbut This is how you make it work when using Operation.call:

signal, (ctx, _) = operation.call(
      [{seq: []}, {}],
      wrap_runtime: Hash.new(my_extension),
      runner: Trailblazer::Activity::TaskWrap::Runner
    )

@apotonick
Copy link
Member

Note that the ctx won't be automatically converted to a Context as it's done here: https://github.com/trailblazer/trailblazer-operation/blob/master/lib/trailblazer/operation/public_call.rb#L79

This is why I vote for slowly fading out usage of Operation.call in the next years in favor of invoking operations using an endpoint.

@skorbut
Copy link
Author

skorbut commented Dec 11, 2023

Thanks a lot for looking into this, just ran a few tests and it looks good. I'm closing this PR, no need to change a deprecated interface.

@skorbut skorbut closed this Dec 11, 2023
@apotonick
Copy link
Member

apotonick commented Dec 11, 2023

Well, technically, it's not deprecated as we cannot simply remove Create.(params: ...) 😬 the questions here are

  1. how do we manage to get people use the circuit interface for low-level concerns?
  2. what form of an endpoint would encourage developers to use that abstraction instead of globally overriding private methods to inject arbitrary data into the operation call?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants