workflow

package
v0.61.0 Latest Latest
Warning

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

Go to latest
Published: Nov 10, 2026 License: Apache-2.0 Imports: 17 Imported by: 0

Documentation

Overview

Package workflow composes deterministic orchestration from Call, Transform, Switch, Fork, Map, and Loop stages. Compile freezes the graph and its child Programs using the Runtime's Compiler. A callback Revision identifies opaque code; Configuration records settings captured by that code. Graph bindings, schemas, budgets, and bounds have their sole owner in the stage declarations. Adapt composes Transform, Call, and Transform to fit any child Program to another role's ports, such as an Interaction serving as a Workflow branch.

Child invocations advance from a Spawn Completion to an Exit. A successful Spawn admits work; only Exit establishes that its subtree has drained. The Runtime owns cancellation, mailbox delivery, persistence, and reaping. Workflow owns only its stage cursor, business values, and outstanding invocations.

Fork and Map preserve declaration order in their output while admitting bounded windows of child work. A failed admission or child execution preserves its original Failure. A window drains before the workflow adopts its results, propagates a failure, or starts another window.

Transform, Switch, Fork, and Loop callbacks run inside discardable Steps. They must be deterministic, bounded, side-effect-free, and cancellation-aware. Context carries cancellation, never hidden domain input. External I/O belongs in a child Program's dispatcher Effects.

Persisted execution state contains only progress not already owned by the immutable graph. Restore validates it against the exact compiled graph. Unaddressed Signals are rejected; Completion and Exit messages must match outstanding invocation identities.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrInvalidStage = errors.New("workflow: invalid stage")

	ErrInvalidDefinitionConfig = errors.New("workflow: invalid definition configuration")
)

Construction sentinels reject caller data before execution and therefore carry no Failure classification.

View Source
var (
	ErrInvalidExecutionState = run.NewClassifiedError(
		run.FailureKindContract,
		"workflow.state.invalid",
		"workflow: invalid execution state",
	)
	ErrInvalidProtocol = run.NewClassifiedError(
		run.FailureKindContract,
		"workflow.protocol.invalid",
		"workflow: invalid protocol payload",
	)
)

Execution sentinels own the Failure persisted when they reach Step. Wrapping one is the only way a Step error acquires its classification.

Functions

func Adapt added in v0.60.0

func Adapt[I, A, B, O any](
	compiler *run.Compiler,
	config AdaptConfig,
	child run.Program[A, B],
	input TransformFunc[I, A],
	output TransformFunc[B, O],
) (run.Program[I, O], error)

Adapt fits child to another role's ports: input maps I to the child's input, output maps the child's output to O. The result is an ordinary Workflow of one Transform, one Call, and one Transform, so it adds no execution semantics of its own.

func Compile added in v0.59.0

func Compile[I, O any](compiler *run.Compiler, cfg Config) (run.Program[I, O], error)

Types

type AdaptConfig added in v0.60.0

type AdaptConfig struct {
	Name          string
	Description   string
	Revision      string
	Configuration any

	// Budget is permanently allocated from the parent when the child starts.
	Budget       run.Budget
	Capabilities run.CapabilitySet
}

AdaptConfig names an adapted Program and the authority its child receives. Revision and Configuration identify the two mapping callbacks exactly as Config does for any Transform.

type BindingRole

type BindingRole string
const (
	BindingRoleInvalid BindingRole = ""
	BindingRoleCall    BindingRole = "call"
	BindingRoleCase    BindingRole = "case"
	BindingRoleBranch  BindingRole = "branch"
	BindingRoleItem    BindingRole = "item"
	BindingRoleBody    BindingRole = "body"
)

func (BindingRole) String added in v0.59.0

func (b BindingRole) String() string

func (BindingRole) Valid added in v0.59.0

func (b BindingRole) Valid() bool

type BindingTopology

type BindingTopology struct {
	Role         BindingRole       `json:"role"`
	ID           string            `json:"id,omitempty"`
	ProgramRef   run.ProgramRef    `json:"program_ref"`
	InputSchema  jsonschema.Schema `json:"input_schema"`
	OutputSchema jsonschema.Schema `json:"output_schema"`
	// Budget is the non-renewable allocation for each child start.
	Budget       run.Budget        `json:"budget"`
	Capabilities run.CapabilitySet `json:"capabilities"`
}

BindingTopology is a function-free projection of one exact child binding. ID is present only for named Switch cases and Fork branches.

type CallConfig

type CallConfig struct {
	ID    string
	Child run.ChildBinding
}

CallConfig declares one exact child Program and its non-renewable Framework resource allocation.

type Config added in v0.59.0

type Config struct {
	Name          string
	Description   string
	Stages        []Stage
	Revision      string
	Configuration any
}

Revision identifies callbacks that cannot be inspected. Configuration records their captured settings; structural stage settings belong to the graph.

type ForkBranch

type ForkBranch struct {
	ID    string
	Child run.ChildBinding
}

type ForkConfig

type ForkConfig[I, B, O any] struct {
	// ID is unique within the Workflow and remains stable across restoration.
	ID string

	// Branches is a non-empty list in stable declaration order. Every branch
	// accepts I and produces B.
	Branches []ForkBranch

	// WindowSize is the positive number of branches started and settled as one
	// execution window before the next window begins.
	WindowSize uint32

	Reduce ForkReducer[I, B, O]
}

type ForkReducer

type ForkReducer[I, B, O any] func(ctx context.Context, input I, branchOutputs []B) (O, error)

ForkReducer combines the Fork's input with its branch outputs in declaration order; branches therefore return only what they add. It must be bounded, deterministic, side-effect-free, honor ctx cancellation, and never retain the slice. Context is not a source of domain input.

type LoopConfig

type LoopConfig[T any] struct {
	// ID is unique within the Workflow and remains stable across restoration.
	ID string

	Body run.ChildBinding

	// MaxIterations bounds body child Processes. Its zero value is unlimited;
	// a finite zero is rejected because a Loop runs its body at least once.
	MaxIterations run.Quota

	Predicate LoopPredicate[T]
}

type LoopPredicate

type LoopPredicate[T any] func(ctx context.Context, value T) (bool, error)

LoopPredicate is a bounded, deterministic, side-effect-free completion test evaluated after each successful body child Process. It must honor ctx cancellation; context is not a source of domain input.

type LoopResult

type LoopResult[T any] struct {
	// Value is the output of the last completed body iteration.
	Value      T      `json:"value"`
	Iterations uint64 `json:"iterations"`
	Satisfied  bool   `json:"satisfied"`
}

LoopResult is the exact semantic output of a Loop Stage. Satisfied is false when MaxIterations was exhausted; that outcome is still a valid completion.

func (LoopResult[T]) Valid

func (l LoopResult[T]) Valid() bool

type MapConfig

type MapConfig[I, O any] struct {
	// ID is unique within the Workflow and remains stable across restoration.
	ID string

	Child run.ChildBinding

	// WindowSize is the positive number of items started and settled as one
	// execution window before the next window begins. Only that window is
	// decoded into I values; snapshot recovery still validates the full input.
	WindowSize uint32

	// MaxItems is the positive maximum accepted input length.
	MaxItems uint32
}

MapConfig declares a bounded homogeneous item fan-out. The Stage input is []I, each exact child Program consumes one I and produces one O, and the Stage output is []O in original item order.

type Stage

type Stage struct {
	// contains filtered or unexported fields
}

Stage is an immutable operation in one Workflow definition. Values can only be constructed by this package, keeping the execution algebra closed.

func Call

func Call(config CallConfig) (Stage, error)

Call constructs one managed child-Process Stage. No child Process is created until the Workflow Execution returns a Framework NewChildStartEffect Effect.

func Fork

func Fork[I, B, O any](config ForkConfig[I, B, O]) (Stage, error)

Fork constructs one windowed managed fan-out Stage. Branch inputs and outputs are homogeneous; heterogeneous work can be wrapped by child Workflows that expose a shared contract.

func Loop

func Loop[T any](config LoopConfig[T]) (Stage, error)

Loop constructs one at-least-once managed iteration Stage. Body must accept and produce exactly T; the Stage itself produces LoopResult[T].

func Map

func Map[I, O any](config MapConfig[I, O]) (Stage, error)

Map constructs one bounded managed item fan-out Stage. Empty input is valid and produces a non-nil empty []O without creating child Processes.

func Switch

func Switch[I any](config SwitchConfig[I]) (Stage, error)

Switch constructs one selected managed child-Process Stage. Every case must accept the same I schema and produce one exactly matching output schema.

func Transform

func Transform[I, O any](id string, transform TransformFunc[I, O]) (Stage, error)

Transform constructs one typed pure Stage. JSON schemas derived from I and O remain the authoritative erased boundary used by the Workflow definition.

func (Stage) Valid

func (s Stage) Valid() bool

type StageKind

type StageKind string
const (
	StageKindInvalid   StageKind = ""
	StageKindTransform StageKind = "transform"
	StageKindCall      StageKind = "call"
	StageKindSwitch    StageKind = "switch"
	StageKindFork      StageKind = "fork"
	StageKindMap       StageKind = "map"
	StageKindLoop      StageKind = "loop"
)

func (StageKind) String added in v0.59.0

func (s StageKind) String() string

func (StageKind) Valid added in v0.59.0

func (s StageKind) Valid() bool

type StageTopology

type StageTopology struct {
	ID           string            `json:"id"`
	Kind         StageKind         `json:"kind"`
	InputSchema  jsonschema.Schema `json:"input_schema"`
	OutputSchema jsonschema.Schema `json:"output_schema"`
	// Bindings are exact child bindings in stable declaration order.
	Bindings []BindingTopology `json:"bindings,omitempty"`
	// WindowSize is the fixed Fork or Map execution-window size.
	WindowSize uint32 `json:"window_size,omitzero"`
	// MaxItems is the maximum accepted Map input length.
	MaxItems uint32 `json:"max_items,omitzero"`
	// MaxIterations is present only for a Loop, including an unlimited Loop.
	MaxIterations *run.Quota `json:"max_iterations,omitzero"`
}

StageTopology is a function-free projection of one sealed Stage. Limits are present only for the Stage kinds that own them.

type SwitchCase

type SwitchCase struct {
	ID    string
	Child run.ChildBinding
}

type SwitchConfig

type SwitchConfig[I any] struct {
	// ID is unique within the Workflow and remains stable across restoration.
	ID string

	Select SwitchSelector[I]

	// Cases is a non-empty list in stable declaration order.
	Cases []SwitchCase
}

type SwitchSelector

type SwitchSelector[I any] func(ctx context.Context, input I) (caseID string, err error)

SwitchSelector is a bounded, deterministic, side-effect-free case selector. It must honor ctx cancellation and returns the exact SwitchCase ID to invoke for the current value. Context is not a source of domain input.

type Topology

type Topology struct {
	Descriptor run.Descriptor `json:"descriptor"`
	// Stages are projected in execution order.
	Stages []StageTopology `json:"stages"`
}

Topology is a detached definition-derived, function-free projection for diagnostics, documentation, UI rendering, and program audit. Mutating a projection never changes the definition or a later projection.

func TopologyOf added in v0.60.0

func TopologyOf[I, O any](program run.Program[I, O]) (Topology, error)

TopologyOf exposes the workflow structure without exposing its execution owner.

type TransformFunc

type TransformFunc[I, O any] func(ctx context.Context, input I) (O, error)

TransformFunc is a bounded, deterministic, side-effect-free reduction. It must honor ctx cancellation during CPU work. External work belongs in a Call stage that starts a child Process; ctx is not a source of domain input.

Jump to

Keyboard shortcuts

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