Documentation
¶
Overview ¶
Package engine implements a Temporal-based graph interpreter workflow engine.
Index ¶
- Constants
- func EvaluateCondition(condition string, context map[string]any) (bool, error)
- func FormatChildWorkflowID(parentWorkflowID, nodeID, branchID string) string
- type Activities
- func (a *Activities) ExecuteTaskActivity(ctx context.Context, taskTemplateID string, inputs map[string]any) (map[string]any, error)
- func (a *Activities) FetchWorkflowDefinitionActivity(_ context.Context, templateID string) (WorkflowDefinition, error)
- func (a *Activities) WorkflowCompletedActivity(_ context.Context, workflowID string, finalContext map[string]any) error
- type AdminInterventionResolver
- type AdminResolutionAction
- type AdminResolutionSignal
- type BroadcastMessage
- type Edge
- type ExecutionStatus
- type FailureMode
- type GatewayType
- type Manager
- type Node
- type NodeInfo
- type NodeStatus
- type NodeType
- type SplitMode
- type SplitTaskConfig
- type SplitTaskItem
- type TaskActivationHandler
- type TaskPayload
- type TemporalManager
- type UpdateEvent
- type WorkflowCompletionHandler
- type WorkflowDefinition
- type WorkflowInstance
Constants ¶
const ( // DefaultIterationKey is the default variable name injected into a child workflow's // state containing iteration details (e.g., _iter.index, _iter.branch_id, _iter.input). DefaultIterationKey = "_iter" // ChildBroadcastSignalName is the base name of the Temporal signal used to route cross-branch // signals from a child workflow back up to the parent for brokerage to other sibling branches. // It is scoped per SPLIT_TASK node via childBroadcastSignalName so that two SPLIT_TASK nodes // running concurrently in the same workflow execution (e.g. under a PARALLEL_SPLIT gateway) // don't share a channel and cross-deliver each other's broadcasts. ChildBroadcastSignalName = "child_broadcast_signal" // Keys injected into the child's workspace variables // VarSplitNodeID identifies the ID of the SplitTask node in the parent workflow. VarSplitNodeID = "_split_node_id" // VarParentWorkflowID contains the workflow ID of the parent/orchestrator workflow. VarParentWorkflowID = "_parent_workflow_id" // VarBranchID contains the unique branch ID assigned to the specific child workflow branch. VarBranchID = "_branch_id" // Iteration context sub-keys (e.g., used to access _iter.index, _iter.branch_id, _iter.input) // IterIndexKey is the sub-key for the 0-based index of this branch within the items array. IterIndexKey = "index" // IterBranchIDKey is the sub-key for the unique branch identifier. IterBranchIDKey = "branch_id" // IterInputKey is the sub-key pointing to the input payload mapped to this branch. IterInputKey = "input" // System task template IDs. SysTaskEmitSignal and SysTaskWaitForSignal let sibling // branches spawned by the same SPLIT_TASK node coordinate: one hop up to the parent, // one hop back down to that node's other children. They do not bubble further up an // ancestor chain or cascade down into a sibling's own nested sub-splits — see the // "System Task Templates" section in README.md for the full scope. // // SysTaskWaitForSignal is the template ID for the built-in system task that suspends // the workflow until a specific signal is received from a sibling branch. SysTaskWaitForSignal = "sys:wait_for_signal" // SysTaskEmitSignal is the template ID for the built-in system task that publishes/emits // a signal to be routed to sibling branches under the same SPLIT_TASK node. SysTaskEmitSignal = "sys:emit_signal" // Input keys for system tasks // InputSignalName is the parameter key used to specify the target signal name in signal tasks. InputSignalName = "signal_name" // InputPayload is the parameter key used to specify the data payload in emit signal tasks. InputPayload = "payload" )
Core structural execution constants
const AdminResolutionSignalName = "AdminResolutionSignal"
AdminResolutionSignalName is the Temporal signal name used to deliver AdminResolutionSignal.
Variables ¶
This section is empty.
Functions ¶
func EvaluateCondition ¶
EvaluateCondition parses and runs a string expression against the global context.
func FormatChildWorkflowID ¶
FormatChildWorkflowID constructs a deterministic child workflow ID from parent ID, node ID, and branch ID.
Types ¶
type Activities ¶
type Activities struct {
// ExecuteTaskActivityHandler is invoked when the workflow engine encounters a task node.
// - For synchronous execution, it should return a nil error with a map containing the results.
// - For asynchronous execution, it should return a nil map and an ErrResultPending error,
// which pauses the workflow activity until an external handler triggers TaskDone.
ExecuteTaskActivityHandler func(TaskPayload) (map[string]any, error)
// WorkflowCompletedActivityHandler is invoked when the overall workflow execution succeeds and reaches
// an End node. It receives the workflow ID and the final accumulated workflow variables, allowing the
// host application to run any necessary completion triggers, notify listeners, or persist final state.
WorkflowCompletedActivityHandler func(string, map[string]any) error
// FetchWorkflowDefinitionHandler is invoked to dynamically retrieve the workflow definition structure
// for a given template ID during SPLIT_TASK execution.
FetchWorkflowDefinitionHandler func(templateID string) (WorkflowDefinition, error)
}
Activities encapsulates the Temporal activity implementations utilized by the workflow engine. It maps the activity execution flow to custom callback handlers provided by the host application.
func (*Activities) ExecuteTaskActivity ¶
func (a *Activities) ExecuteTaskActivity(ctx context.Context, taskTemplateID string, inputs map[string]any) (map[string]any, error)
ExecuteTaskActivity pushes the task to your application and sleeps waiting for it or completes synchronously
func (*Activities) FetchWorkflowDefinitionActivity ¶
func (a *Activities) FetchWorkflowDefinitionActivity(_ context.Context, templateID string) (WorkflowDefinition, error)
FetchWorkflowDefinitionActivity is a Temporal activity that retrieves the workflow definition for a template ID.
func (*Activities) WorkflowCompletedActivity ¶
func (a *Activities) WorkflowCompletedActivity(_ context.Context, workflowID string, finalContext map[string]any) error
WorkflowCompletedActivity is a Temporal activity that executes when a workflow completes successfully.
type AdminInterventionResolver ¶
type AdminInterventionResolver interface {
// ResolveAdminIntervention sends an admin's resolution decision to a node that is
// currently parked in NodeStatusAwaitingAdmin, identified by workflowID/runID/nodeID.
ResolveAdminIntervention(ctx context.Context, workflowID, runID string, resolution AdminResolutionSignal) error
}
AdminInterventionResolver is implemented by managers that support resolving a node parked in NodeStatusAwaitingAdmin. It is kept separate from Manager so that existing Manager implementations (e.g. test doubles) aren't forced to implement it. Callers that want this capability can type-assert: if r, ok := mgr.(AdminInterventionResolver); ok { ... }.
type AdminResolutionAction ¶
type AdminResolutionAction string
AdminResolutionAction describes how an admin chooses to resolve a node that is parked in NodeStatusAwaitingAdmin.
const ( // AdminActionRetry re-runs the node's handler from scratch. It is the admin's // responsibility to ensure this is safe — e.g. a TASK node with a populated // CachedTaskResult has already run its Activity, so retrying re-invokes it. AdminActionRetry AdminResolutionAction = "RETRY" // AdminActionOverride merges Overrides directly into WorkflowVariables and marks // the node completed without re-running anything. Always safe. AdminActionOverride AdminResolutionAction = "OVERRIDE" // AdminActionSkip marks the node completed without setting any variables. AdminActionSkip AdminResolutionAction = "SKIP" // AdminActionAbort fails the node and the workflow with the original error — // the same behavior the engine had before the escape hatch existed. AdminActionAbort AdminResolutionAction = "ABORT" )
Admin resolution actions.
type AdminResolutionSignal ¶
type AdminResolutionSignal struct {
// NodeID is the template node ID (Node.ID) of the parked node — the routing key.
NodeID string `json:"nodeID"`
// Action determines how the node is resolved. See AdminResolutionAction constants.
Action AdminResolutionAction `json:"action"`
// Overrides are merged into WorkflowVariables for AdminActionOverride/AdminActionSkip,
// or merged in before retrying for AdminActionRetry.
Overrides map[string]any `json:"overrides,omitempty"`
// Reason is a free-text admin justification, appended to the workflow's AuditTrail.
Reason string `json:"reason,omitempty"`
}
AdminResolutionSignal is sent by an external admin tool to resolve a node that is parked in NodeStatusAwaitingAdmin.
type BroadcastMessage ¶
type BroadcastMessage struct {
SenderBranchID string `json:"sender_branch_id"`
SignalName string `json:"signal_name"`
Payload map[string]any `json:"payload"`
}
BroadcastMessage defines a unified Message Wrapper for parent brokerage.
type Edge ¶
type Edge struct {
ID string `json:"id"`
SourceID string `json:"source_id"`
TargetID string `json:"target_id"`
Condition string `json:"condition,omitempty"` // Expression mapped against WorkflowVariables
}
Edge represents a directed connection between two nodes.
type ExecutionStatus ¶
type ExecutionStatus string
ExecutionStatus defines the allowed states for a workflow instance.
const ( StatusRunning ExecutionStatus = "RUNNING" StatusCompleted ExecutionStatus = "COMPLETED" StatusFailed ExecutionStatus = "FAILED" )
Execution status constants for workflows.
type FailureMode ¶
type FailureMode string
FailureMode represents the failure handling strategy for split task executions.
const ( FailureModeFailFast FailureMode = "FAIL_FAST" FailureModeCollectAll FailureMode = "COLLECT_ALL" )
Core split task failure handling modes.
type GatewayType ¶
type GatewayType string
GatewayType represents the type of a gateway controlling execution flow.
const ( GatewayTypeExclusiveSplit GatewayType = "EXCLUSIVE_SPLIT" // XOR Split GatewayTypeParallelSplit GatewayType = "PARALLEL_SPLIT" // AND Split GatewayTypeExclusiveJoin GatewayType = "EXCLUSIVE_JOIN" // XOR Join GatewayTypeParallelJoin GatewayType = "PARALLEL_JOIN" // AND Join )
Gateway types controlling branching and merging.
type Manager ¶
type Manager interface {
// StartWorkflow starts a workflow using the provided ID.
// The WorkflowDefinition defines the structure of the workflow graph (nodes and edges).
// initialWorkflowVariables sets the starting state for the graph's
// data payload. Returns an error if submission fails.
StartWorkflow(ctx context.Context, ID string, def WorkflowDefinition, initialWorkflowVariables map[string]any) error
// TaskDone is called by the external system to resume a paused workflow node.
// It routes the output data back into the specific workflow's WorkflowVariables using the provided
// IDs (workflowID, runID, nodeID) that were originally emitted via the TaskActivationHandler.
TaskDone(ctx context.Context, workflowID, runID, nodeID string, output map[string]any) error
// TaskUpdate is used to send an update about the task to the workflow.
// This is typically used to append messages to the workflow's internal state or update
// UI with hints, progress updates, or audit trail messages.
// It does not advance the graph's execution state.
TaskUpdate(ctx context.Context, workflowID, runID string, update UpdateEvent) error
// GetStatus retrieves a running workflow's in-memory state (the WorkflowInstance), including
// current variables, and audit trails.
GetStatus(ctx context.Context, workflowID string) (*WorkflowInstance, error)
}
Manager acts as the bridge between the external host application and the underlying execution engine. It handles workflow lifecycles, external task routing, and state queries.
type Node ¶
type Node struct {
ID string `json:"id"`
Type NodeType `json:"type"` // START, END, TASK, GATEWAY, or SPLIT_TASK
GatewayType GatewayType `json:"gateway_type,omitempty"` // See Gateway Types constants
TaskTemplateID string `json:"task_template_id,omitempty"` // Identifier for the task template to run
InputMapping map[string]string `json:"input_mapping,omitempty"` // Maps WorkflowVariables Key -> Task Input Key
OutputMapping map[string]string `json:"output_mapping,omitempty"` // Maps Task Output Key -> WorkflowVariables Key
// Extensions
SplitTask *SplitTaskConfig `json:"split_task,omitempty"`
}
Node represents a step in the workflow graph.
type NodeInfo ¶
type NodeInfo struct {
ID string `json:"id"`
CreatedAt time.Time `json:"createdAt"` // Timestamp of node creation
UpdatedAt time.Time `json:"updatedAt"` // Timestamp of last node update
Type NodeType `json:"type"` // Type of the node.
GatewayType GatewayType `json:"gateway_type,omitempty"` // See Gateway Types constants
TaskTemplateID string `json:"task_template_id,omitempty"` // Identifier for the task template to run
Status NodeStatus `json:"status"` // Status of the node
// LastError holds the error that caused the node to enter NodeStatusAwaitingAdmin
// (or the terminal error if it was ultimately aborted). Cleared on successful resolution.
LastError string `json:"last_error,omitempty"`
// CachedTaskResult holds the most recent raw Activity result for a TASK node, set right
// after the Activity succeeds and cleared once the node fully completes. It is purely
// informational: if a node parks with this populated, the Activity has already run, so
// an admin should prefer AdminActionOverride over AdminActionRetry to avoid re-running it.
CachedTaskResult map[string]any `json:"cached_task_result,omitempty"`
}
NodeInfo holds information about the state of one of the nodes in the workflow.
type NodeStatus ¶
type NodeStatus string
NodeStatus represents the status of a specific workflow node.
const ( NodeStatusNotStarted NodeStatus = "NOT_STARTED" NodeStatusRunning NodeStatus = "RUNNING" NodeStatusCompleted NodeStatus = "COMPLETED" NodeStatusFailed NodeStatus = "FAILED" NodeStatusAwaitingAdmin NodeStatus = "AWAITING_ADMIN" )
Node status constants.
type NodeType ¶
type NodeType string
NodeType represents the type of a workflow node (e.g. START, END, TASK, GATEWAY).
type SplitTaskConfig ¶
type SplitTaskConfig struct {
Mode SplitMode `json:"mode"` // SAME_TEMPLATE or DIFFERENT_TEMPLATES
ItemsVariable string `json:"items_variable"` // Global context variable dot-path pointing to []map[string]any
ResultsVariable string `json:"results_variable,omitempty"` // Destination path to save aggregated sub-workflow outputs
FailureMode FailureMode `json:"failure_mode"` // FAIL_FAST or COLLECT_ALL
IterationKey string `json:"iteration_key,omitempty"` // Override key for sub-context namespace. Defaults to "_iter"
}
SplitTaskConfig defines dynamic fan-out execution configuration.
type SplitTaskItem ¶
type SplitTaskItem struct {
TemplateID string `json:"template_id"`
BranchID string `json:"branch_id"`
Payload map[string]any `json:"payload"`
}
SplitTaskItem defines the structure for individual branch items inside the items collection.
func ParseSplitTaskItem ¶
func ParseSplitTaskItem(itemRaw any) (SplitTaskItem, error)
ParseSplitTaskItem parses a raw interface item into a SplitTaskItem.
type TaskActivationHandler ¶
type TaskActivationHandler func(payload TaskPayload) (map[string]any, error)
TaskActivationHandler is invoked by the engine whenever the workflow reaches a "Task" node. The handler must support two execution paths:
1. Synchronous Execution:
- If the work completes immediately, return a nil error and a map containing the output variables.
- The workflow immediately consumes these outputs and proceeds to the next node.
2. Asynchronous Execution:
- If the work is long-running (e.g. awaits external API callback, human UI interaction, etc.), return a nil map and an ErrResultPending error.
- The workflow activity pauses and awaits completion. The host application must eventually resume it by calling Manager.TaskDone() with the matching workflow, run, and node IDs.
type TaskPayload ¶
type TaskPayload struct {
// WorkflowID is the unique identifier for the overall business process instance.
WorkflowID string
// RunID is the unique identifier for this specific execution attempt.
RunID string
// NodeID is the ID of the graph node currently being executed. This should be
// unique for each node in the workflow.
NodeID string
// TaskTemplateID identifies the specific type of external work/script the task executor should run.
TaskTemplateID string
// Inputs contains the specific subset of WorkflowVariables mapped to this task's requirements.
Inputs map[string]any
}
TaskPayload represents the contextual data sent to the task executor when the workflow engine reaches a "Task" node. It contains the necessary coordinates for the task executor to identify the work and eventually report back.
type TemporalManager ¶
type TemporalManager interface {
Manager
// RegisterDefinitionHandler registers the handler function for fetching sub-workflow definitions.
RegisterDefinitionHandler(handler func(templateID string) (WorkflowDefinition, error))
// StartWorker connects the internal Temporal Worker to the Temporal Server and
// begins polling the task queue for workflow and activity tasks.
StartWorker() error
// StopWorker gracefully shuts down the internal Temporal Worker, stopping it from
// pulling new tasks while allowing currently executing tasks to finish.
StopWorker()
}
TemporalManager extends the Manager interface with worker control methods.
func NewTemporalManager ¶
func NewTemporalManager( c client.Client, taskQueue string, taskHandler TaskActivationHandler, completionHandler WorkflowCompletionHandler) TemporalManager
NewTemporalManager creates a new instance of TemporalManager.
type UpdateEvent ¶
type UpdateEvent struct {
// EventType categorizes the signal (e.g., "AUDIT", "PROGRESS_UPDATE", "UI_HINT")
// so the workflow knows how to route the data internally.
EventType string `json:"eventType"`
// NodeID is the ID of the graph node being updated.
NodeID string `json:"nodeID"`
// Payload contains the contextual data for the event (e.g., percentage complete, or audit text).
Payload map[string]any `json:"payload,omitempty"`
}
UpdateEvent allows the task executor to send asynchronous signals into a running workflow (e.g., while a task is active).
type WorkflowCompletionHandler ¶
WorkflowCompletionHandler is invoked when the generic DAG workflow successfully reaches an "End" node, providing the final, accumulated state of the workflow variables.
type WorkflowDefinition ¶
type WorkflowDefinition struct {
// ID is the unique identifier for this specific workflow template.
ID string `json:"id"`
// Name is a human-readable label used for display and organizational purposes.
Name string `json:"name"`
// Version tracks iterations of the workflow logic, allowing for side-by-side
// deployment of different logic versions.
Version int `json:"version"`
// Nodes defines the individual steps, gateways, and boundary events
// that make up the workflow.
Nodes []Node `json:"nodes"`
// Edges defines the directed connections between nodes, including
// any conditional logic required for branching.
Edges []Edge `json:"edges"`
}
WorkflowDefinition represents the structural blueprint of a workflow process. It serves as the parsed representation of the JSON DSL, defining how nodes and edges form a directed graph for the execution engine.
type WorkflowInstance ¶
type WorkflowInstance struct {
// ID is the unique ID for this instance of the workflow.
ID string `json:"id"`
// Status represents the current execution state.
Status ExecutionStatus `json:"status"`
// WorkflowVariables holds the shared, dynamic business data passed between nodes.
WorkflowVariables map[string]any `json:"workflow_variables"`
// AuditTrail is a chronologically ordered log of events, milestones, or external signals.
AuditTrail []string `json:"audit_trail"`
NodeInfo map[string]*NodeInfo `json:"node_states"`
// Edges contains the workflow graph connections from the workflow definition.
Edges []Edge `json:"edges"`
}
WorkflowInstance holds the dynamic runtime state of the workflow execution. This struct is returned by the GetStatus query and represents a deterministic snapshot of the engine's memory at a given point in time.
func GraphInterpreterWorkflow ¶
func GraphInterpreterWorkflow(ctx workflow.Context, def WorkflowDefinition, initialWorkflowVariables map[string]any) (*WorkflowInstance, error)
GraphInterpreterWorkflow is the entry point for the Temporal workflow that interprets a graph definition.