Skip to content

Commit

Permalink
Update-with-Start incompatible options
Browse files Browse the repository at this point in the history
  • Loading branch information
stephanos committed Oct 27, 2024
1 parent dfd062f commit 2e44524
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 2 deletions.
41 changes: 41 additions & 0 deletions docs/develop/go/message-passing.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,47 @@ if err != nil {
}
```

#### Update-With-Start {#update-with-start}

Sending an Update-With-Start, if there is a running Workflow with the given Workflow Id, it will process the Update. Otherwise, a new Workflow starts and immediately processes the Update.

Use the [`client.NewUpdateWithStartWorkflowOperation`](https://pkg.go.dev/go.temporal.io/sdk/client#NewUpdateWithStartWorkflowOperation) API to create a new Update Operation. The `WorkflowID` option is optional; and it is invalid to set the `RunID` option.

Then, use the `WithStartOperation` option to attach the Update Operation to the [`Client.ExecuteWorkflow`](https://pkg.go.dev/go.temporal.io/sdk/client#Client.ExecuteWorkflow) API call. Note that not all `ExecuteWorkflow` options are allowed for Update-With-Start, for example specifying a `CronSchedule` with result in an error. Refer to the API documentation for details.

The `ExecuteWorkflow` call will return once an Update result is available; or when the provided context times out. To obtain the Update result, first obtain a [`WorkflowUpdateHandle`](https://pkg.go.dev/go.temporal.io/sdk/client#WorkflowUpdateHandle) by calling `Get` on the Update operation.

Note that an `UpdateWithStartWorkflowOperation` can only be executed once. Re-using a previously executed operation returns an error from `ExecuteWorkflow`.

```go
updateOperation := client.NewUpdateWithStartWorkflowOperation(
client.UpdateWorkflowOptions{
UpdateName: message.SetLanguageUpdate,
WaitForStage: client.WorkflowUpdateStageCompleted,
})

workflowOptions := client.StartWorkflowOptions{
ID: "some-workflow-id",
TaskQueue: "some-task-queue",
WithStartOperation: updateOperation, // attaches the Update to the Workflow Start
}
we, err := c.ExecuteWorkflow(context.Background(), workflowOptions, MyWorkflow)
if err != nil {
log.Fatalf("Unable to execute workflow: %v", err)
}

updateHandle, err := updateOperation.Get(context.Background())
if err != nil {
log.Fatalf("Unable to obtain update handle: %v", err)
}

var previousLang message.Language
err = updateHandle.Get(context.Background(), &previousLang)
if err != nil {
log.Fatalf("Unable to obtain update result: %v", err)
}
```

## Message handler patterns {#message-handler-patterns}

This section covers common write operations, such as Signal and Update handlers.
Expand Down
8 changes: 8 additions & 0 deletions docs/develop/java/message-passing.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,14 @@ Pass method names instead of method objects to:
:::
#### Update-With-Start {#update-with-start}
[TODO: wait for Go]
```java
...
```
## Message handler patterns {#message-handler-patterns}
This section covers common write operations, such as Signal and Update handlers.
Expand Down
23 changes: 21 additions & 2 deletions docs/encyclopedia/application-message-passing.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,11 @@ keywords:
- temporal sdk message passing
---




import PrettyImage from '@site/src/components/pretty-image/PrettyImage';
import { RelatedReadContainer, RelatedReadItem } from '@site/src/components/related-read/RelatedRead';
import {RelatedReadContainer, RelatedReadItem} from '@site/src/components/related-read/RelatedRead';

Workflows can be thought of as stateful web services that can receive messages.
The Workflow can have powerful message handlers akin to endpoints that react to the incoming messages in combination with the current state of the Workflow.
Expand All @@ -53,7 +56,7 @@ Use Signals instead of Updates when:
- The Workflow's clients want to quickly move on after sending an asynchronous message.
- The clients care more about the latency of sending the message than they do about the latency of the end-to-end operation.
- The clients don't want to rely on the Worker being available.
- Clients need to [Signal-With-Start](#signal-with-start) atomically (since there is currently no Update-with-Start operation.)
- Clients need to [Signal-With-Start](#signal-with-start) atomically (since Update-with-Start is not atomic).

Use Updates instead of Signals when:

Expand Down Expand Up @@ -177,6 +180,22 @@ If you want to send an Update to another Workflow such as a Child Workflow from
<RelatedReadItem path="/develop/dotnet/message-passing#send-update-from-client" text="Send Updates in .NET" archetype="feature-guide" />
</RelatedReadContainer>

#### Update-With-Start {#update-with-start}

Sending an Update-With-Start, if there is a running Workflow Execution with the given Workflow Id, it will process the Update. Otherwise, a new Workflow Execution starts and immediately processes the Update.

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 to send them together in a single roundtrip. For example, a shopping cart can be modelled using Update-With-Start: Adding or removing an item with an Update; ensuring the cart is created first before applying the Update.
- **Early Return** - Starting a new Workflow Execution and synchronously receiving a response mid-Workflow, while the Workflow Execution continues to run to completion. For example, a payment process can be modelled using Update-With-Start: Sending the result of the payment validation back to the client synchronously, and continuing to complete or rollback the transaction asynchronously.

It is important to note that - unlike Signal-with-Start - Update-With-Start is *not* atomic. That means if the Update cannot be delievered - for example, when no Worker is running - the Workflow Execution is still started. The SDKs will retry the Update-With-Start request; but there is no gurantee that it will succeed.

<RelatedReadContainer>
<RelatedReadItem path="/develop/go/message-passing#update-with-start" text="Update-With-Start with the Go SDK" archetype="feature-guide" />
<RelatedReadItem path="/develop/java/message-passing#update-with-start" text="Update-With-Start with the Java SDK" archetype="feature-guide" />
</RelatedReadContainer>

### Sending Queries {#sending-queries}

Queries can be sent from a Temporal Client or the Temporal CLI to a Workflow Execution--even if this Workflow has Completed. This call is synchronous and will call into the corresponding Query handler.
Expand Down
1 change: 1 addition & 0 deletions vale/styles/Temporal/terms.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ swap:
timer: Timer
timers: Timers
update: Update
update-with-start: Update-With-Start
worker entity: Worker Entity
worker process: Worker Process
worker program: Worker Program
Expand Down

0 comments on commit 2e44524

Please sign in to comment.