-
Notifications
You must be signed in to change notification settings - Fork 229
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
EDU-3236: Update-with-Start #3120
base: main
Are you sure you want to change the base?
Conversation
3cada6c
to
c63df10
Compare
59a5b3a
to
2e44524
Compare
2e44524
to
065f3c8
Compare
Co-authored-by: Erica Sadun <[email protected]>
Co-authored-by: Erica Sadun <[email protected]>
Co-authored-by: Erica Sadun <[email protected]>
Co-authored-by: Erica Sadun <[email protected]>
Co-authored-by: Erica Sadun <[email protected]>
Co-authored-by: Erica Sadun <[email protected]>
Co-authored-by: Erica Sadun <[email protected]>
Co-authored-by: Erica Sadun <[email protected]>
Co-authored-by: Drew Hoskins <[email protected]>
Co-authored-by: Drew Hoskins <[email protected]>
@@ -300,7 +300,7 @@ If there's a Workflow running with the given Workflow Id, it will be signaled. I | |||
|
|||
Use the [`Client.SignalWithStartWorkflow`](https://pkg.go.dev/go.temporal.io/sdk/client#Client.SignalWithStartWorkflow) API to start a Workflow Execution (if not already running) and pass it the Signal at the same time. | |||
|
|||
Because the Workflow Execution might not exist, this API does not take a Run ID as a parameter | |||
Because the Workflow Execution might not exist, this API does not take a Run Id as a parameter |
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.
Confirmed correct.
@@ -316,12 +316,20 @@ if err != nil { | |||
|
|||
### Send an Update {#send-update-from-client} | |||
|
|||
:::tip Stability | |||
|
|||
In [Pre-release](/evaluate/development-production-features/release-stages#pre-release) (API is subject to change). |
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 needs to be updated to Public Preview. We do not release docs (as a rule) before then, so it should reflect the status when this material is ready for going live.
|
||
In [Pre-release](/evaluate/development-production-features/release-stages#pre-release) (API is subject to change). | ||
|
||
Minimum recommended [Temporal Server version 1.25](https://github.com/temporalio/temporal/releases/tag/v1.25.0) |
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.
Consider "Minimum Temporal Server version" unless there's a compelling reason otherwise to be less restrictive.
An Update is a synchronous, blocking call that can change Workflow state, control its flow, and return a result. | ||
|
||
A Client sending an Update must wait until the Server delivers the Update to a Worker. | ||
Workers must be available and responsive. | ||
Therefore, provide a context with a timeout to limit the time the client waits for a response. |
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.
Therefore, provide a context with a timeout to limit the time the client waits for a response. | |
Setting a timeout with a context provides a hard limit on how long a client will wait for a response. |
@@ -332,10 +340,16 @@ You must provide the Workflow Id, but specifying a Run Id is optional. | |||
If you supply only the Workflow Id (and provide an empty string as the Run Id param), the running Workflow Execution receives the Update. | |||
|
|||
You must provide a `WaitForStage` when calling `UpdateWorkflow()`. | |||
This parameter controls what stage the update must reach before a handle is returned to the caller. If `WaitForStage` is set to `WorkflowUpdateStageCompleted` the handle is returned after the update completes; if `WaitForStage` is set to `WorkflowUpdateStageAccepted` the handle is returned after the Update is accepted (i.e. after the validator has run, if there is a validator). | |||
This parameter controls what stage the update must reach before a handle is returned to the caller. |
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 parameter controls what stage the update must reach before a handle is returned to the caller. | |
This parameter controls the stage the update must reach before returning a handle to the caller: | |
- If `WaitForStage` is set to `WorkflowUpdateStageCompleted`, the handle is returned after the Update completes. | |
- If `WaitForStage` is set to `WorkflowUpdateStageAccepted`, the handle is returned after the Update is accepted and the Validator is run, if it's defined. | |
Note: You cannot send Updates to other Workflow Executions. | |
The following sample demonstrates how to create a context with timeout for sending an `Update` to the Workflow: | |
Or you might consider putting the note into an admonition if important enough.
if err != nil { | ||
log.Fatalf("Unable to get update result: %v", err) | ||
} | ||
``` | ||
|
||
#### Update-With-Start {#update-with-start} | ||
|
||
[Update-with-Start](/encyclopedia/workflow-message-passing#update-with-start) lets you send an Update that checks whether an already-running Workflow with that ID exists. |
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.
Suggestion:
[Update-with-Start](/encyclopedia/workflow-message-passing#update-with-start) lets you send an Update that checks whether an already-running Workflow with that ID exists:
- If the Workflow exists, the Update is processed.
- If the Workflow does not exist, a new Workflow Execution starts with the given ID, and the Update is processed immediately after.
Upon starting a new Workflow, it immediately processes the Update. | ||
|
||
To create a new Update operation, use [`client.NewUpdateWithStartWorkflowOperation`](https://pkg.go.dev/go.temporal.io/sdk/client#NewUpdateWithStartWorkflowOperation). | ||
The Workflow Id is optional - but when it is specified, it must match the one in `StartWorkflowOptions`. |
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.
The Workflow Id is optional - but when it is specified, it must match the one in `StartWorkflowOptions`. | |
The Workflow Id is optional. | |
When specified, the Id must match the one used in `StartWorkflowOptions`. |
|
||
To create a new Update operation, use [`client.NewUpdateWithStartWorkflowOperation`](https://pkg.go.dev/go.temporal.io/sdk/client#NewUpdateWithStartWorkflowOperation). | ||
The Workflow Id is optional - but when it is specified, it must match the one in `StartWorkflowOptions`. | ||
It is invalid to set the Run ID since there might not be running Workflow Execution. |
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.
It is invalid to set the Run ID since there might not be running Workflow Execution. | |
Since a running Workflow Execution may not already exist, you can't set a Run Id. |
The Workflow Id is optional - but when it is specified, it must match the one in `StartWorkflowOptions`. | ||
It is invalid to set the Run ID since there might not be running Workflow Execution. | ||
|
||
Use the `WithStartOperation` option to attach an Update Operation to the [`Client.ExecuteWorkflow`](https://pkg.go.dev/go.temporal.io/sdk/client#Client.ExecuteWorkflow) API call. |
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.
Use the `WithStartOperation` option to attach an Update Operation to the [`Client.ExecuteWorkflow`](https://pkg.go.dev/go.temporal.io/sdk/client#Client.ExecuteWorkflow) API call. | |
Use the `WithStartOperation` option to attach an Update Operation to the [`Client.ExecuteWorkflow`](https://pkg.go.dev/go.temporal.io/sdk/client#Client.ExecuteWorkflow) API call. | |
Not all `ExecuteWorkflow` options are allowed with Update-With-Start. | |
For example, specifying a Cron Schedule will result in an error. | |
For more details, refer to the [API documentation](https://pkg.go.dev/go.temporal.io/sdk/internal#StartWorkflowOptions). |
Refer to the [API documentation](https://pkg.go.dev/go.temporal.io/sdk/internal#StartWorkflowOptions) for further details. | ||
|
||
`ExecuteWorkflow` returns once the requested Update wait stage has been reached; or when a provided context times out. | ||
Choose [Workflow Id Conflict Policy](#workflow-id-conflict-policy) "Use Existing" coupled with an indempotent Update handler by default to allow the code to be executed again, in case of client failure. |
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.
Choose [Workflow Id Conflict Policy](#workflow-id-conflict-policy) "Use Existing" coupled with an indempotent Update handler by default to allow the code to be executed again, in case of client failure. | |
By default, choose the [Workflow Id Conflict Policy](#workflow-id-conflict-policy) "Use Existing" and use an idempotent Update handler. | |
This ensures your code can be executed again in case of a Client failure. |
`ExecuteWorkflow` returns once the requested Update wait stage has been reached; or when a provided context times out. | ||
Choose [Workflow Id Conflict Policy](#workflow-id-conflict-policy) "Use Existing" coupled with an indempotent Update handler by default to allow the code to be executed again, in case of client failure. | ||
|
||
You need a [`WorkflowUpdateHandle`](https://pkg.go.dev/go.temporal.io/sdk/client#WorkflowUpdateHandle) to retrieve a result. |
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.
You need a [`WorkflowUpdateHandle`](https://pkg.go.dev/go.temporal.io/sdk/client#WorkflowUpdateHandle) to retrieve a result. | |
Use [`WorkflowUpdateHandle`](https://pkg.go.dev/go.temporal.io/sdk/client#WorkflowUpdateHandle) to retrieve a result from the Update. |
Call `Get` on the Update operation. | ||
|
||
`UpdateWithStartWorkflowOperation` can only be executed once. | ||
Re-using a previously executed operation returns an error from `ExecuteWorkflow`. |
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.
Nice.
`UpdateWithStartWorkflowOperation` can only be executed once. | ||
Re-using a previously executed operation returns an error from `ExecuteWorkflow`. | ||
|
||
The following example shows the creation, configuration, and use of UpdateWithStart: |
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.
Also, very nice.
|
||
::: | ||
|
||
Update-With-Start lets you send an Update that checks whether an already-running Workflow with that ID exists. |
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.
Update-With-Start lets you send an Update that checks whether an already-running Workflow with that ID exists. | |
Update-With-Start sends an Update that checks whether an already-running Workflow with that ID exists. |
Update-With-Start lets you send an Update that checks whether an already-running Workflow with that ID exists. | ||
If it does, the Update is processed. | ||
If not, it starts a new Workflow Execution with the supplied ID. | ||
Upon starting a new Workflow, it immediately processes the Update. |
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.
Upon starting a new Workflow, it immediately processes the Update. | |
When starting a new Workflow, it immediately processes the Update. |
If not, it starts a new Workflow Execution with the supplied ID. | ||
Upon starting a new Workflow, it immediately processes the Update. | ||
|
||
Update-With-Start is great for latency-sensitive use cases, including the following examples: |
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.
Update-With-Start is great for latency-sensitive use cases, including the following examples: | |
Update-With-Start is great for latency-sensitive use cases: |
- **Lazy Initialization** - | ||
Instead of making separate Start Workflow and Update Workflow calls, Update-With-Start allows you to send them together in a single roundtrip. | ||
For example, a shopping cart can be modelled using Update-With-Start. | ||
Add or remove an item with an Update. |
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.
Add or remove an item with an Update. | |
Updates let you add and remove items from the cart. |
Instead of making separate Start Workflow and Update Workflow calls, Update-With-Start allows you to send them together in a single roundtrip. | ||
For example, a shopping cart can be modelled using Update-With-Start. | ||
Add or remove an item with an Update. | ||
Update-With-Start ensures the cart (the Workflow Execution) is created first before applying the Update (state change of items within the cart). |
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.
Update-With-Start ensures the cart (the Workflow Execution) is created first before applying the Update (state change of items within the cart). | |
Update-With-Start lets the customer start shopping, whether the cart already exists or they've just started shopping. | |
It ensures the cart, modeled by a Workflow Execution, is created before applying any Update that changes the state of items within the cart. |
Update-With-Start ensures the cart (the Workflow Execution) is created first before applying the Update (state change of items within the cart). | ||
- **Early Return** - | ||
Using Update-With-Start can begin a new Workflow Execution and synchronously receiving a response while the Workflow Execution continues to run to completion. | ||
For example, a payment process can be modelled using Update-With-Start. |
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.
For example, a payment process can be modelled using Update-With-Start. | |
For example, you might model a payment process using Update-With-Start. |
- **Early Return** - | ||
Using Update-With-Start can begin a new Workflow Execution and synchronously receiving a response while the Workflow Execution continues to run to completion. | ||
For example, a payment process can be modelled using Update-With-Start. | ||
You can send the result of payment validation back to the client synchronously, while continuing to complete or rollback the transaction asynchronously. |
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.
You can send the result of payment validation back to the client synchronously, while continuing to complete or rollback the transaction asynchronously. | |
Whether the payment completes or rolls back, you can send the payment validation results back to the client synchronously, while attempting the transaction asynchronously. |
Close?
For example, a payment process can be modelled using Update-With-Start. | ||
You can send the result of payment validation back to the client synchronously, while continuing to complete or rollback the transaction asynchronously. | ||
|
||
:::caution |
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 love this admonition.
:::caution | ||
|
||
Unlike Signal-with-Start - Update-With-Start is *not* atomic. | ||
If the Update cannot be delivered, for example, when no Worker is running, the Workflow Execution is still started. |
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.
If the Update cannot be delivered, for example, when no Worker is running, the Workflow Execution is still started. | |
If the Update can't be delivered, for example, say that there's no running Worker available, a new Workflow Execution will still start. |
What does this PR do?
Adds documentation for the Update-with-Start feature as well as its Go SDK usage.