diff --git a/features/deployment_versioning/upgrade_on_continue_as_new/README.md b/features/deployment_versioning/upgrade_on_continue_as_new/README.md new file mode 100644 index 00000000..a4f5f6af --- /dev/null +++ b/features/deployment_versioning/upgrade_on_continue_as_new/README.md @@ -0,0 +1,17 @@ +# Upgrade on Continue-as-New + +This snippet demonstrates how a pinned Workflow can upgrade to a new Worker Deployment Version at Continue-as-New boundaries. + +## Pattern + +Long-running Workflows that use Continue-as-New can upgrade to newer Worker Deployment Versions without patching by: + +1. Checking `GetContinueAsNewSuggested()` periodically +2. Looking for `ContinueAsNewSuggestedReasonTargetWorkerDeploymentVersionChanged` +3. Using `ContinueAsNewVersioningBehaviorAutoUpgrade` when continuing + +## Use Cases + +- Entity Workflows running for months or years +- Batch processing Workflows that checkpoint with Continue-as-New +- AI agent Workflows with long sleeps waiting for user input diff --git a/features/deployment_versioning/upgrade_on_continue_as_new/feature.go b/features/deployment_versioning/upgrade_on_continue_as_new/feature.go new file mode 100644 index 00000000..8a8da134 --- /dev/null +++ b/features/deployment_versioning/upgrade_on_continue_as_new/feature.go @@ -0,0 +1,46 @@ +package upgrade_on_continue_as_new + +import ( + "time" + + "go.temporal.io/sdk/workflow" +) + +// @@@SNIPSTART upgrade-on-continue-as-new-go +// ContinueAsNewWithVersionUpgrade demonstrates how a pinned Workflow can +// upgrade to a new Worker Deployment Version at Continue-as-New boundaries. +// The Workflow checks for the TARGET_WORKER_DEPLOYMENT_VERSION_CHANGED reason +// and uses AutoUpgrade behavior to move to the new version. +func ContinueAsNewWithVersionUpgrade(ctx workflow.Context, attempt int) (string, error) { + if attempt > 0 { + // After continuing as new, return the version + return "v1.0", nil + } + + // Check continue-as-new-suggested periodically + for { + err := workflow.Sleep(ctx, 10*time.Millisecond) + if err != nil { + return "", err + } + + if info := workflow.GetInfo(ctx); info.GetContinueAsNewSuggested() { + for _, reason := range info.GetContinueAsNewSuggestedReasons() { + if reason == workflow.ContinueAsNewSuggestedReasonTargetWorkerDeploymentVersionChanged { + // A new Worker Deployment Version is available + // Continue-as-New with upgrade to the new version + return "", workflow.NewContinueAsNewErrorWithOptions( + ctx, + workflow.ContinueAsNewErrorOptions{ + InitialVersioningBehavior: workflow.ContinueAsNewVersioningBehaviorAutoUpgrade, + }, + "ContinueAsNewWithVersionUpgrade", + attempt+1, + ) + } + } + } + } +} + +// @@@SNIPEND