|
2 | 2 | id: continue-as-new |
3 | 3 | title: Continue-As-New - Go SDK |
4 | 4 | sidebar_label: Continue-As-New |
| 5 | +description: Learn how to use Temporal's Continue-As-New in Go to manage large Event Histories by atomically creating new Workflow Executions with the same Workflow Id and fresh parameters. |
5 | 6 | toc_max_heading_level: 4 |
6 | 7 | keywords: |
7 | | - - continue-as-new |
| 8 | + - continue-as-new workflow |
| 9 | + - restart workflow |
| 10 | + - fresh event history |
| 11 | + - avoid large event histories |
| 12 | + - temporal go continue-as-new |
8 | 13 | tags: |
9 | 14 | - Workflows |
10 | 15 | - continue-as-new |
11 | 16 | - Go SDK |
12 | 17 | - Temporal SDKs |
13 | | -description: Continue-As-New in Temporal allows a Workflow Execution to close and start a new one with the same Workflow Id, new Run Id, and fresh Event History to manage large Event Histories. |
14 | 18 | --- |
15 | 19 |
|
16 | | -[Continue-As-New](/workflow-execution/continue-as-new) enables a Workflow Execution to close successfully and create a new Workflow Execution in a single atomic operation if the number of Events in the Event History is becoming too large. |
17 | | -The Workflow Execution spawned from the use of Continue-As-New has the same Workflow Id, a new Run Id, and a fresh Event History and is passed all the appropriate parameters. |
| 20 | +This page answers the following questions for Go developers: |
| 21 | + |
| 22 | +- [What is Continue-As-New?](#what) |
| 23 | +- [How to Continue-As-New?](#how) |
| 24 | +- [When is it right to Continue-as-New?](#when) |
| 25 | +- [How to test Continue-as-New?](#how-to-test) |
| 26 | + |
| 27 | +## What is Continue-As-New? {#what} |
| 28 | + |
| 29 | +[Continue-As-New](/workflow-execution/continue-as-new) lets a Workflow Execution close successfully and creates a new Workflow Execution. |
| 30 | +You can think of it as a checkpoint when your Workflow gets too long or approaches certain scaling limits. |
| 31 | + |
| 32 | +The new Workflow Execution is in the same [chain](/workflow-execution#workflow-execution-chain); it keeps the same Workflow Id but gets a new Run Id and a fresh Event History. |
| 33 | +It also receives your Workflow's usual parameters. |
18 | 34 |
|
19 | | -To cause a Workflow Execution to [Continue-As-New](/workflow-execution/continue-as-new), the Workflow API should return the result of the [`NewContinueAsNewError()`](https://pkg.go.dev/go.temporal.io/sdk/workflow#NewContinueAsNewError) function available from the `go.temporal.io/sdk/workflow` package. |
| 35 | +## How to Continue-As-New using the Go SDK {#how} |
20 | 36 |
|
| 37 | +First, design your Workflow parameters so that you can pass in the "current state" when you Continue-As-New into the next Workflow run. |
| 38 | +This state is typically set to `None` for the original caller of the Workflow. |
| 39 | + |
| 40 | +<div class="copycode-notice-container"> |
| 41 | + <a href="https://github.com/temporalio/samples-go/blob/main/safe_message_handler/workflow.go"> |
| 42 | + View the source code |
| 43 | + </a>{' '} |
| 44 | + in the context of the rest of the application code. |
| 45 | +</div> |
21 | 46 | ```go |
22 | | -func SimpleWorkflow(ctx workflow.Context, value string) error { |
23 | | - ... |
24 | | - return workflow.NewContinueAsNewError(ctx, SimpleWorkflow, value) |
| 47 | +ClusterManagerInput struct { |
| 48 | + State *ClusterManagerState |
| 49 | + TestContinueAsNew bool |
25 | 50 | } |
26 | | -``` |
27 | 51 |
|
28 | | -To check whether a Workflow Execution was spawned as a result of Continue-As-New, you can check if `workflow.GetInfo(ctx).ContinuedExecutionRunID` is not empty (i.e. `""`). |
| 52 | +func newClusterManager(ctx workflow.Context, wfInput ClusterManagerInput) (*ClusterManager, error) { |
| 53 | + |
| 54 | +```` |
| 55 | +The test hook in the above snippet is covered [below](#how-to-test). |
29 | 56 |
|
30 | | -**Notes** |
| 57 | +Inside your Workflow, return the [`NewContinueAsNewError`](https://pkg.go.dev/go.temporal.io/sdk/workflow#NewContinueAsNewError) error. |
| 58 | +This stops the Workflow right away and starts a new one. |
| 59 | + |
| 60 | +<div class="copycode-notice-container"> |
| 61 | + <a href="https://github.com/temporalio/samples-go/blob/main/safe_message_handler/workflow.go"> |
| 62 | + View the source code |
| 63 | + </a>{' '} |
| 64 | + in the context of the rest of the application code. |
| 65 | +</div> |
| 66 | +```go |
| 67 | +return ClusterManagerResult{}, workflow.NewContinueAsNewError( |
| 68 | + ctx, |
| 69 | + ClusterManagerWorkflow, |
| 70 | + ClusterManagerInput{ |
| 71 | + State: &cm.state, |
| 72 | + TestContinueAsNew: cm.testContinueAsNew, |
| 73 | + }, |
| 74 | +) |
| 75 | +```` |
31 | 76 |
|
32 | | -- To prevent Signal loss, be sure to perform an asynchronous drain on the Signal channel. |
33 | | - Failure to do so can result in buffered Signals being ignored and lost. |
34 | | -- Make sure that the previous Workflow and the Continue-As-New Workflow are referenced by the same alias. |
35 | | - Failure to do so can cause the Workflow to Continue-As-New on an entirely different Workflow. |
| 77 | +### Considerations for Workflows with Message Handlers {#with-message-handlers} |
36 | 78 |
|
37 | | -:::warning Using Continue-as-New and Updates |
| 79 | +If you use Updates or Signals, don't call Continue-as-New from the handlers. |
| 80 | +Instead, wait for your handlers to finish in your main Workflow before you return `NewContinueAsNewError`. |
| 81 | +See the [`AllHandlersFinished`](message-passing#wait-for-message-handlers) example for guidance. |
38 | 82 |
|
39 | | -- Temporal _does not_ support Continue-as-New functionality within Update handlers. |
40 | | -- Complete all handlers _before_ using Continue-as-New. |
41 | | -- Use Continue-as-New from your main Workflow Definition method, just as you would complete or fail a Workflow Execution. |
| 83 | +## When is it right to Continue-as-New using the Go SDK? {#when} |
42 | 84 |
|
43 | | -::: |
| 85 | +Use Continue-as-New when your Workflow might hit [Event History Limits](/workflow-execution/event#event-history). |
| 86 | +
|
| 87 | +Temporal tracks your Workflow's progress against these limits to let you know when you should Continue-as-New. |
| 88 | +Call `GetInfo(ctx).GetContinueAsNewSuggested()` to check if it's time. |
| 89 | +
|
| 90 | +## How to test Continue-as-New using the Go SDK {#how-to-test} |
| 91 | +
|
| 92 | +Testing Workflows that naturally Continue-as-New may be time-consuming and resource-intensive. |
| 93 | +Instead, add a test hook to check your Workflow's Continue-as-New behavior faster in automated tests. |
| 94 | +
|
| 95 | +For example, when `TestContinueAsNew == True`, this sample creates a test-only variable called `maxHistoryLength` and sets it to a small value. |
| 96 | +A helper method in the Workflow checks it each time it considers using Continue-as-New: |
| 97 | +
|
| 98 | +<div class="copycode-notice-container"> |
| 99 | + <a href="https://github.com/temporalio/samples-go/blob/main/safe_message_handler/workflow.go"> |
| 100 | + View the source code |
| 101 | + </a>{' '} |
| 102 | + in the context of the rest of the application code. |
| 103 | +</div> |
| 104 | +
|
| 105 | +```go |
| 106 | +func (cm *ClusterManager) shouldContinueAsNew(ctx workflow.Context) bool { |
| 107 | + if workflow.GetInfo(ctx).GetContinueAsNewSuggested() { |
| 108 | + return true |
| 109 | + } |
| 110 | + if cm.maxHistoryLength > 0 && workflow.GetInfo(ctx).GetCurrentHistoryLength() > cm.maxHistoryLength { |
| 111 | + return true |
| 112 | + } |
| 113 | + return false |
| 114 | +} |
| 115 | +``` |
0 commit comments