Skip to content

feat: Implement Signals — step.waitForSignal / step.sendSignal / sendSignal#369

Draft
thejustinwalsh wants to merge 5 commits intoopenworkflowdev:mainfrom
thejustinwalsh:copilot/implement-signals-feature
Draft

feat: Implement Signals — step.waitForSignal / step.sendSignal / sendSignal#369
thejustinwalsh wants to merge 5 commits intoopenworkflowdev:mainfrom
thejustinwalsh:copilot/implement-signals-feature

Conversation

@thejustinwalsh
Copy link

Builds on #350 (signals seed by @octoper), keeping the API surface identical while fixing bugs, hardening durability, and adding two missing features from the competitive analysis.

Summary

Open Questions

  • Removed ow.defineSignalSpec() instance method as a redundant delegation to the module-level export. Should it be kept for DX consistency?
  • Are there any other signal features that are in scope with the initial implementation?
    • event match/filter
    • non-blocking handlers
    • queries

Bugs fixed

  • Signal pre-pass ordering (execution.ts): upstream threw SleepSignal at the first undelivered signal, silently skipping later-delivered ones in Promise.all([waitForSignal("A"), waitForSignal("B")]). Fixed with a two-phase approach.
  • failStepAttempt return value: upstream used a shallow spread copy instead of the persisted backend result. Consistent with completeStepAttempt usage.
  • Signal timeout invisible to resolveEarliestRunningWaitResumeAt: parallel sleep + waitForSignal(timeout) could sleep past the signal timeout.

New features

  • Signal buffering: sendSignal before waitForSignal parks now succeeds (pre-delivery). Matches Temporal / Inngest / Restate behaviour. Atomic per-backend (worker_id IS NULL guard prevents race with active execution).
  • step.sendSignal(targetRunId, nameOrSpec, payload?, options?): durable cross-workflow signaling from within a workflow function, memoized like step.run(). Config stores {targetRunId, signalName} for observability.
  • Single-query CTE for Postgres deliverSignal: replaced 2-round-trip approach with an atomic CTE.

Tests

95 passing execution tests (+14 net new vs #350), 224 backend tests.


Full details of development choices and itterations: thejustinwalsh#1

Copilot AI and others added 5 commits March 4, 2026 17:44
…d SignalTimeoutError

Co-authored-by: thejustinwalsh <72912+thejustinwalsh@users.noreply.github.com>
Co-authored-by: thejustinwalsh <72912+thejustinwalsh@users.noreply.github.com>
…ignal parks

Co-authored-by: thejustinwalsh <72912+thejustinwalsh@users.noreply.github.com>
Co-authored-by: thejustinwalsh <72912+thejustinwalsh@users.noreply.github.com>
@thejustinwalsh thejustinwalsh changed the title Copilot/implement signals feature feat: Implement Signals — step.waitForSignal / step.sendSignal / sendSignal Mar 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants