Skip to content

Workflow engine reference

Lookup tables for the workflow engine. The concepts are in the model and the runtime. Namespaces are Cratis.Choreography.Workflows and its children (Graphs, Adapters, Waits, Triggers, Runs); the Chronicle types are in Cratis.Choreography.Chronicle.Workflows.

WorkflowNodeKindPerformed byConfigurationTypical outlets
TriggerThe engine, with the trigger’s payload as outputnonenext
ActionAn IWorkflowNodePerformer in a job stepadapter-definednext, failed, fallback
DecisionAn IWorkflowNodePerformer in a job stepadapter-definedthe decision’s own, failed, fallback
WaitThe engine opens a waitWaitConfigurationelapsed, resumed, cancelled, expired
ApprovalThe engine opens an approval waitWaitConfigurationapproved, rejected, expired
ForEachThe engine fans outForEachConfigurationeach
JoinThe engine gathers the branchesJoinConfigurationcompleted, partial

A node’s Outlets are what the author declared; the engine does not derive them from the kind. A node record is WorkflowNode(Id, Kind, Capability, Configuration, Outlets, Policy), an edge is WorkflowEdge(From, Outlet, To).

Configuration is JSON text in WorkflowNodeConfiguration, read with camelCase property names, enums as camelCase strings and a TimeSpan as [d.]hh:mm:ss. It never holds a secret.

NodePropertyMeaning
Waitkindsignal or timer (WaitKind)
WaitafterHow long a timer waits
WaitexpiresAfterHow long a signal or approval waits before it expires; zero waits forever
WaitsignalThe contract a signal wait accepts, {"id":"payment-received","version":1}; default is any
ApprovalexpiresAfterAs for a wait. An approval node is always an approval, whatever kind says
ForEachitemsFromThe node whose output holds the items
ForEachitemsPropertyThe property of that output holding the list
ForEachmaxParallelismHow many branch executions may be scheduled at once; values below 1 become 1
JoinforEachThe ForEach it joins
Joinmodeall, any or atLeast
JointhresholdHow many branches must succeed for atLeast

Every item in the list must be an object with a unique, non-empty string key; the key names the branch. A missing or repeated key fails the ForEach with InvalidOutput.

WorkflowNodePolicy(MaxAttempts, AttemptTimeout, RetryDelay, MaxVisits). WorkflowNodePolicy.Default is one attempt of at most ten minutes, a 30 second retry delay and one visit. A node on a cycle needs MaxVisits above 1, or the graph is refused.

The twelve names in WellKnownOutlets:

OutletTaken
nextAs the ordinary way on
failedWhen a node failed for good
fallbackWhen a node answered with an outlet it does not declare, or output that is not usable, and fallback is connected
eachOnce per item by a ForEach
completedBy a join whose mode was satisfied
partialBy a join whose mode was not satisfied once every branch had ended
resumedBy a signal wait that was resumed
elapsedBy a timer wait once its time has come
expiredBy a signal or approval wait that ran out of time
approvedBy an approval that was given
rejectedBy an approval that was refused
cancelledBy a signal wait that was called off
WorkflowFailureKindCauseRetriedRouted through
ErrorThe performer reported a failure or threwwhile attempts remainfailed
TimedOutThe attempt ran past AttemptTimeoutwhile attempts remainfailed
InvalidOutletThe performer answered with an undeclared outletnofallback, else failed
InvalidOutputOutput was not JSON, too large, or not the shape needednofallback, else failed
PerformerMissingNo performer is registered for the capabilitynofailed
VisitLimitExceededThe node was reached more often than MaxVisitsnonothing: unrouted

A failure with no connected outlet is unrouted. In the root branch it fails the run; in a ForEach branch it only ends the branch. A retry becomes due RetryDelay after the failed attempt.

TypeValues
WorkflowNodeOutcomeStatusSucceeded (leaves through an outlet), Skipped (the branch ends there, not a failure), Failed, Ambiguous (never retried)
WaitKindSignal (resolved through resumed or cancelled, or expired when time runs out), Timer (leaves through elapsed when its time comes), Approval (resolved through approved or rejected, or expired)
JoinModeAll (every branch succeeded), Any (at least one), AtLeast (at least threshold)

A skipped branch counts as succeeded for a join. A join fires as soon as its mode is satisfied, or once every branch has ended. Its output is every branch’s key, status, outlet and output, keyed by branch. A wait can be resolved or expired only while open: whichever is recorded first wins.

TypeValues
WorkflowRunStatusRunning, Waiting, Succeeded, Failed, Cancelled, ReconciliationRequired
NodeExecutionStatusPending, Scheduled, Waiting, Succeeded, Failed, Skipped, Unreachable, Cancelled, ReconciliationRequired, RetryPending

StructuralAdmissionPolicy refuses a graph with any of these WorkflowStructureViolationKind values: NoTrigger, MoreThanOneTrigger, UnknownNode, UndeclaredOutlet, ForEachWithoutSingleJoin, NestedForEachNotSupported, UnboundedCycle (a cycle through a node with MaxVisits of 1 or less), InvalidConfiguration and DuplicateNode.

WorkflowTriggerKindStarted by
ManualA person or code, through IWorkflows.Start
SignalA signal from outside
StageHookA state machine entering a state, through StartWorkflow
ScheduleA schedule

The engine records the kind and does not branch on it. WorkflowData, which carries payloads, inputs, outputs and signal payloads, is JSON of at most 32 KiB (WorkflowData.MaxBytes); larger content is stored by the adapter and referred to. Run input is { "trigger": { payload, subject, correlation }, "nodes": { id: output }, "item": ... }.

CronExpression.Parse reads five space-separated fields, evaluated in UTC: minute (0-59), hour (0-23), day of month (1-31), month (1-12) and day of week (0-6, with 7 also Sunday). Each field is *, a number, a range a-b, a step */n or a-b/n, or a comma-separated list of those. Names such as MON are not supported. When both day of month and day of week are restricted, either matching is enough, as in classic cron. Anything else throws InvalidCronExpression.

ExpressionFires
0 6 * * 1-506:00 UTC on weekdays
*/15 * * * *Every 15 minutes
0 0 1 * *Midnight UTC on the first of each month

The journal records the types in WorkflowRunFacts.Types, named by their bare type name: WorkflowRunAdmitted, WorkflowNodeScheduled, WorkflowNodeOperationCompleted, WorkflowNodeSucceeded, WorkflowNodeSkipped, WorkflowNodeAttemptFailed, WorkflowNodeFailed, WorkflowNodeOutcomeAmbiguous, WorkflowNodesUnreachable, WorkflowBranchesFannedOut, WorkflowBranchesJoined, WorkflowWaitOpened, WorkflowWaitResolved, WorkflowWaitCancelled, WorkflowRunSucceeded, WorkflowRunFailed, WorkflowRunCancelled, WorkflowRunNeedsReconciliation, WorkflowNodeInputPinned and WorkflowJobStopped.