Summary
Add support for non-blocking signal and update handlers.
Today, listen is intentionally blocking:
query registers a handler and continues execution
signal blocks until a matching signal is received
update blocks until a matching update is received
This works well for approval workflows and other wait-for-event patterns, but makes it difficult to model long-running entity-style workflows that must continue executing while still accepting external messages.
Motivation
Temporal supports message handlers that can execute independently of the main workflow path.
Examples:
In these scenarios, the workflow should continue running while remaining responsive to external messages.
Currently, Zigflow users must model signals and updates as explicit blocking steps in the workflow, which prevents this style of workflow.
Proposed design
Introduce a dedicated non-blocking message handler construct rather than extending the semantics of listen.
Example:
handlers:
signals:
cancel:
set:
cancelled: true
updates:
setPriority:
set:
priority: ${ .priority }
Alternative syntaxes are possible.
The important behaviour is:
- Handlers are registered when the workflow starts
- Handlers remain active for the lifetime of the workflow
- Handlers do not block workflow execution
- Handlers may modify workflow state
- Queries can observe state modified by handlers
Continue-As-New considerations
Non-blocking handlers must survive Continue-As-New.
The runtime should:
- Re-register handlers on the continued execution
- Preserve any state mutations made by handlers
- Continue routing signals and updates addressed to the Workflow ID
Open questions
- Should handlers be allowed to execute activities?
- Should handlers be allowed to mutate
$context, $data, or both?
- Should handlers be able to return values directly (update-style responses)?
- What concurrency guarantees should exist when handlers and workflow execution modify the same state?
- Should handler definitions be a new top-level section (
handlers) or an extension of listen?
Acceptance criteria
- Users can define non-blocking signal handlers
- Users can define non-blocking update handlers
- Workflow execution continues while handlers remain active
- Handler state changes are visible to queries
- Handlers survive Continue-As-New
- Documentation and examples are provided
- E2E tests cover signal, update and Continue-As-New behaviour
Summary
Add support for non-blocking signal and update handlers.
Today,
listenis intentionally blocking:queryregisters a handler and continues executionsignalblocks until a matching signal is receivedupdateblocks until a matching update is receivedThis works well for approval workflows and other wait-for-event patterns, but makes it difficult to model long-running entity-style workflows that must continue executing while still accepting external messages.
Motivation
Temporal supports message handlers that can execute independently of the main workflow path.
Examples:
Order workflow
Subscription workflow
Batch processing workflow
In these scenarios, the workflow should continue running while remaining responsive to external messages.
Currently, Zigflow users must model signals and updates as explicit blocking steps in the workflow, which prevents this style of workflow.
Proposed design
Introduce a dedicated non-blocking message handler construct rather than extending the semantics of
listen.Example:
Alternative syntaxes are possible.
The important behaviour is:
Continue-As-New considerations
Non-blocking handlers must survive Continue-As-New.
The runtime should:
Open questions
$context,$data, or both?handlers) or an extension oflisten?Acceptance criteria