@workflow/core 5.0.0-beta.40 → 5.0.0-beta.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/events-consumer.d.ts +127 -6
- package/dist/events-consumer.d.ts.map +1 -1
- package/dist/events-consumer.js +364 -50
- package/dist/private.d.ts +87 -18
- package/dist/private.d.ts.map +1 -1
- package/dist/private.js +116 -44
- package/dist/runtime/constants.d.ts +15 -1
- package/dist/runtime/constants.d.ts.map +1 -1
- package/dist/runtime/constants.js +22 -3
- package/dist/runtime/helpers.d.ts +116 -8
- package/dist/runtime/helpers.d.ts.map +1 -1
- package/dist/runtime/helpers.js +174 -2
- package/dist/runtime/quickjs-assets.generated.d.ts.map +1 -1
- package/dist/runtime/quickjs-assets.generated.js +2 -2
- package/dist/runtime/quickjs-entrypoint.d.ts.map +1 -1
- package/dist/runtime/quickjs-entrypoint.js +13 -5
- package/dist/runtime/quickjs-runtime.d.ts +36 -1
- package/dist/runtime/quickjs-runtime.d.ts.map +1 -1
- package/dist/runtime/quickjs-runtime.js +613 -185
- package/dist/runtime/quickjs-serde.d.ts +107 -0
- package/dist/runtime/quickjs-serde.d.ts.map +1 -0
- package/dist/runtime/quickjs-serde.js +2098 -0
- package/dist/runtime/replay-budget.d.ts +5 -14
- package/dist/runtime/replay-budget.d.ts.map +1 -1
- package/dist/runtime/replay-budget.js +19 -72
- package/dist/runtime/resume-hook.d.ts.map +1 -1
- package/dist/runtime/resume-hook.js +5 -1
- package/dist/runtime/runs.d.ts.map +1 -1
- package/dist/runtime/runs.js +3 -4
- package/dist/runtime/start.js +2 -7
- package/dist/runtime/step-executor.d.ts.map +1 -1
- package/dist/runtime/step-executor.js +1 -4
- package/dist/runtime/suspension-handler.d.ts +7 -0
- package/dist/runtime/suspension-handler.d.ts.map +1 -1
- package/dist/runtime/suspension-handler.js +58 -11
- package/dist/runtime/world-compatibility.d.ts +15 -0
- package/dist/runtime/world-compatibility.d.ts.map +1 -1
- package/dist/runtime/world-compatibility.js +25 -5
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +474 -418
- package/dist/serialization/codec-devalue-vm.d.ts +7 -0
- package/dist/serialization/codec-devalue-vm.d.ts.map +1 -1
- package/dist/serialization/codec-devalue-vm.js +12 -1
- package/dist/serialization/workflow-vm.d.ts +8 -3
- package/dist/serialization/workflow-vm.d.ts.map +1 -1
- package/dist/serialization/workflow-vm.js +9 -4
- package/dist/step.js +2 -2
- package/dist/telemetry/semantic-conventions.d.ts +23 -0
- package/dist/telemetry/semantic-conventions.d.ts.map +1 -1
- package/dist/telemetry/semantic-conventions.js +18 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +2 -2
- package/dist/vm/index.d.ts.map +1 -1
- package/dist/vm/index.js +9 -6
- package/dist/workflow/abort-controller.d.ts.map +1 -1
- package/dist/workflow/abort-controller.js +4 -6
- package/dist/workflow/attribute-dispatcher.js +2 -2
- package/dist/workflow/hook.js +2 -2
- package/dist/workflow/sleep.js +2 -2
- package/dist/workflow.d.ts +10 -0
- package/dist/workflow.d.ts.map +1 -1
- package/dist/workflow.js +60 -19
- package/docs/how-it-works/event-sourcing.mdx +11 -3
- package/package.json +6 -6
- package/dist/correlation-id.d.ts +0 -109
- package/dist/correlation-id.d.ts.map +0 -1
- package/dist/correlation-id.js +0 -139
- package/dist/serialization/vm-bundle-entry.d.ts +0 -12
- package/dist/serialization/vm-bundle-entry.d.ts.map +0 -1
- package/dist/serialization/vm-bundle-entry.js +0 -58
|
@@ -6,6 +6,15 @@ import { type Event } from '@workflow/world';
|
|
|
6
6
|
* in host). Any subscribe() arriving during this window cancels the check.
|
|
7
7
|
*/
|
|
8
8
|
export declare const DEFERRED_CHECK_DELAY_MS = 100;
|
|
9
|
+
/**
|
|
10
|
+
* Floor for the deferred-check delay, so a too-low override can't manufacture
|
|
11
|
+
* spurious divergence (each false positive burns a divergence-recovery retry
|
|
12
|
+
* and can escalate to a terminal `CorruptedEventLogError`).
|
|
13
|
+
*
|
|
14
|
+
* Exported so tests needing the shortest legal delay can ask for it instead of
|
|
15
|
+
* hardcoding a number this floor would silently clamp up.
|
|
16
|
+
*/
|
|
17
|
+
export declare const MIN_DEFERRED_CHECK_DELAY_MS = 10;
|
|
9
18
|
export declare enum EventConsumerResult {
|
|
10
19
|
/**
|
|
11
20
|
* Callback consumed the event, but should not be removed from the callbacks list
|
|
@@ -43,18 +52,72 @@ export interface EventsConsumerOptions {
|
|
|
43
52
|
* deserialization delays the resolve() that triggers the next subscribe().
|
|
44
53
|
*/
|
|
45
54
|
getPromiseQueue: () => Promise<void>;
|
|
55
|
+
/**
|
|
56
|
+
* Whether no data delivery is in flight (`isDeliveryIdle` in private.ts).
|
|
57
|
+
* The unconsumed-event check waits for this before it fires: a delivery in
|
|
58
|
+
* flight means the workflow VM is mid-reaction, and an event it has not
|
|
59
|
+
* claimed yet is an event it has not reached yet.
|
|
60
|
+
*
|
|
61
|
+
* Required rather than defaulting to always-idle: always-idle is exactly the
|
|
62
|
+
* pre-gate behaviour, so a defaulted option would let a construction site opt
|
|
63
|
+
* a whole replay path back out without saying so. Tests that drive a consumer
|
|
64
|
+
* with no orchestrator context pass `() => true` to keep the pre-existing
|
|
65
|
+
* timing, and say so at the call site.
|
|
66
|
+
*/
|
|
67
|
+
isDeliveryIdle: () => boolean;
|
|
46
68
|
}
|
|
47
69
|
export declare class EventsConsumer {
|
|
48
70
|
eventIndex: number;
|
|
49
71
|
readonly events: Event[];
|
|
50
72
|
readonly callbacks: EventConsumerCallback[];
|
|
73
|
+
/**
|
|
74
|
+
* Events the ordered walk stepped over because nobody claimed them and their
|
|
75
|
+
* type carries no ordering claim. Each keeps the index it held in the log:
|
|
76
|
+
* consumers read {@link eventIndex} at consumption time to order their
|
|
77
|
+
* delivery against the rest of the log, and a late delivery must still make
|
|
78
|
+
* the claim its position gave it.
|
|
79
|
+
*
|
|
80
|
+
* Held in log order, drained in log order, and drained before every offer so
|
|
81
|
+
* a consumer registered after the walk passed the event still receives it.
|
|
82
|
+
*/
|
|
83
|
+
private readonly parked;
|
|
84
|
+
/**
|
|
85
|
+
* Correlation ids of the {@link ONE_SHOT_EVENT_TYPES} events consumed so
|
|
86
|
+
* far, so a second resolution for one of them is recognized as unclaimable
|
|
87
|
+
* rather than parked for a consumer that cannot exist.
|
|
88
|
+
*/
|
|
89
|
+
private readonly resolved;
|
|
51
90
|
private onConsumedEvent?;
|
|
52
91
|
private onUnconsumedEvent;
|
|
53
92
|
private getPromiseQueue;
|
|
93
|
+
private isDeliveryIdle;
|
|
54
94
|
private pendingUnconsumedCheck;
|
|
55
95
|
private pendingUnconsumedTimeout;
|
|
56
96
|
private unconsumedCheckVersion;
|
|
57
97
|
constructor(events: Event[], options: EventsConsumerOptions);
|
|
98
|
+
/**
|
|
99
|
+
* The oldest event the walk stepped over that no consumer has claimed yet,
|
|
100
|
+
* if any. Parking is a bet that a consumer will be registered later, so at
|
|
101
|
+
* any point where no consumer ever will be again — the replay finishing is
|
|
102
|
+
* the definitive one — this answers which event the bet lost on.
|
|
103
|
+
*/
|
|
104
|
+
get strandedEvent(): Event | undefined;
|
|
105
|
+
/**
|
|
106
|
+
* What the walk is still holding, or `undefined` when it holds nothing.
|
|
107
|
+
*
|
|
108
|
+
* Read at every point a replay stops, including the suspensions that are not
|
|
109
|
+
* settling points, so the held state reaches telemetry. A replay cannot tell
|
|
110
|
+
* a delivery awaiting a later consumer from one no consumer will ever
|
|
111
|
+
* register, so it reports rather than decides: the same `eventId` reported on
|
|
112
|
+
* suspension after suspension of one run is the shape that says the bet
|
|
113
|
+
* parking made is not going to pay off, and that shape is only visible across
|
|
114
|
+
* replays.
|
|
115
|
+
*/
|
|
116
|
+
get parkedSummary(): {
|
|
117
|
+
count: number;
|
|
118
|
+
eventId: string;
|
|
119
|
+
eventType: Event['eventType'];
|
|
120
|
+
} | undefined;
|
|
58
121
|
append(events: Event[]): void;
|
|
59
122
|
/**
|
|
60
123
|
* Registers a callback function to be called after an event has been consumed
|
|
@@ -70,13 +133,71 @@ export declare class EventsConsumer {
|
|
|
70
133
|
private consume;
|
|
71
134
|
/**
|
|
72
135
|
* Offer `currentEvent` to each registered callback in turn. Returns true
|
|
73
|
-
* when a callback consumed
|
|
74
|
-
*
|
|
75
|
-
|
|
76
|
-
|
|
136
|
+
* when a callback consumed it. Does not move {@link eventIndex}: the ordered
|
|
137
|
+
* walk and the parked drain advance differently, so each does its own.
|
|
138
|
+
*/
|
|
139
|
+
private offer;
|
|
140
|
+
/**
|
|
141
|
+
* Offer everything parked, oldest first, until a pass claims nothing.
|
|
142
|
+
*
|
|
143
|
+
* Each offer runs with {@link eventIndex} moved back to the position the
|
|
144
|
+
* parked event held in the log, because that is the position its consumer
|
|
145
|
+
* will register a delivery barrier under. Restoring the walk pointer
|
|
146
|
+
* afterwards is what keeps the two pointers from interfering.
|
|
147
|
+
*/
|
|
148
|
+
private drainParked;
|
|
149
|
+
/**
|
|
150
|
+
* Step the ordered walk over an event nobody claimed, holding on to it for a
|
|
151
|
+
* later consumer. Returns false when the event's type makes its position a
|
|
152
|
+
* decision record, which is the one case where nobody claiming it means the
|
|
153
|
+
* replay diverged.
|
|
154
|
+
*/
|
|
155
|
+
private park;
|
|
156
|
+
private handleEndOfLog;
|
|
157
|
+
private scheduleUnconsumedCheck;
|
|
158
|
+
/**
|
|
159
|
+
* Run `fn` once no data delivery is in flight, polling the way
|
|
160
|
+
* `scheduleWhenIdle` does: let the promise queue drain, re-check a timer
|
|
161
|
+
* tick later, repeat.
|
|
162
|
+
*
|
|
163
|
+
* Without this the check is a bet that every delivery the walk is running
|
|
164
|
+
* ahead of lands inside a fixed window. Consumption is synchronous while the
|
|
165
|
+
* resolution it triggers is not: a step result hydrates in the host, resolves
|
|
166
|
+
* from a detached continuation behind `awaitEarlierDeliveries`, and only then
|
|
167
|
+
* does VM code run far enough to subscribe the next consumer. Replaying a
|
|
168
|
+
* batch of N parallel step results leaves N-1 of them on that detached path
|
|
169
|
+
* with the queue already drained, so the walk sits on the ordered event the
|
|
170
|
+
* VM is about to draw and the window is the only thing standing between a
|
|
171
|
+
* healthy run and `ReplayDivergenceError`.
|
|
172
|
+
*
|
|
173
|
+
* Shortening the window shows that mechanism directly: on identical event logs
|
|
174
|
+
* the local race repro corrupts 34 of 42 runs at a 10ms window and 0 of 114 at
|
|
175
|
+
* the 100ms default. That measures how the bet loses, not that the default
|
|
176
|
+
* loses it, and no measurement of a delivery outrunning 100ms exists either
|
|
177
|
+
* way. So read this as retiring the bet rather than as repairing an observed
|
|
178
|
+
* failure of that number: the delay is a user-settable env override, which
|
|
179
|
+
* leaves the old behaviour one configuration away from losing on any backend.
|
|
180
|
+
*
|
|
181
|
+
* Termination is `hasParkedCommittedDelivery`'s: it counts only deliveries
|
|
182
|
+
* that resolve on their own, so nothing here can gate its own retirement. A
|
|
183
|
+
* genuinely orphaned event has no delivery to wait on and reaches `fn` on the
|
|
184
|
+
* first poll.
|
|
185
|
+
*
|
|
186
|
+
* What the gate gives up: for the ordered events that still reach
|
|
187
|
+
* `onUnconsumedEvent` rather than {@link park}, this stops being the thing
|
|
188
|
+
* that catches a diverged log while a delivery is in flight. The suspension
|
|
189
|
+
* and this check now wake from the same `isDeliveryIdle` edge, and
|
|
190
|
+
* `scheduleWhenIdle` fires on the first timer tick after idle while this waits
|
|
191
|
+
* a further `getDeferredCheckDelayMs()`. So a run with a pending `sleep()`
|
|
192
|
+
* suspends first, and `onWorkflowError` drops the divergence arriving second
|
|
193
|
+
* (its `'suspended'` branch demotes to `'replay'` and surfaces nothing),
|
|
194
|
+
* leaving a later `resume()` to decline into a cold replay. Pre-gate the
|
|
195
|
+
* suspension already won that race whenever the delivery landed inside the
|
|
196
|
+
* fixed window, so what changed is that the outcome stopped depending on
|
|
197
|
+
* timing. Nothing should treat this check as the mechanism that reports
|
|
198
|
+
* divergence on a log the run is still delivering into.
|
|
77
199
|
*/
|
|
78
|
-
private
|
|
79
|
-
private handleUnconsumed;
|
|
200
|
+
private whenDeliveryIdle;
|
|
80
201
|
}
|
|
81
202
|
export {};
|
|
82
203
|
//# sourceMappingURL=events-consumer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events-consumer.d.ts","sourceRoot":"","sources":["../src/events-consumer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,KAAK,EAAa,MAAM,iBAAiB,CAAC;AAGxD;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"events-consumer.d.ts","sourceRoot":"","sources":["../src/events-consumer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,KAAK,EAAa,MAAM,iBAAiB,CAAC;AAGxD;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAE3C;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B,KAAK,CAAC;AAgG9C,oBAAY,mBAAmB;IAC7B;;OAEG;IACH,QAAQ,IAAA;IACR;;OAEG;IACH,WAAW,IAAA;IACX;;OAEG;IACH,QAAQ,IAAA;CACT;AAED,KAAK,qBAAqB,GAAG,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,KAAK,mBAAmB,CAAC;AAE1E,MAAM,WAAW,qBAAqB;IACpC;;;;OAIG;IACH,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACzC;;;;;;OAMG;IACH,iBAAiB,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAC1C;;;;;OAKG;IACH,eAAe,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC;;;;;;;;;;;OAWG;IACH,cAAc,EAAE,MAAM,OAAO,CAAC;CAC/B;AAED,qBAAa,cAAc;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,qBAAqB,EAAE,CAAM;IACjD;;;;;;;;;OASG;IACH,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyC;IAChE;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;IAC9C,OAAO,CAAC,eAAe,CAAC,CAAyB;IACjD,OAAO,CAAC,iBAAiB,CAAyB;IAClD,OAAO,CAAC,eAAe,CAAsB;IAC7C,OAAO,CAAC,cAAc,CAAgB;IACtC,OAAO,CAAC,sBAAsB,CAA8B;IAC5D,OAAO,CAAC,wBAAwB,CAA8C;IAC9E,OAAO,CAAC,sBAAsB,CAAK;gBAEvB,MAAM,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,qBAAqB;IAY3D;;;;;OAKG;IACH,IAAI,aAAa,IAAI,KAAK,GAAG,SAAS,CAErC;IAED;;;;;;;;;;OAUG;IACH,IAAI,aAAa,IACb;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,KAAK,CAAC,WAAW,CAAC,CAAA;KAAE,GACjE,SAAS,CAUZ;IAED,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI;IAK7B;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,EAAE,qBAAqB;IAgBnC,OAAO,CAAC,mBAAmB;IAa3B,OAAO,CAAC,OAAO,CA4Cb;IAEF;;;;OAIG;IACH,OAAO,CAAC,KAAK;IAmCb;;;;;;;OAOG;IACH,OAAO,CAAC,WAAW;IAyBnB;;;;;OAKG;IACH,OAAO,CAAC,IAAI;IAqBZ,OAAO,CAAC,cAAc;IA2BtB,OAAO,CAAC,uBAAuB;IAqD/B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAyCG;IACH,OAAO,CAAC,gBAAgB;CA2BzB"}
|