Failed-run redrive recovers more workflows: workflow-code memo and search-attribute upserts, applied signal waits, and failures in workflow code, including onto a corrected definition when you ask for it.
Redrive (#864)
- Workflow-code upserts (#1001):
MemoUpsertedandSearchAttributesUpsertedsteps in the completed prefix are reused at their original time. Memo and search-attribute rows carry to the successor unchanged, so a successor that fails again can be redriven again. - Applied signal waits (#1002): a signal wait (
await('name')) that received and applied its signal is reused with its value and original time. The message cursor carries over, so a consumed signal isn't delivered again. - Workflow-code and structural-limit failures (#1004):
WorkflowFailednow recordsfailed_step_sequencewithfailed_step_kindworkflow_codeorstructural_limit, and the successor resumes at that step.- On the same definition, a workflow-code failure is refused, because the same code would throw again. A structural-limit failure may redrive.
- Corrected definition, opt-in only (#1004): pass
allow_definition_change: true.- Inside the redrive transaction, the new code replays the reused prefix in memory, bounded by the history budget, before anything is written.
- An accepted change records
definition_changed_fromon the successor'sWorkflowStarted. Run detail shows it asworkflow_definition_changed_from, and describe asrun.definition_changed_from. A later redrive on the same definition records none.
Upgrade notes
-
Rollback. Releases before 2.19.0 ignore
reused_recorded_aton the signal, memo and search-attribute events that a 2.19.0 redrive successor reuses. Replaying such a successor on an older release can change its workflow time and the deadlines derived from it. Once a 2.19.0 redrive successor with reused signal waits or upserts exists, keep 2.19.0 or later workers, or confirm that no such history can replay before rolling back. -
New
failed_step_kindvalues.workflow_codeandstructural_limitjoinactivity. Readers that switch onfailed_step_kindshould accept them. Failures written by earlier releases have no boundary and still refuse redrive withunrecorded_failure_boundary. -
allow_definition_changeis an explicit opt-in. Without it, a changed definition is refused as before. Runs started by a service worker are always refused withdefinition_change_requires_replay_check, even if a local class is registered for the type later. -
New typed refusals:
workflow_code_failure_requires_corrected_definitiondefinition_incompatible_with_prefix, withdefinition_mismatch {sequence, kind}definition_check_over_budgetdefinition_change_requires_replay_checkunsupported_signal_wait,unsupported_pending_signal,incomplete_signal_step,mismatched_signal_receipt,external_signal_payload_not_supportedservice_redrive_history_not_qualified
unsupported_visibility_metadatanow refuses only a workflow-code row with no matching reused upsert step. -
Service mode (#1006):
- A run a service worker started is refused redrive with
service_redrive_history_not_qualifiedwhen its completed prefix has a memo upsert, search-attribute upsert or signal wait to reuse. The refusal happens before any write. The fence lifts only through a replay-capability check once durable-workflow/sdk-python#235, durable-workflow/sdk-php#244 and durable-workflow/sdk-rust#172 ship installed-qualified. - Service runs whose prefix holds only activities, side effects, version markers and fired timers redrive as in 2.18.0. That SDK replay is qualified: Python 2.13.1 and PHP 3.8.3 installed-qualified, Rust 4.11.0 last fully qualified, with Rust's lifecycle open in durable-workflow/sdk-rust#170.
- Native Server redrive parity is still open in durable-workflow/server#980.
- A run a service worker started is refused redrive with
Main CI was green at 28893f97 (merge of #1005). Release Verification runs on this tag.