Documentation
¶
Overview ¶
Package runtime evaluates durable workflow decisions against recorded history.
A workflow handler schedules named activities, timers and signal receives. Schedule multiple futures before calling Get to allow parallel execution. Get returns a saved result or yields the decision until an outcome arrives. The handler then runs again from its beginning. Now advances from run creation through the outcomes consumed by Get or Select, without consulting a worker clock.
You must keep workflow code deterministic. Use activity handlers for network, filesystem, database and other external work. Do not use goroutines, channels, map iteration order, random values, wall clocks, deferred effects or recovered control-flow panics in a workflow handler. Ordinary Go code cannot be sandboxed by this API. Command validation detects changed recorded decisions; it cannot prevent arbitrary Go code from performing an external effect itself.
Activity execution has at-least-once semantics. An activity may reach an external service before its result is recorded. Use its stable execution and command identity as an external idempotency key where the service supports it. Completing a workflow without waiting for a future abandons that pending work.
Return nil, w.ContinueAsNew(input, options) to close this run and atomically start its successor. Return the intent directly and make no later SDK calls. Empty routing options inherit the source; a nil RunTimeout inherits its saved duration, while a pointer to zero removes the run limit. The chain retains its absolute execution deadline. Unread signals follow the chain with their original acceptance identities. Pending tasks are fenced and child-close policies apply. The successor does not adopt the source's child futures. A child that continues remains one invocation to its original parent until the chain finally closes. Historical queries of a continued run reconstruct its saved decisions without creating another successor.
Set StartRequest.RetryPolicy or ChildOptions.RetryPolicy to opt into whole-workflow retries. Nil and entirely zero policies keep retries disabled. A configured policy defaults to a 1s initial interval, coefficient 2, a 100x maximum interval and unlimited attempts. MaximumAttempts includes the first run. NonRetryableTypes and ApplicationError.NonRetryable make failures final. Accepted cancellation, termination and execution timeout also prevent retries; run timeout may retry.
Each retry retains the failed/timed-out source and atomically creates a delayed successor with the same input, type, build and queue. Unread signals follow it; consumed signals and completed activity results stay in the source history. Whole-workflow retries can repeat external effects, so choose idempotency keys that cover the business operation across runs. Child futures wait for the chain's final result. Timeout coordinators need no registered workflow handler.
RunInfo exposes saved lineage and RetryAttempt. ContinueAsNew resets that attempt to one; RunNumber includes both retries and continuations. Now starts at saved run availability, so retry backoff is excluded from the run timeout but counts against the unchanged execution deadline. No retry starts at or after that limit.
A version 2 activity with a finite deadline can call ActivityInfo.DeferCompletion before delivering its handle to an external service. A confirmed handoff stops worker renewal and suppresses later handler results, including panics. Complete it through Worker.CompleteAsyncActivity, or report progress through Worker.HeartbeatAsyncActivity with consecutive sequences. Keep each request ID and its contents stable when retrying an unknown response. Completion applies the recorded retry policy; a retried attempt has a new callback credential.
AsyncActivityHandle is a credential. JSON includes its secret for delivery; ordinary formatting redacts it. Keep the handle immutable, coordinate heartbeat sequences between producers, and authorize callers before exposing callback methods remotely. A crash before handle delivery leaves an orphaned handoff which recovers through its persisted deadline. Memory is for development and tests; use a qualified persistent execution store for restart recovery. An uncertain sent handoff suspends ordinary worker heartbeats with ErrHandoffPending. Retry DeferCompletion to recover its original handle. Renewal also reconciles that saved request before using the old worker token; a cancelled request that stayed unsent is never retried in the background.
ReceiveSignal returns a future for one message of a given name. Give each receive a stable command ID. Messages are buffered in history, consumed in arrival order within their name, and assigned to a receive in its decision transaction. Repeated Get returns a copy of the same input. Now advances using the recorded message arrival time, even if consumption commits much later.
SignalExecution targets an explicit run or the current open run with an empty RunID. SignalWithStart atomically selects an open run or creates the proposed run first. Request IDs are unique across both operations within one namespace and workflow ID. Retry the whole original request to recover its original receipt, including after a replacement run starts. A receipt confirms durable acceptance. Your workflow decides whether to consume all signals before closing. Callback clients need the pinned namespace/build, but no registered handlers. SignalWithStart proposals must fit the Go runtime's queue/type limits, even when those fields are unused because an existing run wins.
Select races 1 through 1000 distinct futures from the current evaluation. Give each call a stable command ID. It returns the original winning future, consumes its signal if applicable and advances Now. Get then returns its copied result or recorded failure. New choices follow availability event sequence, with candidate order breaking shared-signal ties. Replay uses the saved winner. The ordered candidates and winner commit with the workflow decision. Selection does not cancel losing work or create a polled task. For a draining loop, remove each winner from your candidate slice; ready futures can otherwise win again.
Cancel requests cancellation of an activity, timer or signal receive. Wait on its returned future for durable acknowledgment, then use errors.Is with ErrCancelled on the target's Get result. A winning completion remains intact. CancelledError carries copied attempt/heartbeat progress when available. Cancel fences task results and preserves unused signals. It cannot undo an external effect or prove that a running external operation physically stopped. A running handler observes lost ownership through renewal or heartbeats.
RequestCancelExecution accepts whole-workflow cancellation with an explicit run or an empty RunID for the current open run. Retry the original request to recover its receipt after closure or replacement. Acceptance leaves the run open. A later decision atomically fences old pending tasks and schedules cleanup.
Register SetCancellationHandler before your first command if it must handle cancellation accepted before the initial decision. Normal code replays from the history prefix before first acceptance; cleanup uses the same captured state with full history after the saved fence. Already-recorded results remain readable; unresolved normal activity, timer and receive futures return ErrWorkflowCancelled. Cleanup can use ordinary durable commands with IDs unique across both phases. Return ErrWorkflowCancelled to close cancelled, nil to complete, or another error to fail. Without a handler, the run closes cancelled. The first request controls the reason; later requests cannot replace it or restart cleanup. A handler registered beyond the frozen normal boundary cannot handle that request.
Register queries with SetQueryHandler before the workflow can yield. A query reads local state reconstructed by validated replay, then returns a copied result without committing that replay's decisions. QueryExecution requires an explicit run and pinned build. Completed, failed and cancelled runs remain queryable when their history matches the registered workflow code. QueryResult carries the persisted revision, sequence and lifecycle state for the history prefix used. An accepted signal can be visible to a query before a worker commits consumption.
Queries must return promptly and avoid external effects. SDK scheduling, Future.Get, Select, Cancel and handler registration are prohibited during a query, even if it recovers the runtime's control-flow panic. Now remains readable. Ordinary Go effects and blocking cannot be sandboxed. QueryExecution checks its context between reads and invocation phases, and after code returns; it does not launch an evaluator goroutine that could outlive cancellation. Input and output are each limited to 1 MiB. Query names contain at most 200 bytes.
Evaluate requires a complete history snapshot with at most 100,000 events for a running execution, or 101,000 for a closed execution including its final decision. It accepts at most 999 new command, signal consumption, selection and cancellation acknowledgment events per decision, or 998 when a workflow retry policy is set to leave room for a store-owned retry link. Command IDs, names and queues contain at most 200 bytes. History format version 1 is explicit; unknown versions and event types fail evaluation so operators can supply compatible code. A panic or nondeterministic replay fails the task, not the execution.
Index ¶
- Constants
- Variables
- type ActivityAttempt
- type ActivityError
- type ActivityFunc
- type ActivityHandoff
- type ActivityInfo
- type ActivityOptions
- type ActivityTimeoutKind
- type ApplicationError
- type AsyncActivityHandle
- type AsyncCompletionRequest
- type AsyncHeartbeatRequest
- type Cancellation
- type CancellationStart
- type CancelledError
- type ChildCancellationFailure
- type ChildCommand
- type ChildOptions
- type ChildStartFailure
- type ChildWorkflowError
- type ClaimStatus
- type Command
- type Continuation
- type ContinueOptions
- type Decision
- type DrainHandle
- type DrainRequest
- type DrainResult
- type Future
- type HeartbeatCheckpoint
- type Options
- type Outcome
- type QueryFunc
- type QueryRequest
- type QueryResult
- type RetirementOptions
- type RetryPolicy
- type Selection
- type SignalConsumption
- type Worker
- func (w *Worker) BeginDrain(ctx context.Context, r DrainRequest) (DrainHandle, error)
- func (w *Worker) BeginDrainBeforeDeadline(ctx context.Context, r DrainRequest) (DrainHandle, error)
- func (w *Worker) CompleteAsyncActivity(ctx context.Context, client AsyncCompletionRequest) (durable.Receipt, error)
- func (w *Worker) HeartbeatAsyncActivity(ctx context.Context, client AsyncHeartbeatRequest) (durable.Receipt, error)
- func (w *Worker) QueryExecution(ctx context.Context, request QueryRequest) (QueryResult, error)
- func (w *Worker) Readiness(ctx context.Context) (WorkerReadiness, error)
- func (w *Worker) RequestCancelExecution(ctx context.Context, request durable.CancelExecutionRequest) (durable.CancelExecutionReceipt, error)
- func (w *Worker) Run(ctx context.Context) (result error)
- func (w *Worker) RunOnce(ctx context.Context, kind durable.TaskKind) (worked bool, err error)
- func (w *Worker) ServesBuild(namespace, build string) bool
- func (w *Worker) SignalExecution(ctx context.Context, request durable.SignalRequest) (durable.SignalReceipt, error)
- func (w *Worker) SignalWithStart(ctx context.Context, request durable.SignalWithStartRequest) (durable.SignalReceipt, error)
- func (w *Worker) SignalWithStartOutcome(ctx context.Context, request durable.SignalWithStartRequest) (durable.SignalStartOutcome, error)
- func (w *Worker) StartExecution(ctx context.Context, request durable.StartRequest) (durable.Receipt, error)
- func (w *Worker) Status() WorkerStatus
- func (w *Worker) Stop(ctx context.Context) error
- func (w *Worker) SupportsSignalStartOutcome() bool
- func (w *Worker) WaitDrain(ctx context.Context, handle DrainHandle) (DrainResult, error)
- type WorkerReadiness
- type WorkerState
- type WorkerStatus
- type Workflow
- func (w *Workflow) Activity(id, name, queue string, input []byte) *Future
- func (w *Workflow) ActivityWithOptions(id, name, queue string, input []byte, options ActivityOptions) *Future
- func (w *Workflow) Cancel(id string, target *Future) *Future
- func (w *Workflow) CancelChild(id string, target *Future) *Future
- func (w *Workflow) ChildWorkflow(id, name string, input []byte, options ChildOptions) *Future
- func (w *Workflow) ContinueAsNew(input []byte, options ContinueOptions) error
- func (w *Workflow) Now() time.Time
- func (w *Workflow) ReceiveSignal(id, name string) *Future
- func (w *Workflow) RunInfo() durable.RunMetadata
- func (w *Workflow) Select(id string, futures ...*Future) *Future
- func (w *Workflow) SetCancellationHandler(handler WorkflowCancellationFunc)
- func (w *Workflow) SetQueryHandler(name string, handler QueryFunc)
- func (w *Workflow) Timer(id string, delay time.Duration) *Future
- type WorkflowCancellationFunc
- type WorkflowCancelledError
- type WorkflowFunc
Constants ¶
const ( CommandChild durable.TaskKind = "child" CommandCancelChild durable.TaskKind = "cancel_child" TaskChildDelivery durable.TaskKind = "child_delivery" EventChildStartFailed = "workflow.child_start_failed" EventChildCancellationFailed = "workflow.child_cancellation_failed" EventWorkflowTimedOut = durable.EventWorkflowTimedOut FailureChildStartConflict = "child_start_conflict" )
const ( // EventCancellationStarted records the atomic fence before cleanup can run. EventCancellationStarted = "workflow.cancellation_started" // EventWorkflowCancelled records a terminal cancellation after cleanup. EventWorkflowCancelled = "workflow.cancelled" )
const ( EventSignalReceived = durable.EventSignalReceived EventSignalConsumed = durable.EventSignalConsumed )
Signal history separates durable acceptance from workflow consumption.
const ( EventStarted = "execution.started" EventCommandScheduled = "workflow.command_scheduled" EventWorkflowWaiting = "workflow.waiting" EventActivityCompleted = "activity.completed" EventActivityDeferred = "activity.deferred" EventActivityAttemptStarted = "activity.attempt_started" EventActivityAttemptFailed = "activity.attempt_failed" EventTimerFired = "timer.fired" EventWorkflowCompleted = "workflow.completed" EventWorkflowFailed = "workflow.failed" )
History event types understood by this version of the Go runtime.
const CommandCancel durable.TaskKind = "cancel"
CommandCancel requests a recorded cancellation without creating a polled task.
const CommandSelect durable.TaskKind = "select"
CommandSelect records an ordered set of futures without creating a polled task.
const CommandSignal durable.TaskKind = "signal"
CommandSignal records a receive operation. It never creates a polled task.
const EventContinuationRequested = "workflow.continuation_requested"
EventContinuationRequested captures the SDK decision before the store closes the run.
const EventFutureCancelled = "workflow.future_cancelled"
EventFutureCancelled acknowledges fencing or preserves an existing outcome.
const EventSelected = "workflow.selected"
EventSelected records the winning future in the workflow decision transaction.
const FailureWorkerLost = "activity_worker_lost"
FailureWorkerLost denotes an attempt whose grant expired without a result. The external operation may have succeeded; retries still require idempotency.
const TaskExecutionTimeout durable.TaskKind = "execution_timeout"
TaskExecutionTimeout polls expired runs independently of pinned workflow builds.
const TaskTimeout durable.TaskKind = "timeout"
TaskTimeout polls expired activity deadlines across queues in the worker's namespace and pinned build. It is a poller kind, not a scheduled task kind.
Variables ¶
var ( ErrChildStart = errors.New("durable runtime: child could not start") ErrChildCancelled = errors.New("durable runtime: child cancelled") ErrChildTerminated = errors.New("durable runtime: child terminated") ErrChildTimedOut = errors.New("durable runtime: child timed out") )
var ( ErrQueryNotFound = errors.New("durable runtime: query handler not registered at this snapshot") ErrQueryMutation = errors.New("durable runtime: workflow operations are forbidden in a query") ErrQueryPanic = errors.New("durable runtime: query handler panicked") )
Query errors distinguish absent registration, prohibited SDK use and panics.
var ( ErrNondeterministic = errors.New("durable runtime: workflow does not match history") ErrHistory = errors.New("durable runtime: invalid history") ErrWorkflowPanic = errors.New("durable runtime: workflow panicked") )
Evaluation errors leave the workflow task uncommitted for operator recovery.
var ( ErrWorkerStarted = errors.New("durable runtime: worker already started") ErrWorkerDraining = errors.New("durable runtime: worker claim admission closed") ErrDrainIncomplete = errors.New("durable runtime: drain incomplete") ErrDrainDeadline = errors.New("durable runtime: first drain acceptance deadline passed") // ErrClaimUnknown wraps a claim the store didn't answer, such as a // timeout. The task may be leased to this worker; it returns to the // queue when the lease expires. Run retries these claims with backoff. ErrClaimUnknown = errors.New("durable runtime: claim outcome unknown") )
var ErrCancelled = errors.New("durable runtime: future cancelled")
ErrCancelled identifies a future whose result was fenced by cancellation.
var ErrDeferralUnknown = errors.New("durable runtime: task deferral outcome unknown")
var ErrHandlerNotFound = errors.New("durable runtime: handler not registered")
ErrHandlerNotFound leaves a task available for a worker with compatible code.
var ErrHandoffPending = errors.New("durable runtime: asynchronous handoff response is unresolved")
ErrHandoffPending means worker heartbeats are suspended until an uncertain ownership transfer resolves. Retry DeferCompletion to recover its handle.
var ErrWorkflowCancelled = errors.New("durable runtime: workflow cancelled")
ErrWorkflowCancelled distinguishes run cancellation from individual futures.
Functions ¶
This section is empty.
Types ¶
type ActivityAttempt ¶
type ActivityAttempt struct {
Version int `json:"version"`
CommandID string `json:"command_id"`
Attempt int64 `json:"attempt"`
Epoch int64 `json:"epoch"`
Failure *ApplicationError `json:"failure,omitempty"`
RetryAfter time.Duration `json:"retry_after,omitempty"`
Timeout ActivityTimeoutKind `json:"timeout,omitempty"`
HeartbeatEnabled bool `json:"heartbeat_enabled,omitempty"`
Progress []byte `json:"progress,omitempty"`
Heartbeat *HeartbeatCheckpoint `json:"heartbeat,omitempty"`
}
ActivityAttempt records a logical attempt and the ownership epoch that started it. A failed record also stores the failure and chosen retry delay; zero is final.
type ActivityError ¶
type ActivityError struct {
Failure *ApplicationError
Attempt int64
Timeout ActivityTimeoutKind
Heartbeat *HeartbeatCheckpoint
}
ActivityError provides activity metadata while preserving ApplicationError through errors.As. The checkpoint returned to workflow code is a copy.
func (*ActivityError) Error ¶
func (e *ActivityError) Error() string
func (*ActivityError) Unwrap ¶
func (e *ActivityError) Unwrap() error
type ActivityFunc ¶
ActivityFunc performs external work under a renewable, fenced task lease. Observe cancellation, and make external effects idempotent using ActivityInfo.
type ActivityHandoff ¶
type ActivityHandoff struct {
Version int `json:"version"`
CommandID string `json:"command_id"`
Attempt int64 `json:"attempt"`
Epoch int64 `json:"epoch"`
Heartbeat *HeartbeatCheckpoint `json:"heartbeat"`
}
ActivityHandoff records transfer of one attempt without exposing credentials.
type ActivityInfo ¶
type ActivityInfo struct {
Key durable.Key
CommandID string
BuildID string
// Attempt counts durable starts for version 2 activities. Legacy activities
// expose the task claim count, which can include claims lost before execution.
Attempt int64
// contains filtered or unexported fields
}
ActivityInfo identifies an operation independently of its retry attempt.
func (ActivityInfo) DeferCompletion ¶
func (a ActivityInfo) DeferCompletion(ctx context.Context) (AsyncActivityHandle, error)
DeferCompletion durably hands this attempt to an external callback before returning its handle. A confirmed handoff suppresses subsequent handler results. Calling again during the handler returns the same handle. A finite persisted overall, attempt or heartbeat deadline is required. After an unknown response, retry to recover the handle. Renewal reconciles sent pending requests; ordinary heartbeats return ErrHandoffPending meanwhile.
func (ActivityInfo) Heartbeat ¶
func (a ActivityInfo) Heartbeat(ctx context.Context, details []byte) error
Heartbeat synchronously persists copied progress under this activity grant. An identical retry resolves its original receipt without extending it again.
func (ActivityInfo) HeartbeatDetails ¶
func (a ActivityInfo) HeartbeatDetails() []byte
HeartbeatDetails returns a copy of progress inherited from the previous attempt.
func (ActivityInfo) IdempotencyKey ¶
func (a ActivityInfo) IdempotencyKey() string
IdempotencyKey is stable across attempts, and distinct across runs/namespaces.
type ActivityOptions ¶
type ActivityOptions struct {
RetryPolicy *RetryPolicy `json:"retry_policy"`
ScheduleToStartTimeout time.Duration `json:"schedule_to_start_timeout,omitempty"`
StartToCloseTimeout time.Duration `json:"start_to_close_timeout,omitempty"`
ScheduleToCloseTimeout time.Duration `json:"schedule_to_close_timeout,omitempty"`
HeartbeatTimeout time.Duration `json:"heartbeat_timeout,omitempty"`
}
ActivityOptions are captured in command history before any attempt starts. Zero timeouts are disabled. Deadlines use store time and do not follow lease renewal.
type ActivityTimeoutKind ¶
type ActivityTimeoutKind string
ActivityTimeoutKind identifies the recorded deadline that ended an activity.
const ( TimeoutScheduleToStart ActivityTimeoutKind = "schedule_to_start" TimeoutStartToClose ActivityTimeoutKind = "start_to_close" TimeoutScheduleToClose ActivityTimeoutKind = "schedule_to_close" TimeoutHeartbeat ActivityTimeoutKind = "heartbeat" )
type ApplicationError ¶
type ApplicationError struct {
Type string `json:"type"`
Message string `json:"message"`
NonRetryable bool `json:"non_retryable,omitempty"`
}
ApplicationError is a recorded application failure. Type allows deterministic handling.
func (*ApplicationError) Error ¶
func (f *ApplicationError) Error() string
type AsyncActivityHandle ¶
type AsyncActivityHandle struct {
Version int `json:"version"`
Key durable.Key `json:"key"`
BuildID string `json:"build_id"`
Token durable.TaskToken `json:"token"`
Secret string `json:"secret"`
// InitialHeartbeatSequence is informational. Coordinate later sequences
// separately across callback producers; do not update this handle.
InitialHeartbeatSequence int64 `json:"initial_heartbeat_sequence"`
}
AsyncActivityHandle transfers callback authority for one activity attempt. Treat it as a credential. JSON carries the secret for explicit delivery; ordinary formatting redacts every field. Keep the handle immutable.
func (AsyncActivityHandle) GoString ¶
func (h AsyncActivityHandle) GoString() string
func (AsyncActivityHandle) String ¶
func (h AsyncActivityHandle) String() string
func (AsyncActivityHandle) Validate ¶
func (h AsyncActivityHandle) Validate() error
Validate checks the handle's shape. Stores verify its current authority.
type AsyncCompletionRequest ¶
type AsyncCompletionRequest struct {
Handle AsyncActivityHandle `json:"handle"`
RequestID string `json:"request_id"`
Output []byte `json:"output,omitempty"`
Failure *ApplicationError `json:"failure,omitempty"`
}
AsyncCompletionRequest completes or fails an asynchronous attempt. RequestID must stay stable on retries and be unique among result requests in the run. Output and Failure are mutually exclusive; an empty successful output is valid.
type AsyncHeartbeatRequest ¶
type AsyncHeartbeatRequest struct {
Handle AsyncActivityHandle
RequestID string
Sequence int64
Details []byte
}
AsyncHeartbeatRequest records consecutive progress. RequestID is unique among heartbeat requests in the run. Reuse the entire request after an unknown ACK.
type Cancellation ¶
type Cancellation struct {
Version int `json:"version"`
CommandID string `json:"command_id"`
TargetID string `json:"target_id"`
Cancelled bool `json:"cancelled"`
Attempt int64 `json:"attempt,omitempty"`
Heartbeat *HeartbeatCheckpoint `json:"heartbeat,omitempty"`
}
Cancellation is the persisted disposition of one cancellation command. Attempt and Heartbeat describe a newly canceled version 2 activity only.
type CancellationStart ¶
type CancellationStart struct {
Version int `json:"version"`
RequestID string `json:"request_id"`
CommandCount int64 `json:"command_count"`
}
CancellationStart binds task fencing to the saved normal-command boundary.
type CancelledError ¶
type CancelledError struct {
CommandID string
Attempt int64
Heartbeat *HeartbeatCheckpoint
}
CancelledError carries copied progress from a canceled activity, or zero metadata for a timer or receive. Storage fencing cannot undo external effects.
func (*CancelledError) Error ¶
func (e *CancelledError) Error() string
func (*CancelledError) Unwrap ¶
func (e *CancelledError) Unwrap() error
type ChildCancellationFailure ¶
type ChildCancellationFailure struct {
Version int `json:"version"`
CommandID string `json:"command_id"`
TargetID string `json:"target_id"`
Child durable.Key `json:"child"`
}
ChildCancellationFailure preserves an earlier creation failure. No child cancellation was accepted when the target execution could not be created.
type ChildCommand ¶
type ChildCommand struct {
RetryPolicy *durable.WorkflowRetryPolicy `json:"retry_policy,omitempty"`
Key durable.Key `json:"key"`
BuildID string `json:"build_id"`
ParentClosePolicy durable.ParentClosePolicy `json:"parent_close_policy"`
RunTimeout time.Duration `json:"run_timeout,omitempty"`
ExecutionTimeout time.Duration `json:"execution_timeout,omitempty"`
}
ChildCommand retains a child's exact identity and build across parent replay.
type ChildOptions ¶
type ChildOptions struct {
RetryPolicy *durable.WorkflowRetryPolicy
WorkflowID string
BuildID string
Queue string
ParentClosePolicy durable.ParentClosePolicy
RunTimeout time.Duration
ExecutionTimeout time.Duration
}
ChildOptions captures routing and parent-close behavior in the saved command. Empty build and queue inherit the parent. The default close policy terminates.
type ChildStartFailure ¶
type ChildStartFailure struct {
Version int `json:"version"`
CommandID string `json:"command_id"`
Child durable.Key `json:"child"`
Failure *ApplicationError `json:"failure"`
}
ChildStartFailure records a definitive conflict without adopting another run.
type ChildWorkflowError ¶
type ChildWorkflowError struct {
Child durable.Key
State durable.State
Failure *ApplicationError
Timeout *durable.ExecutionTimeout
}
ChildWorkflowError preserves the child identity, lifecycle and application cause. Empty State means creation failed before a child execution existed.
func (*ChildWorkflowError) Error ¶
func (e *ChildWorkflowError) Error() string
func (*ChildWorkflowError) Is ¶
func (e *ChildWorkflowError) Is(target error) bool
func (*ChildWorkflowError) Unwrap ¶
func (e *ChildWorkflowError) Unwrap() error
type ClaimStatus ¶
type ClaimStatus struct {
Kind durable.TaskKind
Claiming int64
Processing int64
Failures int64
FailingSince time.Time
}
ClaimStatus counts local calls, including claims awaiting a database response. Failures counts this kind's consecutive ErrClaimUnknown claims since FailingSince; both reset when one of its claims gets an answer.
type Command ¶
type Command struct {
Version int `json:"version"`
Index int64 `json:"index"`
ID string `json:"id"`
Kind durable.TaskKind `json:"kind"`
Name string `json:"name,omitempty"`
Queue string `json:"queue,omitempty"`
Input []byte `json:"input,omitempty"`
Delay time.Duration `json:"delay,omitempty"`
Deadline time.Time `json:"deadline,omitempty"`
ActivityOptions *ActivityOptions `json:"activity_options,omitempty"`
Candidates []string `json:"candidates,omitempty"`
TargetID string `json:"target_id,omitempty"`
Child *ChildCommand `json:"child,omitempty"`
}
Command records one decision before its associated task can execute. Index is one-based and monotonically increasing within a run.
type Continuation ¶
type Continuation struct {
Version int `json:"version"`
CommandCount int64 `json:"command_count"`
Options ContinueOptions `json:"options"`
Next durable.ContinueSpec `json:"next"`
}
Continuation records both caller options and resolved successor values. Queue is resolved from the source task when the caller leaves it empty.
type ContinueOptions ¶
type ContinueOptions struct {
WorkflowType string `json:"workflow_type,omitempty"`
BuildID string `json:"build_id,omitempty"`
Queue string `json:"queue,omitempty"`
RunTimeout *time.Duration `json:"run_timeout,omitempty"`
}
ContinueOptions selects the successor's routing and run timeout. Empty strings inherit the source. A nil timeout inherits; a pointer to zero removes the run limit. The chain's absolute execution deadline never changes.
type Decision ¶
type Decision struct {
Continuation *Continuation
Commands []Command
Signals []SignalConsumption
Selections []Selection
State durable.State
Output []byte
Failure *ApplicationError
CancellationStart *CancellationStart
Cancelled *durable.ExecutionCancellation
}
Decision contains new commands, signal consumptions and selections. Running means a future is unresolved. An evaluation error never returns a usable decision.
func Evaluate ¶
func Evaluate(execution durable.Execution, events []durable.Event, handler WorkflowFunc) (Decision, error)
Evaluate replays a complete history snapshot through LastSequence. It produces a decision without writing state or running activities. Errors must never be converted into successful workflow transitions by a caller.
type DrainHandle ¶
type DrainHandle struct {
RuntimeID string
DrainRequest
}
DrainHandle binds an accepted operation to one immutable Worker incarnation.
type DrainRequest ¶
DrainRequest fixes the operation deadline independently of any observer. Retrying an operation must preserve both fields.
type DrainResult ¶
type DrainResult struct {
Handle DrainHandle
Complete bool
DeadlineExpired bool
Quiescent bool
InFlight int64
UnknownClaims int64
ObservedAt time.Time
}
DrainResult separates the immutable operation outcome from current quiescence. Deadline expiry and unknown claims never become a successful drain on replay.
type Future ¶
type Future struct {
// contains filtered or unexported fields
}
Future represents a recorded command's eventual result. Get yields the workflow decision if its result has not been recorded.
type HeartbeatCheckpoint ¶
type HeartbeatCheckpoint struct {
At time.Time `json:"at"`
Epoch int64 `json:"epoch"`
Sequence int64 `json:"sequence"`
Details []byte `json:"details,omitempty"`
}
HeartbeatCheckpoint is the last persisted progress at an attempt's outcome. Sequence zero carries the progress inherited when the attempt started.
type Options ¶
type Options struct {
Retirement *RetirementOptions
Namespace string
Queue string
BuildID string
Owner string
// RuntimeID names one process incarnation. A replacement must use a new ID.
RuntimeID string
InstanceID string
LeaseDuration time.Duration
PollInterval time.Duration
StoreTimeout time.Duration
Concurrency int
Workflows map[string]WorkflowFunc
Activities map[string]ActivityFunc
// Telemetry receives the worker's spans and metrics: one root "process
// durable task" span per claimed task, and the task, poll and replay
// metrics. Nil starts spans on the global tracer provider and records no
// metrics. engine.WithDurableWorkflows fills it with the engine's own.
Telemetry *telemetry.Telemetry
}
Options pin a worker to a namespace, queue and build. Register all handlers before construction; NewWorker copies the maps. Concurrency is per task kind.
type Outcome ¶
type Outcome struct {
Version int `json:"version"`
CommandID string `json:"command_id"`
Attempt int64 `json:"attempt,omitempty"`
Timeout ActivityTimeoutKind `json:"timeout,omitempty"`
Output []byte `json:"output,omitempty"`
Failure *ApplicationError `json:"failure,omitempty"`
Heartbeat *HeartbeatCheckpoint `json:"heartbeat,omitempty"`
}
Outcome binds an activity result or timer firing to its scheduled command. Output and Failure are mutually exclusive.
type QueryFunc ¶
QueryFunc reads reconstructed workflow state. Return promptly without external effects or asynchronous workflow operations. Each call uses a fresh replay.
type QueryRequest ¶
type QueryRequest struct {
durable.Key
Selection durable.RunSelection `json:"selection,omitempty"`
BuildID string `json:"build_id"`
Name string `json:"name"`
Input []byte `json:"input,omitempty"`
}
QueryRequest selects an explicit, current or latest run and its pinned build. Queries are observations and do not use mutation request IDs or receipts.
func (QueryRequest) Validate ¶
func (r QueryRequest) Validate() error
Validate checks run selection, pinned build, query name and input bound.
type QueryResult ¶
type QueryResult struct {
durable.Key
State durable.State `json:"state"`
Revision int64 `json:"revision"`
LastSequence int64 `json:"last_sequence"`
Output []byte `json:"output,omitempty"`
}
QueryResult identifies the persisted snapshot used to reconstruct the answer. State describes that saved projection, even when replay observes a signal whose consumption has not yet been committed by a workflow worker.
func EvaluateQuery ¶
func EvaluateQuery(execution durable.Execution, events []durable.Event, handler WorkflowFunc, request QueryRequest) (QueryResult, error)
EvaluateQuery reconstructs a complete immutable history prefix and invokes a named query on its private workflow instance. It never returns a publishable decision or performs store operations. Arbitrary Go side effects and blocking cannot be sandboxed; keep query handlers read-only and prompt.
type RetirementOptions ¶
RetirementOptions opts into persisted deployment compatibility checks. Enrollment remains an explicit authorized store operation.
type RetryPolicy ¶
type RetryPolicy struct {
InitialInterval time.Duration `json:"initial_interval"`
BackoffCoefficient float64 `json:"backoff_coefficient"`
MaximumInterval time.Duration `json:"maximum_interval"`
MaximumAttempts int64 `json:"maximum_attempts"`
NonRetryableTypes []string `json:"non_retryable_types,omitempty"`
}
RetryPolicy governs failures across durable activity attempts. Zero fields use a 1s initial interval, coefficient 2, 100x maximum interval and unlimited attempts. MaximumAttempts includes the first attempt; 1 disables retries.
type Selection ¶
type Selection struct {
Version int `json:"version"`
CommandID string `json:"command_id"`
FutureID string `json:"future_id"`
}
Selection binds one stable selection command to its ready candidate.
type SignalConsumption ¶
type SignalConsumption = durable.SignalConsumption
SignalConsumption binds one accepted message to a stable receive command.
type Worker ¶
type Worker struct {
// contains filtered or unexported fields
}
Worker claims durable tasks. Multiple workers may share a queue and store.
func (*Worker) BeginDrain ¶
func (w *Worker) BeginDrain(ctx context.Context, r DrainRequest) (DrainHandle, error)
BeginDrain closes claim admission permanently. Its context only governs acceptance; the explicit operation deadline governs cancellation of work.
func (*Worker) BeginDrainBeforeDeadline ¶
func (w *Worker) BeginDrainBeforeDeadline(ctx context.Context, r DrainRequest) (DrainHandle, error)
BeginDrainBeforeDeadline refuses a first acceptance after the operation deadline. The refusal is synchronized with claim admission and leaves work untouched. An exact already accepted operation can still be recovered after its deadline.
func (*Worker) CompleteAsyncActivity ¶
func (w *Worker) CompleteAsyncActivity(ctx context.Context, client AsyncCompletionRequest) (durable.Receipt, error)
CompleteAsyncActivity publishes a result or failure using the saved retry policy. A compatible worker needs no activity handler. Accepted request IDs recover their original receipt after retry, timeout, state advancement or closure. This trusted Go API requires caller authorization before remote exposure.
func (*Worker) HeartbeatAsyncActivity ¶
func (w *Worker) HeartbeatAsyncActivity(ctx context.Context, client AsyncHeartbeatRequest) (durable.Receipt, error)
HeartbeatAsyncActivity persists external progress without renewing a worker lease. Callers coordinate consecutive sequences starting after the handle's initial sequence. An exact retry returns the original receipt after closure.
func (*Worker) QueryExecution ¶
func (w *Worker) QueryExecution(ctx context.Context, request QueryRequest) (QueryResult, error)
QueryExecution reads a consistent history prefix and invokes a query against compatible workflow code. It never claims a task or publishes a decision. The request needs a run selector and pinned build; the client's queue does not restrict reads. Authorize callers before exposing this method remotely.
func (*Worker) Readiness ¶
func (w *Worker) Readiness(ctx context.Context) (WorkerReadiness, error)
Readiness reads authoritative compatibility using a bounded store context. An unavailable observation never becomes a healthy readiness response.
func (*Worker) RequestCancelExecution ¶
func (w *Worker) RequestCancelExecution(ctx context.Context, request durable.CancelExecutionRequest) (durable.CancelExecutionReceipt, error)
RequestCancelExecution durably accepts cancellation on an explicit or current run. The receipt proves acceptance only. Authorize callers before exposing this trusted API remotely; repeat the whole request after an unknown response.
func (*Worker) Run ¶
Run polls each task kind until cancellation or the first processing error. Processing errors are returned to the supervisor, never silently discarded. A claim the store doesn't answer (ErrClaimUnknown) is retried with backoff and reported through Status, since nothing was processed and a task it may have taken returns to the queue when its lease expires. Cancellation leaves unfinished tasks for replacement workers after expiry.
func (*Worker) RunOnce ¶
RunOnce claims and processes at most one task. Worked is true after a claim, including when processing fails. It is safe to call concurrently.
func (*Worker) ServesBuild ¶
ServesBuild checks immutable routing without starting work or replaying history.
func (*Worker) SignalExecution ¶
func (w *Worker) SignalExecution(ctx context.Context, request durable.SignalRequest) (durable.SignalReceipt, error)
SignalExecution persists a signal without requiring a registered handler. Authorize callers before exposing this trusted Go API remotely. Retry with the entire original request when an acknowledgement is lost.
func (*Worker) SignalWithStart ¶
func (w *Worker) SignalWithStart(ctx context.Context, request durable.SignalWithStartRequest) (durable.SignalReceipt, error)
SignalWithStart atomically chooses or creates a run and accepts its signal. The proposed queue is used only for a new run. The callback worker's queue and handler registrations do not change the existing run's routing.
func (*Worker) SignalWithStartOutcome ¶
func (w *Worker) SignalWithStartOutcome(ctx context.Context, request durable.SignalWithStartRequest) (durable.SignalStartOutcome, error)
SignalWithStartOutcome retains recovery provenance through unknown-ACK retries. Stores without atomic provenance are unavailable to this remote-facing path.
func (*Worker) StartExecution ¶
func (w *Worker) StartExecution(ctx context.Context, request durable.StartRequest) (durable.Receipt, error)
StartExecution validates the worker's namespace/build and persists its first task. Reuse the entire request when the outcome of a start is unknown.
func (*Worker) Status ¶
func (w *Worker) Status() WorkerStatus
Status returns a private snapshot and never calls storage or user code.
func (*Worker) Stop ¶
Stop closes admission, cancels work and waits for actual call completion. A timed-out caller can wait again; it cannot force an uncooperative handler out.
func (*Worker) SupportsSignalStartOutcome ¶
SupportsSignalStartOutcome reports atomic acceptance provenance support.
func (*Worker) WaitDrain ¶
func (w *Worker) WaitDrain(ctx context.Context, handle DrainHandle) (DrainResult, error)
WaitDrain waits without changing the operation's deadline or cancellation.
type WorkerReadiness ¶
type WorkerReadiness struct {
Worker WorkerStatus
Ready bool
RetirementEnabled bool
RetirementStatus string
Compatibility durable.CompatibilityFacts
QueryRuntimeCapability bool
}
WorkerReadiness separates process polling from persisted deployment support. Query schema support does not establish a qualified host artifact or probe.
type WorkerState ¶
type WorkerState string
WorkerState describes polling lifecycle independently of database liveness.
const ( WorkerNotStarted WorkerState = "not_started" WorkerRunning WorkerState = "running" WorkerDraining WorkerState = "draining" WorkerStopped WorkerState = "stopped" WorkerFailed WorkerState = "failed" )
type WorkerStatus ¶
type WorkerStatus struct {
State WorkerState
Namespace, Queue, BuildID string
Owner, RuntimeID, InstanceID string
Ready, AdmissionClosed bool
InFlight int64
Claims []ClaimStatus
UnknownClaims int64
Failure string
// ClaimFailures is the longest run of ErrClaimUnknown claims among the
// task kinds, and ClaimFailingSince when the oldest current run began.
// Claims has each kind's own run.
ClaimFailures int64
ClaimFailingSince time.Time
Drain *DrainHandle
ObservedAt time.Time
}
WorkerStatus reports process facts. Zero local work does not prove a build has no persisted runs, callback grants, timers or child obligations.
type Workflow ¶
type Workflow struct {
// contains filtered or unexported fields
}
Workflow provides replayable decision primitives. Use these methods only from the handler's goroutine. Schedule multiple futures before Get for parallel work.
func (*Workflow) Activity ¶
Activity schedules an external operation. Empty queue uses the workflow queue. The ID must be unique within this run and stable when the handler is replayed.
func (*Workflow) ActivityWithOptions ¶
func (w *Workflow) ActivityWithOptions(id, name, queue string, input []byte, options ActivityOptions) *Future
ActivityWithOptions captures a retry policy in a version 2 activity command. Use this for new workflows; changing saved options is nondeterministic replay.
func (*Workflow) Cancel ¶
Cancel requests cancellation of an activity, timer or signal-receive future from this evaluation. Use a unique stable ID for each request. Wait on the returned future for persistence acknowledgment; it returns nil output/error whether cancellation fenced the target or an existing result was preserved. An acknowledgment does not prove an external operation physically stopped.
func (*Workflow) CancelChild ¶
CancelChild requests cancellation and returns a future for its acknowledgment. The child's own future remains pending until its actual terminal result arrives.
func (*Workflow) ChildWorkflow ¶
func (w *Workflow) ChildWorkflow(id, name string, input []byte, options ChildOptions) *Future
ChildWorkflow schedules a separate execution atomically with this decision. Await Started before returning when an abandoned child must outlive its parent.
func (*Workflow) ContinueAsNew ¶
func (w *Workflow) ContinueAsNew(input []byte, options ContinueOptions) error
ContinueAsNew closes this run and starts its successor atomically when the workflow returns this error. Return nil output and make no later SDK calls. Unread signals follow the chain; pending tasks and child futures do not.
func (*Workflow) Now ¶
Now returns logical time: run availability, advanced by outcomes consumed by Get or Select. It never reads the worker's wall clock.
func (*Workflow) ReceiveSignal ¶
ReceiveSignal waits for the oldest unconsumed message with this name. Use a unique, stable command ID for each receive. Repeated Get on the same future returns the same copied input. Closing a workflow leaves any unread signals in history; acceptance alone does not promise processing.
func (*Workflow) RunInfo ¶
func (w *Workflow) RunInfo() durable.RunMetadata
RunInfo returns a copy of the saved run coordinates. RetryAttempt starts at one and resets after ContinueAsNew; RunNumber counts every run in the chain.
func (*Workflow) Select ¶
Select returns a ready candidate, or yields until one is ready. Give each call a stable, unique command ID and 1 through 1000 distinct futures from this evaluation. New choices use history order; replay retains the saved winner. Select consumes its winning signal and advances Now. Get reads its result or failure. Losing futures remain active, and a later Select may reuse a winner.
func (*Workflow) SetCancellationHandler ¶
func (w *Workflow) SetCancellationHandler(handler WorkflowCancellationFunc)
SetCancellationHandler registers cleanup on this evaluation. Register before the first command to handle cancellation accepted before the initial decision. Later registrations are available only when frozen normal replay reaches them.
func (*Workflow) SetQueryHandler ¶
SetQueryHandler registers a name on this replay instance. Register handlers before an unresolved future can yield. Invalid or duplicate registrations fail evaluation; they do not become workflow application failures.
type WorkflowCancellationFunc ¶
type WorkflowCancellationFunc func(*Workflow, durable.ExecutionCancellation) ([]byte, error)
WorkflowCancellationFunc replays cleanup after the pending-task fence commits. Return ErrWorkflowCancelled to close cancelled, nil to complete, or another error to fail. Use durable commands for effects and explicit control flow.
type WorkflowCancelledError ¶
WorkflowCancelledError identifies the first accepted cancellation request.
func (*WorkflowCancelledError) Error ¶
func (e *WorkflowCancelledError) Error() string
func (*WorkflowCancelledError) Unwrap ¶
func (e *WorkflowCancelledError) Unwrap() error
Source Files
¶
- activity_async.go
- activity_async_history.go
- activity_heartbeat.go
- activity_history.go
- activity_policy.go
- activity_timeout.go
- cancellation.go
- cancellation_history.go
- children.go
- children_history.go
- continuation.go
- doc.go
- execution_cancellation.go
- execution_cancellation_history.go
- execution_timeout.go
- query.go
- replay.go
- selector.go
- selector_history.go
- signal.go
- signal_history.go
- telemetry.go
- termination.go
- types.go
- worker.go
- worker_activity.go
- worker_async.go
- worker_async_callback.go
- worker_cancellation.go
- worker_children.go
- worker_decision.go
- worker_deferral.go
- worker_effect.go
- worker_execution_cancellation.go
- worker_execution_timeout.go
- worker_heartbeat.go
- worker_lease.go
- worker_lifecycle.go
- worker_query.go
- worker_readiness.go
- worker_signal.go
- worker_store.go
- worker_timeout.go
- workflow.go
- workflow_retry.go