@@ -36,6 +36,10 @@ durable execution with minimal operational complexity.
3636 discovery paths, and optional ignore patterns for CLI commands. It typically
3737 imports the shared ` backend ` from ` openworkflow/client.* ` so app code and CLI
3838 use the same connection.
39+ - ** Signal** : A named, point-in-time message sent to all workflows currently
40+ waiting on that signal name. Signals carry an optional JSON payload. When
41+ sent, a row is written to ` workflow_signals ` for each waiting workflow and
42+ the workflow is woken. If no workflow is waiting, the signal is dropped.
3943- ** ` availableAt ` ** : A critical timestamp on a workflow run that controls its
4044 visibility to workers. It is used for scheduling, heartbeating, crash
4145 recovery, and durable timers.
@@ -105,6 +109,7 @@ of coordination. There is no separate orchestrator server.
105109 | |
106110 | - workflow_runs |
107111 | - step_attempts |
112+ | - workflow_signals |
108113 +------------------------------+
109114```
110115
@@ -122,9 +127,10 @@ of coordination. There is no separate orchestrator server.
122127 ` npx @openworkflow/cli worker start ` with
123128 auto-discovery of workflow files.
124129- ** Backend** : The source of truth. It stores workflow runs and step attempts.
125- The ` workflow_runs ` table serves as the job queue for the workers, while the
126- ` step_attempts ` table serves as a record of started and completed work,
127- enabling memoization.
130+ The ` workflow_runs ` table serves as the job queue for the workers, the
131+ ` step_attempts ` table serves as a record of started and completed work
132+ enabling memoization, and the ` workflow_signals ` table records signal
133+ deliveries so a waking workflow can read the payload.
128134
129135### 2.3. Basic Execution Flow
130136
@@ -149,7 +155,7 @@ of coordination. There is no separate orchestrator server.
149155 ` step_attempt ` record with status ` running ` , executes the step function, and
150156 then updates the ` step_attempt ` to ` completed ` upon completion. The Worker
151157 continues executing inline until the workflow code completes or encounters a
152- sleep.
158+ durable wait such as sleep, child-workflow waiting, or signal waiting .
1531596 . ** State Update** : The Worker updates the Backend with each ` step_attempt ` as
154160 it is created and completed, and updates the status of the ` workflow_run `
155161 (e.g., ` completed ` , ` running ` for parked waits).
@@ -234,10 +240,34 @@ target workflow name in `spec`) and `options.timeout` controls the wait timeout
234240(default 1y). When the timeout is reached, the parent step fails but the child
235241workflow continues running independently.
236242
237- All step APIs (` step.run ` , ` step.sleep ` , and ` step.runWorkflow ` ) share the same
238- collision logic for durable keys. If duplicate base names are encountered in one
239- execution pass, OpenWorkflow auto-indexes them as ` name ` , ` name:1 ` , ` name:2 ` ,
240- and so on so each step call maps to a distinct step attempt.
243+ ** ` step.sendSignal(options) ` ** : Sends a named signal to all workflows currently
244+ waiting on it. The send is recorded as a step attempt so it won't repeat on
245+ replay. If no workflow is waiting, the signal is silently dropped.
246+
247+ ``` ts
248+ await step .sendSignal ({
249+ signal: ` approval:${orderId } ` ,
250+ data: { approved: true },
251+ });
252+ ```
253+
254+ ** ` step.waitForSignal(options) ` ** : Parks the workflow until a matching signal
255+ arrives or the timeout expires. When a signal is sent targeting this signal
256+ name, a delivery row is written to ` workflow_signals ` and the workflow is woken.
257+ If the timeout expires first, the step resolves with ` null ` .
258+
259+ ``` ts
260+ const data = await step .waitForSignal ({
261+ signal: ` approval:${orderId } ` ,
262+ timeout: " 7d" ,
263+ });
264+ ```
265+
266+ All step APIs (` step.run ` , ` step.sleep ` , ` step.runWorkflow ` , ` step.sendSignal ` ,
267+ and ` step.waitForSignal ` ) share the same collision logic for durable keys. If
268+ duplicate base names are encountered in one execution pass, OpenWorkflow
269+ auto-indexes them as ` name ` , ` name:1 ` , ` name:2 ` , and so on so each step call
270+ maps to a distinct step attempt.
241271
242272## 4. Error Handling & Retries
243273
0 commit comments