-
Notifications
You must be signed in to change notification settings - Fork 220
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
New Update-With-Start API #1731
Conversation
7b0f0cc
to
c787087
Compare
// NewWithStartWorkflowOperation returns a WithStartWorkflowOperation to perform Update-with-Start. | ||
// Returns an error if the WorkflowIDConflictPolicy is not set, or if the workflow or arguments are invalid. | ||
// NOTE: Experimental | ||
NewWithStartWorkflowOperation(options StartWorkflowOptions, workflow interface{}, args ...interface{}) WithStartWorkflowOperation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NewWithStartWorkflowOperation(options StartWorkflowOptions, workflow interface{}, args ...interface{}) WithStartWorkflowOperation | |
NewWithStartWorkflowOperation(options WithStartWorkflowOperationOptions) WithStartWorkflowOperation |
Arguably this is more future proof, but understood if we don't want it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to be going too far to me: it doesn't seem right to have to create a WithStartWorkflowOperationOptions
struct in order to create a WithStartWorkflowOperation
given that the latter essentially is just a stateful version of the former.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(unresolved since I wanted to add a comment but it was resolved which disables the ability to discuss further)
it doesn't seem right to have to create a WithStartWorkflowOperationOptions struct in order to create a WithStartWorkflowOperation given that the latter essentially is just a stateful version of the former.
Creation methods of stateful things often accept options to create them and it helps us if later we need to add another option. I am ok if we all agree this isn't needed, but accepting an options object when creating something does save us from having a potential differently-named overload or adding mutation methods on the result later. I fear we will add some server-side option that only applies to multiop start workflow and we won't be able to represent it here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
which disables the ability to discuss further
Apparently not :)
I am ok if we all agree this isn't needed
Indeed, the consensus with others was that it wasn't needed.
I fear we will add some server-side option that only applies to multiop start workflow and we won't be able to represent it here.
We would be able to add such an option to UpdateWithStartWorkflowOptions
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We would be able to add such an option to UpdateWithStartWorkflowOptions.
Until we use this WithStartWorkflowOperation
for more than just update with start, which is why I figured it was named to not be related to update. But it's not a big deal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I might not be getting what you're saying but if we
add some server-side option that only applies to multiop start workflow
we would at least be able to add as a top-level field here:
type UpdateWithStartWorkflowOptions struct {
StartWorkflowOperation WithStartWorkflowOperation
UpdateOptions UpdateWorkflowOptions
}
56d5d61
to
5e6ea5c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly little stuff
// NewWithStartWorkflowOperation returns a WithStartWorkflowOperation to perform Update-with-Start. | ||
// Returns an error if the WorkflowIDConflictPolicy is not set, or if the workflow or arguments are invalid. | ||
// NOTE: Experimental | ||
NewWithStartWorkflowOperation(options StartWorkflowOptions, workflow interface{}, args ...interface{}) WithStartWorkflowOperation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(unresolved since I wanted to add a comment but it was resolved which disables the ability to discuss further)
it doesn't seem right to have to create a WithStartWorkflowOperationOptions struct in order to create a WithStartWorkflowOperation given that the latter essentially is just a stateful version of the former.
Creation methods of stateful things often accept options to create them and it helps us if later we need to add another option. I am ok if we all agree this isn't needed, but accepting an options object when creating something does save us from having a potential differently-named overload or adding mutation methods on the result later. I fear we will add some server-side option that only applies to multiop start workflow and we won't be able to represent it here.
Operation: "UpdateWithStartWorkflow", | ||
Name: in.UpdateName, | ||
Tags: map[string]string{workflowIDTagKey: in.WorkflowID, updateIDTagKey: in.UpdateID}, | ||
ToHeader: true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just out of curiosity, which header does this span get put on? Is it both the start request and the update request or just one?
@@ -416,6 +421,11 @@ type ClientUpdateWorkflowInput struct { | |||
WaitForStage WorkflowUpdateStage | |||
} | |||
|
|||
type ClientUpdateWithStartWorkflowInput struct { | |||
UpdateInput *ClientUpdateWorkflowInput | |||
StartWorkflowOperation WithStartWorkflowOperation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
May be worth noting that the interceptor can't do much with this. They can't even know what workflow it applies to. We don't have to do anything now, but I would expect at some point for interceptor authors to ask how to get details of the start the same way they can get details of the update.
internal/interceptor.go
Outdated
@@ -416,6 +421,11 @@ type ClientUpdateWorkflowInput struct { | |||
WaitForStage WorkflowUpdateStage | |||
} | |||
|
|||
type ClientUpdateWithStartWorkflowInput struct { | |||
UpdateInput *ClientUpdateWorkflowInput |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is input for another interceptor call, I don't think we should reuse it for this one. The interceptor input really just needs to be the values passed in by the user. Maybe something like:
type ClientUpdateWithStartWorkflowInput struct {
StartOptions *StartWorkflowOptions
StartWorkflowType string
StartWorkflowArgs []any
UpdateID string
UpdateName string
UpdateArgs []any
UpdateWaitForStage WorkflowUpdateStage
}
Or something like:
type ClientUpdateWithStartWorkflowInput struct {
StartOptions *StartWorkflowOptions
StartWorkflowType string
StartWorkflowArgs []any
UpdateOptions *UpdateWorkflowOptions
}
Or something like:
type ClientUpdateWithStartWorkflowInput struct {
UpdateOptions *UpdateWorkflowOptions
StartOperation WithStartWorkflowOperation
}
and add Options() StartWorkflowOptions
and WorkflowType() string
and WorkflowArgs() []any
to WithStartWorkflowOperation
interface.
(this is my only remaining discussion before marking approved, everything else LGTM or is non-blocking)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What problem are you trying to solve? This is how it's done in Java:
public WorkflowUpdateWithStartInput(
WorkflowStartInput workflowStartInput, StartUpdateInput<R> workflowUpdateInput) {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Each input type is only for the outer call being made, it is not reused in places where it may contain non-applicable fields (e.g. ClientUpdateWorkflowInput.RunID
which makes no sense here). The whole point is so that we can grow the interceptor as needed for just this call. This is different than our stance on reusing option types for callers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll note Java does reuse, but I think it is the only SDK that takes such an approach
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah right I see, thank you @Quinn-With-Two-Ns and @cretz for the suggested schemas. I've switched to
type ClientUpdateWithStartWorkflowInput struct {
UpdateOptions *UpdateWorkflowOptions
StartWorkflowOperation WithStartWorkflowOperation
}
// NewWithStartWorkflowOperation returns a WithStartWorkflowOperation to perform Update-with-Start. | ||
// Returns an error if the WorkflowIDConflictPolicy is not set, or if the workflow or arguments are invalid. | ||
// NOTE: Experimental | ||
NewWithStartWorkflowOperation(options StartWorkflowOptions, workflow interface{}, args ...interface{}) WithStartWorkflowOperation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We would be able to add such an option to UpdateWithStartWorkflowOptions.
Until we use this WithStartWorkflowOperation
for more than just update with start, which is why I figured it was named to not be related to update. But it's not a big deal.
New Update-With-Start API.
ExecuteWorkflow
, update-with-start is invoked via a new methodUpdateWithStartWorkflow
onClient
which returns anUpdateHandle
WithStartWorkflowOperation
struct which defines the start operation, and exposes a method to obtain the workflow run:The snippet below is from the accompanying sample: temporalio/samples-go#370: