Skip to content

Commit 3e6d471

Browse files
Document replay-critical history event wire formats
Issue: zorporation/durable-workflow#495 Loop-ID: build-02
1 parent 68d73ed commit 3e6d471

2 files changed

Lines changed: 448 additions & 0 deletions

File tree

docs/api-stability.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,37 @@ Renaming, removing, or repurposing a field in any published event is a
117117
protocol break — not a minor-version change — regardless of whether
118118
the PHP class that produced the event is `@internal`.
119119

120+
Every stable event schema must name both its frozen payload keys and at
121+
least one replay or projection consumer. Frequently replayed event
122+
families are enumerated first because they sit on the hot path for
123+
cross-SDK replay:
124+
125+
| event | frozen payload keys | primary replay / projection consumers |
126+
| --- | --- | --- |
127+
| `WorkflowStarted` | `workflow_class`, `workflow_type`, `workflow_instance_id`, `workflow_run_id`, `workflow_command_id`, `business_key`, `visibility_labels`, `memo`, `search_attributes`, `execution_timeout_seconds`, `run_timeout_seconds`, `execution_deadline_at`, `run_deadline_at`, `workflow_definition_fingerprint`, `declared_queries`, `declared_query_contracts`, `declared_signals`, `declared_signal_contracts`, `declared_updates`, `declared_update_contracts`, `declared_entry_method`, `declared_entry_mode`, `declared_entry_declaring_class` | `WorkflowDefinitionFingerprint`, `RunLineageView`, worker history payload consumers |
128+
| `ActivityScheduled` | `activity_execution_id`, `activity_class`, `activity_type`, `sequence`, `activity` | `WorkflowStepHistory`, `WorkflowExecutor`, `QueryStateReplayer`, `ActivityRecovery` |
129+
| `ActivityCompleted` | `activity_execution_id`, `activity_attempt_id`, `activity_class`, `activity_type`, `sequence`, `attempt_number`, `result`, `payload_codec`, `activity`, `parallel_group_path` | `WorkflowExecutor`, `QueryStateReplayer`, `ParallelChildGroup`, `ActivityRecovery` |
130+
| `TimerScheduled` | `timer_id`, `sequence`, `delay_seconds`, `fire_at`, `timer_kind`, `condition_wait_id`, `condition_key`, `condition_definition_fingerprint`, `signal_wait_id`, `signal_name` | `WorkflowStepHistory`, `QueryStateReplayer`, `RunTimerView`, `ConditionWaits`, `SignalWaits` |
131+
| `TimerFired` | `timer_id`, `sequence`, `delay_seconds`, `fired_at`, `timer_kind`, `condition_wait_id`, `condition_key`, `condition_definition_fingerprint`, `signal_wait_id`, `signal_name` | `WorkflowStepHistory`, `QueryStateReplayer`, `RunTimerView`, `ConditionWaits`, `SignalWaits` |
132+
| `SignalReceived` | `workflow_command_id`, `signal_id`, `workflow_instance_id`, `workflow_run_id`, `signal_name`, `signal_wait_id` | `SignalWaits`, `RunSignalView`, worker history payload consumers |
133+
| `SignalApplied` | `workflow_command_id`, `signal_id`, `signal_name`, `signal_wait_id`, `sequence`, `value` | `WorkflowStepHistory`, `SignalWaits`, `RunSignalView`, `QueryStateReplayer` |
134+
| `UpdateAccepted` | `workflow_command_id`, `update_id`, `workflow_instance_id`, `workflow_run_id`, `update_name`, `arguments` | `RunUpdateView`, worker history payload consumers |
135+
| `UpdateApplied` | `workflow_command_id`, `update_id`, `workflow_instance_id`, `workflow_run_id`, `update_name`, `arguments`, `sequence` | `QueryStateReplayer`, `RunUpdateView`, worker history payload consumers |
136+
| `UpdateCompleted` | `workflow_command_id`, `update_id`, `workflow_instance_id`, `workflow_run_id`, `update_name`, `sequence`, `result` | `RunUpdateView`, worker history payload consumers |
137+
| `ConditionWaitOpened` | `condition_wait_id`, `condition_key`, `condition_definition_fingerprint`, `sequence`, `timeout_seconds` | `WorkflowStepHistory`, `ConditionWaits`, worker history payload consumers |
138+
| `SideEffectRecorded` | `sequence`, `result` | `WorkflowStepHistory`, `WorkflowExecutor`, `QueryStateReplayer` |
139+
| `VersionMarkerRecorded` | `sequence`, `change_id`, `version`, `min_supported`, `max_supported` | `WorkflowStepHistory`, `WorkflowExecutor`, `QueryStateReplayer` |
140+
| `ChildWorkflowScheduled` | `sequence`, `workflow_link_id`, `child_call_id`, `child_workflow_instance_id`, `child_workflow_run_id`, `child_workflow_class`, `child_workflow_type`, `parent_close_policy`, `retry_policy`, `timeout_policy` | `WorkflowStepHistory`, `WorkflowExecutor`, `QueryStateReplayer`, `ChildRunHistory`, `RunLineageView` |
141+
| `ChildRunStarted` | `sequence`, `workflow_link_id`, `child_call_id`, `child_workflow_instance_id`, `child_workflow_run_id`, `child_workflow_class`, `child_workflow_type`, `child_run_number`, `retry_policy`, `timeout_policy`, `execution_timeout_seconds`, `run_timeout_seconds`, `execution_deadline_at`, `run_deadline_at` | `ChildRunHistory`, `RunLineageView`, worker history payload consumers |
142+
| `ChildRunCompleted` | `sequence`, `workflow_link_id`, `child_call_id`, `child_workflow_instance_id`, `child_workflow_run_id`, `child_workflow_class`, `child_workflow_type`, `child_run_number`, `child_status`, `closed_reason`, `closed_at`, `output`, `parallel_group_path` | `WorkflowExecutor`, `QueryStateReplayer`, `ChildRunHistory`, `ParallelChildGroup`, `RunLineageView` |
143+
144+
The key list is a wire-format list, not a promise that every event row
145+
contains every key. Some keys are optional because older rows predate a
146+
projection, a branch does not have that attribute, or `array_filter`
147+
omitted a null value. Consumers must continue to accept missing optional
148+
keys indefinitely. Producers must not rename, remove, or change the type
149+
or meaning of an existing key.
150+
120151
### `VersionMarkerRecorded`
121152

122153
This marker records the result of `Workflow::getVersion()`, `Workflow::patched()`,

0 commit comments

Comments
 (0)