Documentation
¶
Index ¶
- Constants
- func FilterState(state map[string]any, declared []string) map[string]any
- func MergeState(state any, changes any, reducers map[string]Reducer) (map[string]any, error)
- type Flow
- func (f *Flow) Get(key string, target any) error
- func (f *Flow) GetBool(key string) bool
- func (f *Flow) GetDuration(key string) time.Duration
- func (f *Flow) GetFloat(key string) float64
- func (f *Flow) GetInt(key string) int
- func (f *Flow) GetString(key string) string
- func (f *Flow) GetStrings(key string) []string
- func (f *Flow) Goto(taskName string)
- func (f *Flow) GotoRequested() string
- func (f *Flow) Has(key string) bool
- func (f *Flow) Interrupt(payload any)
- func (f *Flow) InterruptRequested() (map[string]any, bool)
- func (f *Flow) MarshalJSON() ([]byte, error)
- func (f *Flow) ParseState(target any) error
- func (f *Flow) Retry(maxAttempts int, initialDelay time.Duration, multiplier float64, ...) bool
- func (f *Flow) RetryNow() bool
- func (f *Flow) RetryNowOnTimeout(err error) bool
- func (f *Flow) RetryOnTimeout(err error, maxAttempts int, initialDelay time.Duration, multiplier float64, ...) bool
- func (f *Flow) RetryRequested() (maxAttempts int, initialDelay time.Duration, multiplier float64, ...)
- func (f *Flow) Set(key string, value any) error
- func (f *Flow) SetBool(key string, value bool)
- func (f *Flow) SetChanges(source any, snap map[string]any) error
- func (f *Flow) SetDuration(key string, value time.Duration)
- func (f *Flow) SetFloat(key string, value float64)
- func (f *Flow) SetInt(key string, value int)
- func (f *Flow) SetState(source any) error
- func (f *Flow) SetString(key string, value string)
- func (f *Flow) SetStrings(key string, value []string)
- func (f *Flow) Sleep(duration time.Duration)
- func (f *Flow) SleepRequested() time.Duration
- func (f *Flow) Snapshot() map[string]any
- func (f *Flow) Subgraph(workflowURL string, input map[string]any)
- func (f *Flow) SubgraphRequested() (workflowURL string, input map[string]any, ok bool)
- func (f *Flow) UnmarshalJSON(data []byte) error
- type Graph
- func (g *Graph) AddSubgraph(name, workflowURL string)
- func (g *Graph) AddTask(name, url string)
- func (g *Graph) AddTransition(from, to string)
- func (g *Graph) AddTransitionForEach(from, to string, forEach string, as string)
- func (g *Graph) AddTransitionGoto(from, to string)
- func (g *Graph) AddTransitionOnError(from, to string)
- func (g *Graph) AddTransitionOnTimeout(from, to string)
- func (g *Graph) AddTransitionWhen(from, to string, when string)
- func (g *Graph) DeclareInputs(fields ...string)
- func (g *Graph) DeclareOutputs(fields ...string)
- func (g *Graph) EntryPoint() string
- func (g *Graph) ErrorTransition(name string) (Transition, bool)
- func (g *Graph) FanInFor(fanOutSource string) string
- func (g *Graph) HasFanIn() bool
- func (g *Graph) Inputs() []string
- func (g *Graph) IsFanIn(name string) bool
- func (g *Graph) IsFanOutSource(name string) bool
- func (g *Graph) IsSubgraph(name string) bool
- func (g *Graph) MarshalJSON() ([]byte, error)
- func (g *Graph) Mermaid() string
- func (g *Graph) Name() string
- func (g *Graph) NamesForURL(url string) []string
- func (g *Graph) Nodes() []Node
- func (g *Graph) Outputs() []string
- func (g *Graph) Reducers() map[string]Reducer
- func (g *Graph) SetEntryPoint(name string)
- func (g *Graph) SetFanIn(name string)
- func (g *Graph) SetReducer(field string, reducer Reducer)
- func (g *Graph) SetTimeBudget(name string, budget time.Duration)
- func (g *Graph) TimeBudget(name string) time.Duration
- func (g *Graph) Transitions() []Transition
- func (g *Graph) URLOf(name string) string
- func (g *Graph) UnmarshalJSON(data []byte) error
- func (g *Graph) Validate() error
- type Node
- type RawFlow
- func (f *RawFlow) ClearChanges()
- func (f *RawFlow) ClearControl()
- func (f *RawFlow) RawChanges() map[string]any
- func (f *RawFlow) RawState() map[string]any
- func (f *RawFlow) SetAttempt(attempt int)
- func (f *RawFlow) SetRawChanges(changes map[string]any)
- func (f *RawFlow) SetRawState(state map[string]any)
- type Reducer
- type Transition
Constants ¶
const END = "END"
END is a pseudo-node indicating that the workflow should terminate. Use it as the target of a transition to mark a terminal path.
Variables ¶
This section is empty.
Functions ¶
func FilterState ¶
FilterState returns a subset of state based on declared field names. nil or empty = pass nothing. ["*"] = pass everything. Named fields = pass only those fields.
func MergeState ¶
MergeState applies changes on top of state, using the provided reducers for fields that have one. For fields without an explicit reducer, the reducer is inferred from the field name's prefix (sum*, list*, set*); fields not matching a convention prefix use replace semantics.
The set* prefix is polymorphic: it dispatches to union when the value is a JSON array and to merge when the value is a JSON object. Explicit reducer configuration via SetReducer is strict and does not polymorph.
State, changes and the result are map[string]any or nil.
Types ¶
type Flow ¶
type Flow struct {
// contains filtered or unexported fields
}
Flow is the carrier object passed to tasks. It holds the state and control signals for a single step in a workflow execution.
func (*Flow) Get ¶
Get unmarshals a state field into the target. Use this for complex types (structs, maps, etc.).
func (*Flow) GetDuration ¶
GetDuration returns a state field as a time.Duration.
func (*Flow) GetStrings ¶
GetStrings returns a state field as a string slice.
func (*Flow) Goto ¶
Goto overrides transition routing. The orchestrator skips condition evaluation and follows the specified task instead.
func (*Flow) GotoRequested ¶
GotoRequested returns the task URL set by Goto, or empty if not set.
func (*Flow) Interrupt ¶
Interrupt pauses the flow execution and requests external input. The payload is propagated up through the surgraph chain and surfaced via State() so the caller can see what data the task needs. The task should return normally after calling Interrupt.
func (*Flow) InterruptRequested ¶
InterruptRequested returns the interrupt payload and true if Interrupt was called.
func (*Flow) MarshalJSON ¶
MarshalJSON serializes the Flow including private fields.
func (*Flow) ParseState ¶
ParseState unmarshals state fields into the target struct. Fields are matched by their JSON tag names. Fields in state that are not in the struct are ignored.
func (*Flow) Retry ¶
func (f *Flow) Retry(maxAttempts int, initialDelay time.Duration, multiplier float64, maxDelay time.Duration) bool
Retry requests the orchestrator to retry this task with exponential backoff. Returns true if a retry will be scheduled (attempts remaining), false if exhausted. When true, the task should return nil. When false, the task should return its error. The delay for attempt N is min(initialDelay * multiplier^N, maxDelay).
Example:
result, err := callExternalAPI(ctx)
if err != nil {
if flow.Retry(5, 1*time.Second, 2.0, 30*time.Second) {
return result, nil // retry scheduled, don't report error
}
return result, err // retries exhausted, report the error
}
func (*Flow) RetryNow ¶
RetryNow signals the orchestrator to re-execute this task immediately with no limit. Equivalent to Retry(math.MaxInt32, 0, 0, 0).
func (*Flow) RetryNowOnTimeout ¶ added in v1.30.0
RetryNowOnTimeout retries the task immediately on HTTP 408 with no attempt limit and no delay, and returns false for any other error so the caller can surface it. Equivalent to RetryOnTimeout(err, math.MaxInt32, 0, 0, 0).
func (*Flow) RetryOnTimeout ¶ added in v1.30.0
func (f *Flow) RetryOnTimeout(err error, maxAttempts int, initialDelay time.Duration, multiplier float64, maxDelay time.Duration) bool
RetryOnTimeout retries the task only when err carries HTTP status 408 (Request Timeout), and otherwise returns false so the caller can surface the error to the workflow. Returns true exactly when Retry would schedule another attempt; the caller should return nil in that case.
Typical usage:
result, err := svc.doWork(ctx)
if err != nil {
if flow.RetryOnTimeout(err, 5, 2*time.Second, 2.0, time.Minute) {
return result, nil // retry scheduled, suppress the timeout
}
return result, errors.Trace(err) // non-timeout, or attempts exhausted
}
func (*Flow) RetryRequested ¶
func (f *Flow) RetryRequested() (maxAttempts int, initialDelay time.Duration, multiplier float64, maxDelay time.Duration, ok bool)
RetryRequested returns the backoff parameters and true if Retry was called. The foreman uses these to compute the sleep delay and check the attempt limit.
func (*Flow) Set ¶
Set sets a state field and tracks the change. Use this for complex types (structs, maps, etc.).
func (*Flow) SetChanges ¶
SetChanges marshals the source struct back to state, comparing against the provided snapshot. Only fields whose JSON value differs from the snapshot are recorded as changes. Changed fields are written to both the state and changes maps, so that subsequent reads (including transition condition evaluation) see the updated values.
func (*Flow) SetDuration ¶
SetDuration sets a state time.Duration field and tracks the change.
func (*Flow) SetState ¶
SetState marshals the source struct fields into state without tracking changes. Fields are matched by their JSON tag names.
func (*Flow) SetStrings ¶
SetStrings sets a state string slice field and tracks the change.
func (*Flow) Sleep ¶
Sleep tells the orchestrator to wait for the given duration before the next execution.
func (*Flow) SleepRequested ¶
SleepRequested returns the duration set by Sleep, or zero if not set.
func (*Flow) Snapshot ¶
Snapshot captures a read-only copy of the flow's current state (including any changes applied so far). Pass the returned snapshot to SetChanges to record only the fields that differ.
func (*Flow) Subgraph ¶
Subgraph signals the orchestrator to create and run a child workflow before this step completes. The step is parked until the child finishes - similar to how Interrupt pauses until Resume is called. When the child completes, its final state is filtered through the child's DeclareOutputs and merged into this step's changes using the parent graph's reducers, then the task is re-executed. On re-entry the task sees the child's output in its state and should return normally without calling Subgraph again.
The child's initial state is built from the parent's full state plus the surgraph step's accumulated changes; the explicit input map is then merged on top using the child graph's reducers, and the result is filtered through the child's DeclareInputs.
func (*Flow) SubgraphRequested ¶
SubgraphRequested returns the workflow URL, input state, and true if Subgraph was called.
func (*Flow) UnmarshalJSON ¶
UnmarshalJSON deserializes the Flow including private fields.
type Graph ¶
type Graph struct {
// contains filtered or unexported fields
}
Graph is the definition of a workflow. It describes the tasks, transitions between them, and reducers for merging state during fan-in.
func (*Graph) AddSubgraph ¶
AddSubgraph registers a child workflow as a subgraph node in the graph under the given name, with the given URL as the dispatch target. Same registration semantics as AddTask.
func (*Graph) AddTask ¶
AddTask registers a task node in the graph under the given name, with the given URL as the dispatch target. The first node added becomes the default entry point unless SetEntryPoint is called explicitly. The pseudo-node END is not registered. Re-registering the same name is a no-op.
The same URL may be registered under multiple names. This is how a workflow author reuses the same task code at distinct positions in the graph with different downstream transitions per position.
func (*Graph) AddTransition ¶
AddTransition adds an unconditional transition between two nodes. Both endpoints are auto-registered as tasks if not already present (see autoRegister).
func (*Graph) AddTransitionForEach ¶
AddTransitionForEach adds a dynamic fan-out transition.
func (*Graph) AddTransitionGoto ¶
AddTransitionGoto adds a transition that is only taken when the source task calls flow.Goto with a target that resolves to this transition's destination.
func (*Graph) AddTransitionOnError ¶ added in v1.30.0
AddTransitionOnError adds a transition that is taken when the source task returns an error.
func (*Graph) AddTransitionOnTimeout ¶ added in v1.30.0
AddTransitionOnTimeout adds an error transition that is taken only when the source task's error carries HTTP status 408.
func (*Graph) AddTransitionWhen ¶
AddTransitionWhen adds a conditional transition between two nodes.
func (*Graph) DeclareInputs ¶
DeclareInputs declares which state fields are passed into this graph when used as a subgraph.
func (*Graph) DeclareOutputs ¶
DeclareOutputs declares which state fields are returned from this graph on completion.
func (*Graph) EntryPoint ¶
EntryPoint returns the node name of the entry point of the graph.
func (*Graph) ErrorTransition ¶
func (g *Graph) ErrorTransition(name string) (Transition, bool)
ErrorTransition returns the error transition from the given node name, if one exists.
func (*Graph) FanInFor ¶ added in v1.30.0
FanInFor returns the fan-in node that pops the frame pushed by a fan-out at the named source, or "" if the source is not a fan-out. Populated by Validate.
func (*Graph) HasFanIn ¶ added in v1.30.0
HasFanIn reports whether the graph declares any fan-in nexus.
func (*Graph) IsFanOutSource ¶ added in v1.30.0
IsFanOutSource reports whether the named node has 2+ non-goto/non-error outgoing transitions, or any forEach outgoing transition.
func (*Graph) IsSubgraph ¶
IsSubgraph returns true if the given node name is registered as a subgraph.
func (*Graph) MarshalJSON ¶
MarshalJSON serializes the graph to JSON.
func (*Graph) Mermaid ¶
Mermaid returns a fully-styled Mermaid flowchart representation of the graph, suitable for writing directly to a .mmd file. The output includes the classDef styles, a title node derived from the graph's URL, and per-node class annotations.
Node shapes encode role: regular tasks are rectangles, subgraphs use the double rectangle, forEach targets use a stacked rectangle ("many of these"), and SetFanIn nodes use an inverted trapezoid ("many converging here"). Edges into a SetFanIn node carry a "fan-in" label.
func (*Graph) NamesForURL ¶ added in v1.30.0
NamesForURL returns all node names whose dispatch URL matches the given URL. Empty result means no node uses that URL. Multiple results mean the URL is reused at distinct graph positions.
func (*Graph) SetEntryPoint ¶
SetEntryPoint sets the entry point of the graph explicitly, overriding the default (first task added). The argument is a node name.
func (*Graph) SetFanIn ¶ added in v1.30.0
SetFanIn marks a node as a fan-in nexus. Opts the graph into the lineage validator.
func (*Graph) SetReducer ¶
SetReducer sets the merge strategy for a state field during fan-in.
func (*Graph) SetTimeBudget ¶
SetTimeBudget sets the execution time budget for a specific node, by name.
func (*Graph) TimeBudget ¶
TimeBudget returns the execution time budget for a node by name, or 0 if not set.
func (*Graph) Transitions ¶
func (g *Graph) Transitions() []Transition
Transitions returns the list of transitions in the graph.
func (*Graph) URLOf ¶ added in v1.30.0
URLOf returns the dispatch URL for a node identified by name. Returns the empty string if the name is not registered. END maps to itself.
func (*Graph) UnmarshalJSON ¶
UnmarshalJSON deserializes the graph from JSON.
type Node ¶
Node describes a task or subgraph node registered in a workflow graph. Name is the node's identifier within the graph and the value stored on step rows (microbus_steps.task_name). URL is the dispatch target the foreman calls when the node is reached.
type RawFlow ¶
type RawFlow struct {
Flow
}
RawFlow wraps Flow with additional methods used by the foreman orchestrator. Task endpoints should use Flow directly; RawFlow is for internal orchestration use only.
func NewRawFlow ¶
func NewRawFlow() *RawFlow
NewRawFlow creates a new RawFlow with initialized maps.
func (*RawFlow) ClearChanges ¶
func (f *RawFlow) ClearChanges()
ClearChanges resets the changes map. Called by the orchestrator after persisting changes.
func (*RawFlow) ClearControl ¶
func (f *RawFlow) ClearControl()
ClearControl resets all control signals. Called by the orchestrator after processing them.
func (*RawFlow) RawChanges ¶
RawChanges returns a copy of the raw changes map.
func (*RawFlow) SetAttempt ¶
SetAttempt sets the attempt counter on the flow. Called by the orchestrator before dispatching a task so that Retry can check whether attempts are exhausted.
func (*RawFlow) SetRawChanges ¶
SetRawChanges replaces the entire changes map with the given raw map.
func (*RawFlow) SetRawState ¶
SetRawState replaces the entire state with the given raw map, without tracking changes.
type Reducer ¶
type Reducer string
Reducer defines how concurrent state modifications from parallel tasks are merged during fan-in.
func ReducerForFieldName ¶ added in v1.29.0
ReducerForFieldName returns the reducer inferred from a state field name. Returns empty (replace) if no convention prefix matches.
Conventions:
sum* - numeric add list* - array append set* - polymorphic: array union, object merge
The character right after the prefix must be uppercase to avoid matching English words like "summary", "listening", or "setup".
type Transition ¶
type Transition struct {
From string `json:"from"`
To string `json:"to"`
When string `json:"when,omitzero"`
WithGoto bool `json:"withGoto,omitzero"`
ForEach string `json:"forEach,omitzero"` // dynamic fan-out over a state field
As string `json:"as,omitzero"` // alias for the current element during forEach fan-out
OnError bool `json:"onError,omitzero"` // taken when the source task returns an error
StatusCode int `json:"statusCode,omitzero"`
}
Transition defines a possible transition between two nodes in a workflow graph. From and To are node names, not URLs.