Help us shape the future of Go! Take the 2026 Go Developer Survey

runtime

package
v1.9.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 26, 2026 License: MIT Imports: 22 Imported by: 0

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

View Source
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"
)
View Source
const (
	// EventCancellationStarted records the atomic fence before cleanup can run.
	EventCancellationStarted = "workflow.cancellation_started"
	// EventWorkflowCancelled records a terminal cancellation after cleanup.
	EventWorkflowCancelled = "workflow.cancelled"
)
View Source
const (
	EventSignalReceived = durable.EventSignalReceived
	EventSignalConsumed = durable.EventSignalConsumed
)

Signal history separates durable acceptance from workflow consumption.

View Source
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.

View Source
const CommandCancel durable.TaskKind = "cancel"

CommandCancel requests a recorded cancellation without creating a polled task.

View Source
const CommandSelect durable.TaskKind = "select"

CommandSelect records an ordered set of futures without creating a polled task.

View Source
const CommandSignal durable.TaskKind = "signal"

CommandSignal records a receive operation. It never creates a polled task.

View Source
const EventContinuationRequested = "workflow.continuation_requested"

EventContinuationRequested captures the SDK decision before the store closes the run.

View Source
const EventFutureCancelled = "workflow.future_cancelled"

EventFutureCancelled acknowledges fencing or preserves an existing outcome.

View Source
const EventSelected = "workflow.selected"

EventSelected records the winning future in the workflow decision transaction.

View Source
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.

View Source
const TaskExecutionTimeout durable.TaskKind = "execution_timeout"

TaskExecutionTimeout polls expired runs independently of pinned workflow builds.

View Source
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

View Source
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")
)
View Source
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.

View Source
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.

View Source
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")
)
View Source
var ErrCancelled = errors.New("durable runtime: future cancelled")

ErrCancelled identifies a future whose result was fenced by cancellation.

View Source
var ErrDeferralUnknown = errors.New("durable runtime: task deferral outcome unknown")
View Source
var ErrHandlerNotFound = errors.New("durable runtime: handler not registered")

ErrHandlerNotFound leaves a task available for a worker with compatible code.

View Source
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.

View Source
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

type ActivityFunc func(context.Context, ActivityInfo, []byte) ([]byte, error)

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

type DrainRequest struct {
	OperationID string
	Deadline    time.Time
}

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.

func (*Future) Get

func (f *Future) Get() ([]byte, error)

Get returns a copy of a saved result, or a typed recorded activity failure. An unresolved future yields internally; do not recover this control flow in workflow code or perform work in a defer. The handler is replayed to resume.

func (*Future) Started

func (f *Future) Started() (durable.Key, error)

Started yields until the child start or definitive creation failure is saved. It never claims that the child has completed.

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

type QueryFunc func([]byte) ([]byte, error)

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

type RetirementOptions struct {
	InstallationID string
	WriterProtocol int
}

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 NewWorker

func NewWorker(store durable.Store, options Options) (*Worker, error)

NewWorker validates routing and timing before any task can be claimed.

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

func (w *Worker) Run(ctx context.Context) (result error)

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

func (w *Worker) RunOnce(ctx context.Context, kind durable.TaskKind) (worked bool, err error)

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

func (w *Worker) ServesBuild(namespace, build string) bool

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

func (w *Worker) Stop(ctx context.Context) error

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

func (w *Worker) SupportsSignalStartOutcome() bool

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

func (w *Workflow) Activity(id, name, queue string, input []byte) *Future

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

func (w *Workflow) Cancel(id string, target *Future) *Future

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

func (w *Workflow) CancelChild(id string, target *Future) *Future

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

func (w *Workflow) Now() time.Time

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

func (w *Workflow) ReceiveSignal(id, name string) *Future

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

func (w *Workflow) Select(id string, futures ...*Future) *Future

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

func (w *Workflow) SetQueryHandler(name string, handler QueryFunc)

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.

func (*Workflow) Timer

func (w *Workflow) Timer(id string, delay time.Duration) *Future

Timer schedules a durable delay from Now, rounded up to store clock precision. No worker or goroutine needs to stay alive while this future is pending.

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

type WorkflowCancelledError struct {
	RequestID string
	Reason    string
}

WorkflowCancelledError identifies the first accepted cancellation request.

func (*WorkflowCancelledError) Error

func (e *WorkflowCancelledError) Error() string

func (*WorkflowCancelledError) Unwrap

func (e *WorkflowCancelledError) Unwrap() error

type WorkflowFunc

type WorkflowFunc func(*Workflow, []byte) ([]byte, error)

WorkflowFunc contains deterministic decisions, never external effects. The runtime replays it from its beginning whenever an outcome becomes available.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL