Summary#
subscribe declares that a workflow state is listening for an event, and configures that wait — who may fill it, when
it is armed, what must hold first, and what it promises. It is config only: the guarded routes that fire when the
event arrives (on Event when (…) { … goto … }) live at the state level alongside the wait, not inside the
subscribe block.
Signature#
subscribe <Event>(<typed params>) [as <Alias>] [foreach (<T> <x> in <collection>)] {
Candidates = <principal => bool> | <() => List<Principal>>; // who may HOLD or satisfy it
Reassign = <actor => bool>; // who may hand it ON
Assignee = <expr>; // who it is handed to at arm time
When = <predicate>; // whether it is armed on this run at all
After = [<Slot>, …]; // slots that must be satisfied first
Assigned { … } // the pickup promise — Within, Remind, a breach arm
Finished { … } // the completion promise
Requires { … } // named preconditions on filling it
}
subscribe <Event>(); // bodyless — a wait with no configurationDescription#
A workflow state advances when an event it subscribes to arrives and a matching route transitions it. subscribe
names that event and restates its typed parameters (so the payload is visible at the handler), then configures the
wait itself. Each setting has its own page — see See also — and the shape to hold is that they answer
different questions:
| setting | question |
|---|---|
Candidates | who may hold or satisfy this slot |
Reassign | who besides the holder may move it |
Assignee | who it belongs to from the moment it is armed (a slot with one is not a pool slot) |
When | whether this run gets the slot at all |
After | which sibling slots must be satisfied before it opens |
The promises — how long a slot may sit unclaimed, how long its holder has, the nudges along the way, the retries,
and where a missed one routes — are declared in the Assigned/Finished blocks inside the
slot, not as flat settings on it. That is where Within, Remind, Retries, Backoff and the Unassigned /
Unfinished / Exhausted arms live.
A slot's success routes (on <Event> when (…), on <Alias>(…)) and the state's own timers (on Expire,
on Deadline) live at the state level, not inside the subscribe — every on … in one place.
An entity-typed parameter is a live row, not a copy. A route may read it and write through it, exactly as it can through the workflow's own tracked item, and those writes are saved with the rest of the transition:
event CustomerWithdrawsItem(OrderItem item);
on CustomerWithdrawsItem(OrderItem item) {
item.Status = ItemStatus.Withdrawn; // persisted with the transition
RefundItem(item);
}The event's delivery context (who deposited, the claim) is available to a route that opts into a Deposit
parameter — see <span class="planned" title="this page is planned and not written yet">workflow-route</span>; it is never ambient.
A state may hold more than one subscribe (multi-wait / N-of-M); that is its own surface — see <span class="planned" title="this page is planned and not written yet">workflow-multiwait</span>.
Examples#
A pool slot the support team may take, a supervisor may move, and which promises to be picked up within an hour:
subscribe Respond() as Reply {
Candidates = u => u.Team == Team.Support && u.OnDuty;
Reassign = a => a.IsSupervisor;
Assigned { Within = TimeSpan.FromHours(1); Unassigned { goto Escalated; } }
}The same wait as an app writes it, in context:
Minimal — a wait with no config, just the event:
subscribe Submit();See also#
- Candidates (slot) — the slot's
Candidatesgate: who may HOLD/satisfy this slot (predicate or computed set), and how a screen ASKS it before offering a button:<Wf>.For(item).<Slot>.Candidates(u) - Assign — handing a slot to a named colleague —
Reassign, and the verbs that hand a slot to a named colleague - Assigned / Finished (milestones) — the
Assigned/Finishedpromises declared inside the slot:Within,Remind,Retries,Backoff, and the breach arms - slot dependencies (After / When / Pending) —
After: the sibling slots that must be satisfied before this one opens - Requires — named preconditions, and the live checklist —
Requires: named preconditions on filling the slot, and the live checklist that reports them - <span class="planned" title="this page is planned and not written yet">workflow-event</span> — the
eventthis subscribes to (a method signature) - <span class="planned" title="this page is planned and not written yet">workflow-route</span> — the state-level
on <Event> … goto …routes that consume the deposit - <span class="planned" title="this page is planned and not written yet">workflow-state</span> — the enclosing state and its
Expiredeadline - Tracks and Initial (the field a workflow drives) — how the workflow binds to an entity's enum property