@rivetkit/workflow-engine 0.0.0-2-3-0-rc-rollback.f0e199e → 0.0.0-claude-edge-bundle-slim.fb63356
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/tsup/{chunk-A33YVYOF.cjs → chunk-GQWOLYBA.cjs} +87 -61
- package/dist/tsup/chunk-GQWOLYBA.cjs.map +1 -0
- package/dist/tsup/{chunk-EAAPMGGE.js → chunk-KA2T56AJ.js} +87 -61
- package/dist/tsup/chunk-KA2T56AJ.js.map +1 -0
- package/dist/tsup/index.cjs +2 -2
- package/dist/tsup/index.d.cts +16 -12
- package/dist/tsup/index.d.ts +16 -12
- package/dist/tsup/index.js +1 -1
- package/dist/tsup/testing.cjs +23 -23
- package/dist/tsup/testing.js +1 -1
- package/package.json +1 -1
- package/schemas/serde.ts +1 -3
- package/src/context.ts +41 -30
- package/src/index.ts +41 -21
- package/src/location.ts +1 -1
- package/src/types.ts +3 -1
- package/dist/tsup/chunk-A33YVYOF.cjs.map +0 -1
- package/dist/tsup/chunk-EAAPMGGE.js.map +0 -1
package/dist/tsup/index.cjs
CHANGED
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
|
|
44
44
|
|
|
45
45
|
|
|
46
|
-
var
|
|
46
|
+
var _chunkGQWOLYBAcjs = require('./chunk-GQWOLYBA.cjs');
|
|
47
47
|
|
|
48
48
|
|
|
49
49
|
|
|
@@ -89,5 +89,5 @@ var _chunkA33YVYOFcjs = require('./chunk-A33YVYOF.cjs');
|
|
|
89
89
|
|
|
90
90
|
|
|
91
91
|
|
|
92
|
-
exports.CancelledError =
|
|
92
|
+
exports.CancelledError = _chunkGQWOLYBAcjs.CancelledError; exports.CriticalError = _chunkGQWOLYBAcjs.CriticalError; exports.DEFAULT_LOOP_HISTORY_PRUNE_INTERVAL = _chunkGQWOLYBAcjs.DEFAULT_LOOP_HISTORY_PRUNE_INTERVAL; exports.DEFAULT_MAX_RETRIES = _chunkGQWOLYBAcjs.DEFAULT_MAX_RETRIES; exports.DEFAULT_RETRY_BACKOFF_BASE = _chunkGQWOLYBAcjs.DEFAULT_RETRY_BACKOFF_BASE; exports.DEFAULT_RETRY_BACKOFF_MAX = _chunkGQWOLYBAcjs.DEFAULT_RETRY_BACKOFF_MAX; exports.DEFAULT_STEP_TIMEOUT = _chunkGQWOLYBAcjs.DEFAULT_STEP_TIMEOUT; exports.EntryInProgressError = _chunkGQWOLYBAcjs.EntryInProgressError; exports.EvictedError = _chunkGQWOLYBAcjs.EvictedError; exports.HistoryDivergedError = _chunkGQWOLYBAcjs.HistoryDivergedError; exports.JoinError = _chunkGQWOLYBAcjs.JoinError; exports.Loop = _chunkGQWOLYBAcjs.Loop; exports.MessageWaitError = _chunkGQWOLYBAcjs.MessageWaitError; exports.RaceError = _chunkGQWOLYBAcjs.RaceError; exports.RollbackCheckpointError = _chunkGQWOLYBAcjs.RollbackCheckpointError; exports.RollbackError = _chunkGQWOLYBAcjs.RollbackError; exports.SleepError = _chunkGQWOLYBAcjs.SleepError; exports.StepExhaustedError = _chunkGQWOLYBAcjs.StepExhaustedError; exports.StepFailedError = _chunkGQWOLYBAcjs.StepFailedError; exports.WorkflowContextImpl = _chunkGQWOLYBAcjs.WorkflowContextImpl; exports.appendLoopIteration = _chunkGQWOLYBAcjs.appendLoopIteration; exports.appendName = _chunkGQWOLYBAcjs.appendName; exports.createEntry = _chunkGQWOLYBAcjs.createEntry; exports.createHistorySnapshot = _chunkGQWOLYBAcjs.createHistorySnapshot; exports.createStorage = _chunkGQWOLYBAcjs.createStorage; exports.deleteEntriesWithPrefix = _chunkGQWOLYBAcjs.deleteEntriesWithPrefix; exports.emptyLocation = _chunkGQWOLYBAcjs.emptyLocation; exports.extractErrorInfo = _chunkGQWOLYBAcjs.extractErrorInfo; exports.flush = _chunkGQWOLYBAcjs.flush; exports.generateId = _chunkGQWOLYBAcjs.generateId; exports.getEntry = _chunkGQWOLYBAcjs.getEntry; exports.getOrCreateMetadata = _chunkGQWOLYBAcjs.getOrCreateMetadata; exports.isLocationPrefix = _chunkGQWOLYBAcjs.isLocationPrefix; exports.isLoopIterationMarker = _chunkGQWOLYBAcjs.isLoopIterationMarker; exports.loadMetadata = _chunkGQWOLYBAcjs.loadMetadata; exports.loadStorage = _chunkGQWOLYBAcjs.loadStorage; exports.locationToKey = _chunkGQWOLYBAcjs.locationToKey; exports.locationsEqual = _chunkGQWOLYBAcjs.locationsEqual; exports.parentLocation = _chunkGQWOLYBAcjs.parentLocation; exports.registerName = _chunkGQWOLYBAcjs.registerName; exports.replayWorkflowFromStep = _chunkGQWOLYBAcjs.replayWorkflowFromStep; exports.resolveName = _chunkGQWOLYBAcjs.resolveName; exports.runWorkflow = _chunkGQWOLYBAcjs.runWorkflow; exports.setEntry = _chunkGQWOLYBAcjs.setEntry;
|
|
93
93
|
//# sourceMappingURL=index.cjs.map
|
package/dist/tsup/index.d.cts
CHANGED
|
@@ -345,6 +345,8 @@ interface StepConfig<T> {
|
|
|
345
345
|
retryBackoffMax?: number;
|
|
346
346
|
/** Timeout in ms for step execution (default: 30000). Set to 0 to disable. */
|
|
347
347
|
timeout?: number;
|
|
348
|
+
/** If true, step timeouts retry like any other error instead of failing immediately as critical. Default: false. */
|
|
349
|
+
retryOnTimeout?: boolean;
|
|
348
350
|
}
|
|
349
351
|
type TryStepCatchKind = "critical" | "timeout" | "exhausted" | "rollback";
|
|
350
352
|
interface TryStepFailure {
|
|
@@ -398,7 +400,7 @@ type LoopResult<S, T> = {
|
|
|
398
400
|
* Stateless loops (state = undefined) may return void/undefined, which is treated as
|
|
399
401
|
* `Loop.continue(undefined)`.
|
|
400
402
|
*/
|
|
401
|
-
type LoopIterationResult<S, T> = Promise<LoopResult<S, T> | (S extends undefined ?
|
|
403
|
+
type LoopIterationResult<S, T> = Promise<LoopResult<S, T> | (S extends undefined ? undefined : never)>;
|
|
402
404
|
/**
|
|
403
405
|
* Configuration for a loop.
|
|
404
406
|
*/
|
|
@@ -697,12 +699,12 @@ declare class WorkflowContextImpl implements WorkflowContextInterface {
|
|
|
697
699
|
*/
|
|
698
700
|
evict(): void;
|
|
699
701
|
/**
|
|
700
|
-
* Wait for
|
|
701
|
-
*
|
|
702
|
-
*
|
|
703
|
-
*
|
|
702
|
+
* Wait for `ms`, rejecting early with EvictedError if the workflow is
|
|
703
|
+
* evicted. Both the timer and the abort listener are torn down on either
|
|
704
|
+
* outcome, so a completed sleep never leaves a dangling listener on the
|
|
705
|
+
* long-lived run abort signal.
|
|
704
706
|
*/
|
|
705
|
-
|
|
707
|
+
private sleepOrEvict;
|
|
706
708
|
step<T>(nameOrConfig: string | StepConfig<T>, run?: () => Promise<T>): Promise<T>;
|
|
707
709
|
tryStep<T>(nameOrConfig: string | TryStepConfig<T>, run?: () => Promise<T>): Promise<TryStepResult<T>>;
|
|
708
710
|
try<T>(nameOrConfig: string | TryBlockConfig<T>, run?: (ctx: WorkflowContextInterface) => Promise<T>): Promise<TryBlockResult<T>>;
|
|
@@ -713,7 +715,9 @@ declare class WorkflowContextImpl implements WorkflowContextInterface {
|
|
|
713
715
|
*
|
|
714
716
|
* Note: This does NOT cancel the underlying operation. JavaScript Promises
|
|
715
717
|
* cannot be cancelled once started. When a timeout occurs:
|
|
716
|
-
* - The step is
|
|
718
|
+
* - The step is rejected with StepTimeoutError. By default this is treated
|
|
719
|
+
* as a critical failure with no retry. Set retryOnTimeout: true on the
|
|
720
|
+
* step config to retry timeouts like any other error.
|
|
717
721
|
* - The underlying async operation continues running in the background
|
|
718
722
|
* - Any side effects from the operation may still occur
|
|
719
723
|
*
|
|
@@ -779,6 +783,11 @@ declare class WorkflowContextImpl implements WorkflowContextInterface {
|
|
|
779
783
|
private executeRemoved;
|
|
780
784
|
}
|
|
781
785
|
|
|
786
|
+
/**
|
|
787
|
+
* Extract structured error information from an error.
|
|
788
|
+
*/
|
|
789
|
+
declare function extractErrorInfo(error: unknown): WorkflowError;
|
|
790
|
+
|
|
782
791
|
/**
|
|
783
792
|
* Thrown from steps to prevent retry.
|
|
784
793
|
* Use this when an error is unrecoverable and retrying would be pointless.
|
|
@@ -883,11 +892,6 @@ declare class EntryInProgressError extends Error {
|
|
|
883
892
|
constructor();
|
|
884
893
|
}
|
|
885
894
|
|
|
886
|
-
/**
|
|
887
|
-
* Extract structured error information from an error.
|
|
888
|
-
*/
|
|
889
|
-
declare function extractErrorInfo(error: unknown): WorkflowError;
|
|
890
|
-
|
|
891
895
|
/**
|
|
892
896
|
* Check if a path segment is a loop iteration marker.
|
|
893
897
|
*/
|
package/dist/tsup/index.d.ts
CHANGED
|
@@ -345,6 +345,8 @@ interface StepConfig<T> {
|
|
|
345
345
|
retryBackoffMax?: number;
|
|
346
346
|
/** Timeout in ms for step execution (default: 30000). Set to 0 to disable. */
|
|
347
347
|
timeout?: number;
|
|
348
|
+
/** If true, step timeouts retry like any other error instead of failing immediately as critical. Default: false. */
|
|
349
|
+
retryOnTimeout?: boolean;
|
|
348
350
|
}
|
|
349
351
|
type TryStepCatchKind = "critical" | "timeout" | "exhausted" | "rollback";
|
|
350
352
|
interface TryStepFailure {
|
|
@@ -398,7 +400,7 @@ type LoopResult<S, T> = {
|
|
|
398
400
|
* Stateless loops (state = undefined) may return void/undefined, which is treated as
|
|
399
401
|
* `Loop.continue(undefined)`.
|
|
400
402
|
*/
|
|
401
|
-
type LoopIterationResult<S, T> = Promise<LoopResult<S, T> | (S extends undefined ?
|
|
403
|
+
type LoopIterationResult<S, T> = Promise<LoopResult<S, T> | (S extends undefined ? undefined : never)>;
|
|
402
404
|
/**
|
|
403
405
|
* Configuration for a loop.
|
|
404
406
|
*/
|
|
@@ -697,12 +699,12 @@ declare class WorkflowContextImpl implements WorkflowContextInterface {
|
|
|
697
699
|
*/
|
|
698
700
|
evict(): void;
|
|
699
701
|
/**
|
|
700
|
-
* Wait for
|
|
701
|
-
*
|
|
702
|
-
*
|
|
703
|
-
*
|
|
702
|
+
* Wait for `ms`, rejecting early with EvictedError if the workflow is
|
|
703
|
+
* evicted. Both the timer and the abort listener are torn down on either
|
|
704
|
+
* outcome, so a completed sleep never leaves a dangling listener on the
|
|
705
|
+
* long-lived run abort signal.
|
|
704
706
|
*/
|
|
705
|
-
|
|
707
|
+
private sleepOrEvict;
|
|
706
708
|
step<T>(nameOrConfig: string | StepConfig<T>, run?: () => Promise<T>): Promise<T>;
|
|
707
709
|
tryStep<T>(nameOrConfig: string | TryStepConfig<T>, run?: () => Promise<T>): Promise<TryStepResult<T>>;
|
|
708
710
|
try<T>(nameOrConfig: string | TryBlockConfig<T>, run?: (ctx: WorkflowContextInterface) => Promise<T>): Promise<TryBlockResult<T>>;
|
|
@@ -713,7 +715,9 @@ declare class WorkflowContextImpl implements WorkflowContextInterface {
|
|
|
713
715
|
*
|
|
714
716
|
* Note: This does NOT cancel the underlying operation. JavaScript Promises
|
|
715
717
|
* cannot be cancelled once started. When a timeout occurs:
|
|
716
|
-
* - The step is
|
|
718
|
+
* - The step is rejected with StepTimeoutError. By default this is treated
|
|
719
|
+
* as a critical failure with no retry. Set retryOnTimeout: true on the
|
|
720
|
+
* step config to retry timeouts like any other error.
|
|
717
721
|
* - The underlying async operation continues running in the background
|
|
718
722
|
* - Any side effects from the operation may still occur
|
|
719
723
|
*
|
|
@@ -779,6 +783,11 @@ declare class WorkflowContextImpl implements WorkflowContextInterface {
|
|
|
779
783
|
private executeRemoved;
|
|
780
784
|
}
|
|
781
785
|
|
|
786
|
+
/**
|
|
787
|
+
* Extract structured error information from an error.
|
|
788
|
+
*/
|
|
789
|
+
declare function extractErrorInfo(error: unknown): WorkflowError;
|
|
790
|
+
|
|
782
791
|
/**
|
|
783
792
|
* Thrown from steps to prevent retry.
|
|
784
793
|
* Use this when an error is unrecoverable and retrying would be pointless.
|
|
@@ -883,11 +892,6 @@ declare class EntryInProgressError extends Error {
|
|
|
883
892
|
constructor();
|
|
884
893
|
}
|
|
885
894
|
|
|
886
|
-
/**
|
|
887
|
-
* Extract structured error information from an error.
|
|
888
|
-
*/
|
|
889
|
-
declare function extractErrorInfo(error: unknown): WorkflowError;
|
|
890
|
-
|
|
891
895
|
/**
|
|
892
896
|
* Check if a path segment is a loop iteration marker.
|
|
893
897
|
*/
|
package/dist/tsup/index.js
CHANGED
package/dist/tsup/testing.cjs
CHANGED
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
|
|
48
48
|
|
|
49
49
|
|
|
50
|
-
var
|
|
50
|
+
var _chunkGQWOLYBAcjs = require('./chunk-GQWOLYBA.cjs');
|
|
51
51
|
|
|
52
52
|
// src/testing.ts
|
|
53
53
|
var InMemoryWorkflowMessageDriver = class {
|
|
@@ -97,7 +97,7 @@ var InMemoryWorkflowMessageDriver = class {
|
|
|
97
97
|
}
|
|
98
98
|
async waitForMessages(messageNames, abortSignal) {
|
|
99
99
|
if (abortSignal.aborted) {
|
|
100
|
-
throw new (0,
|
|
100
|
+
throw new (0, _chunkGQWOLYBAcjs.EvictedError)();
|
|
101
101
|
}
|
|
102
102
|
const nameSet = messageNames.length > 0 ? new Set(messageNames) : void 0;
|
|
103
103
|
if (this.#messages.some(
|
|
@@ -118,7 +118,7 @@ var InMemoryWorkflowMessageDriver = class {
|
|
|
118
118
|
},
|
|
119
119
|
abortSignal,
|
|
120
120
|
onAbort: () => {
|
|
121
|
-
waiter.reject(new (0,
|
|
121
|
+
waiter.reject(new (0, _chunkGQWOLYBAcjs.EvictedError)());
|
|
122
122
|
}
|
|
123
123
|
};
|
|
124
124
|
abortSignal.addEventListener("abort", waiter.onAbort, {
|
|
@@ -158,56 +158,56 @@ var InMemoryDriver = (_class = class {constructor() { _class.prototype.__init.ca
|
|
|
158
158
|
__init4() {this.workerPollInterval = 100}
|
|
159
159
|
__init5() {this.messageDriver = this.#inMemoryMessageDriver}
|
|
160
160
|
async get(key) {
|
|
161
|
-
await
|
|
162
|
-
const entry = this.kv.get(
|
|
161
|
+
await _chunkGQWOLYBAcjs.sleep.call(void 0, this.latency);
|
|
162
|
+
const entry = this.kv.get(_chunkGQWOLYBAcjs.keyToHex.call(void 0, key));
|
|
163
163
|
return _nullishCoalesce((entry == null ? void 0 : entry.value), () => ( null));
|
|
164
164
|
}
|
|
165
165
|
async set(key, value) {
|
|
166
|
-
await
|
|
167
|
-
this.kv.set(
|
|
166
|
+
await _chunkGQWOLYBAcjs.sleep.call(void 0, this.latency);
|
|
167
|
+
this.kv.set(_chunkGQWOLYBAcjs.keyToHex.call(void 0, key), { key, value });
|
|
168
168
|
}
|
|
169
169
|
async delete(key) {
|
|
170
|
-
await
|
|
171
|
-
this.kv.delete(
|
|
170
|
+
await _chunkGQWOLYBAcjs.sleep.call(void 0, this.latency);
|
|
171
|
+
this.kv.delete(_chunkGQWOLYBAcjs.keyToHex.call(void 0, key));
|
|
172
172
|
}
|
|
173
173
|
async deletePrefix(prefix) {
|
|
174
|
-
await
|
|
174
|
+
await _chunkGQWOLYBAcjs.sleep.call(void 0, this.latency);
|
|
175
175
|
for (const [hexKey, entry] of this.kv) {
|
|
176
|
-
if (
|
|
176
|
+
if (_chunkGQWOLYBAcjs.keyStartsWith.call(void 0, entry.key, prefix)) {
|
|
177
177
|
this.kv.delete(hexKey);
|
|
178
178
|
}
|
|
179
179
|
}
|
|
180
180
|
}
|
|
181
181
|
async deleteRange(start, end) {
|
|
182
|
-
await
|
|
182
|
+
await _chunkGQWOLYBAcjs.sleep.call(void 0, this.latency);
|
|
183
183
|
for (const [hexKey, entry] of this.kv) {
|
|
184
|
-
if (
|
|
184
|
+
if (_chunkGQWOLYBAcjs.compareKeys.call(void 0, entry.key, start) >= 0 && _chunkGQWOLYBAcjs.compareKeys.call(void 0, entry.key, end) < 0) {
|
|
185
185
|
this.kv.delete(hexKey);
|
|
186
186
|
}
|
|
187
187
|
}
|
|
188
188
|
}
|
|
189
189
|
async list(prefix) {
|
|
190
|
-
await
|
|
190
|
+
await _chunkGQWOLYBAcjs.sleep.call(void 0, this.latency);
|
|
191
191
|
const results = [];
|
|
192
192
|
for (const entry of this.kv.values()) {
|
|
193
|
-
if (
|
|
193
|
+
if (_chunkGQWOLYBAcjs.keyStartsWith.call(void 0, entry.key, prefix)) {
|
|
194
194
|
results.push({ key: entry.key, value: entry.value });
|
|
195
195
|
}
|
|
196
196
|
}
|
|
197
|
-
return results.sort((a, b) =>
|
|
197
|
+
return results.sort((a, b) => _chunkGQWOLYBAcjs.compareKeys.call(void 0, a.key, b.key));
|
|
198
198
|
}
|
|
199
199
|
async batch(writes) {
|
|
200
|
-
await
|
|
200
|
+
await _chunkGQWOLYBAcjs.sleep.call(void 0, this.latency);
|
|
201
201
|
for (const { key, value } of writes) {
|
|
202
|
-
this.kv.set(
|
|
202
|
+
this.kv.set(_chunkGQWOLYBAcjs.keyToHex.call(void 0, key), { key, value });
|
|
203
203
|
}
|
|
204
204
|
}
|
|
205
205
|
async setAlarm(workflowId, wakeAt) {
|
|
206
|
-
await
|
|
206
|
+
await _chunkGQWOLYBAcjs.sleep.call(void 0, this.latency);
|
|
207
207
|
this.alarms.set(workflowId, wakeAt);
|
|
208
208
|
}
|
|
209
209
|
async clearAlarm(workflowId) {
|
|
210
|
-
await
|
|
210
|
+
await _chunkGQWOLYBAcjs.sleep.call(void 0, this.latency);
|
|
211
211
|
this.alarms.delete(workflowId);
|
|
212
212
|
}
|
|
213
213
|
async waitForMessages(messageNames, abortSignal) {
|
|
@@ -218,7 +218,7 @@ var InMemoryDriver = (_class = class {constructor() { _class.prototype.__init.ca
|
|
|
218
218
|
}
|
|
219
219
|
while (true) {
|
|
220
220
|
if (abortSignal.aborted) {
|
|
221
|
-
throw new (0,
|
|
221
|
+
throw new (0, _chunkGQWOLYBAcjs.EvictedError)();
|
|
222
222
|
}
|
|
223
223
|
const messages = await this.messageDriver.receiveMessages({
|
|
224
224
|
names: messageNames.length > 0 ? messageNames : void 0,
|
|
@@ -228,7 +228,7 @@ var InMemoryDriver = (_class = class {constructor() { _class.prototype.__init.ca
|
|
|
228
228
|
if (messages.length > 0) {
|
|
229
229
|
return;
|
|
230
230
|
}
|
|
231
|
-
await
|
|
231
|
+
await _chunkGQWOLYBAcjs.sleep.call(void 0, Math.max(1, this.latency));
|
|
232
232
|
}
|
|
233
233
|
}
|
|
234
234
|
/**
|
|
@@ -324,5 +324,5 @@ var InMemoryDriver = (_class = class {constructor() { _class.prototype.__init.ca
|
|
|
324
324
|
|
|
325
325
|
|
|
326
326
|
|
|
327
|
-
exports.CancelledError =
|
|
327
|
+
exports.CancelledError = _chunkGQWOLYBAcjs.CancelledError; exports.CriticalError = _chunkGQWOLYBAcjs.CriticalError; exports.DEFAULT_LOOP_HISTORY_PRUNE_INTERVAL = _chunkGQWOLYBAcjs.DEFAULT_LOOP_HISTORY_PRUNE_INTERVAL; exports.DEFAULT_MAX_RETRIES = _chunkGQWOLYBAcjs.DEFAULT_MAX_RETRIES; exports.DEFAULT_RETRY_BACKOFF_BASE = _chunkGQWOLYBAcjs.DEFAULT_RETRY_BACKOFF_BASE; exports.DEFAULT_RETRY_BACKOFF_MAX = _chunkGQWOLYBAcjs.DEFAULT_RETRY_BACKOFF_MAX; exports.DEFAULT_STEP_TIMEOUT = _chunkGQWOLYBAcjs.DEFAULT_STEP_TIMEOUT; exports.EntryInProgressError = _chunkGQWOLYBAcjs.EntryInProgressError; exports.EvictedError = _chunkGQWOLYBAcjs.EvictedError; exports.HistoryDivergedError = _chunkGQWOLYBAcjs.HistoryDivergedError; exports.InMemoryDriver = InMemoryDriver; exports.JoinError = _chunkGQWOLYBAcjs.JoinError; exports.Loop = _chunkGQWOLYBAcjs.Loop; exports.MessageWaitError = _chunkGQWOLYBAcjs.MessageWaitError; exports.RaceError = _chunkGQWOLYBAcjs.RaceError; exports.RollbackCheckpointError = _chunkGQWOLYBAcjs.RollbackCheckpointError; exports.RollbackError = _chunkGQWOLYBAcjs.RollbackError; exports.SleepError = _chunkGQWOLYBAcjs.SleepError; exports.StepExhaustedError = _chunkGQWOLYBAcjs.StepExhaustedError; exports.StepFailedError = _chunkGQWOLYBAcjs.StepFailedError; exports.WorkflowContextImpl = _chunkGQWOLYBAcjs.WorkflowContextImpl; exports.appendLoopIteration = _chunkGQWOLYBAcjs.appendLoopIteration; exports.appendName = _chunkGQWOLYBAcjs.appendName; exports.createEntry = _chunkGQWOLYBAcjs.createEntry; exports.createHistorySnapshot = _chunkGQWOLYBAcjs.createHistorySnapshot; exports.createStorage = _chunkGQWOLYBAcjs.createStorage; exports.deleteEntriesWithPrefix = _chunkGQWOLYBAcjs.deleteEntriesWithPrefix; exports.emptyLocation = _chunkGQWOLYBAcjs.emptyLocation; exports.extractErrorInfo = _chunkGQWOLYBAcjs.extractErrorInfo; exports.flush = _chunkGQWOLYBAcjs.flush; exports.generateId = _chunkGQWOLYBAcjs.generateId; exports.getEntry = _chunkGQWOLYBAcjs.getEntry; exports.getOrCreateMetadata = _chunkGQWOLYBAcjs.getOrCreateMetadata; exports.isLocationPrefix = _chunkGQWOLYBAcjs.isLocationPrefix; exports.isLoopIterationMarker = _chunkGQWOLYBAcjs.isLoopIterationMarker; exports.loadMetadata = _chunkGQWOLYBAcjs.loadMetadata; exports.loadStorage = _chunkGQWOLYBAcjs.loadStorage; exports.locationToKey = _chunkGQWOLYBAcjs.locationToKey; exports.locationsEqual = _chunkGQWOLYBAcjs.locationsEqual; exports.parentLocation = _chunkGQWOLYBAcjs.parentLocation; exports.registerName = _chunkGQWOLYBAcjs.registerName; exports.replayWorkflowFromStep = _chunkGQWOLYBAcjs.replayWorkflowFromStep; exports.resolveName = _chunkGQWOLYBAcjs.resolveName; exports.runWorkflow = _chunkGQWOLYBAcjs.runWorkflow; exports.setEntry = _chunkGQWOLYBAcjs.setEntry;
|
|
328
328
|
//# sourceMappingURL=testing.cjs.map
|
package/dist/tsup/testing.js
CHANGED
package/package.json
CHANGED
package/schemas/serde.ts
CHANGED
|
@@ -18,7 +18,6 @@ import type {
|
|
|
18
18
|
EntryMetadata as InternalEntryMetadata,
|
|
19
19
|
EntryStatus as InternalEntryStatus,
|
|
20
20
|
Location as InternalLocation,
|
|
21
|
-
LoopIterationMarker as InternalLoopIterationMarker,
|
|
22
21
|
PathSegment as InternalPathSegment,
|
|
23
22
|
SleepState as InternalSleepState,
|
|
24
23
|
WorkflowState as InternalWorkflowState,
|
|
@@ -27,7 +26,6 @@ import {
|
|
|
27
26
|
CURRENT_VERSION,
|
|
28
27
|
ENTRY_METADATA_VERSIONED,
|
|
29
28
|
ENTRY_VERSIONED,
|
|
30
|
-
WORKFLOW_METADATA_VERSIONED,
|
|
31
29
|
} from "./versioned.js";
|
|
32
30
|
|
|
33
31
|
// === Helper: ArrayBuffer to/from utilities ===
|
|
@@ -74,7 +72,7 @@ function assertString(
|
|
|
74
72
|
/**
|
|
75
73
|
* Validate that a value is a number.
|
|
76
74
|
*/
|
|
77
|
-
function
|
|
75
|
+
function _assertNumber(
|
|
78
76
|
value: unknown,
|
|
79
77
|
context: string,
|
|
80
78
|
): asserts value is number {
|
package/src/context.ts
CHANGED
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
StepExhaustedError,
|
|
22
22
|
StepFailedError,
|
|
23
23
|
} from "./errors.js";
|
|
24
|
-
import {
|
|
24
|
+
import { buildEntryMetadataKey, buildLoopIterationRange } from "./keys.js";
|
|
25
25
|
import {
|
|
26
26
|
appendLoopIteration,
|
|
27
27
|
appendName,
|
|
@@ -36,13 +36,12 @@ import {
|
|
|
36
36
|
flush,
|
|
37
37
|
getOrCreateMetadata,
|
|
38
38
|
loadMetadata,
|
|
39
|
-
setEntry,
|
|
40
39
|
type PendingDeletions,
|
|
40
|
+
setEntry,
|
|
41
41
|
} from "./storage.js";
|
|
42
42
|
import type {
|
|
43
43
|
BranchConfig,
|
|
44
44
|
BranchOutput,
|
|
45
|
-
BranchStatus,
|
|
46
45
|
Entry,
|
|
47
46
|
EntryKindType,
|
|
48
47
|
EntryMetadata,
|
|
@@ -66,13 +65,12 @@ import type {
|
|
|
66
65
|
WorkflowError,
|
|
67
66
|
WorkflowErrorEvent,
|
|
68
67
|
WorkflowErrorHandler,
|
|
68
|
+
WorkflowMessageDriver,
|
|
69
69
|
WorkflowQueue,
|
|
70
70
|
WorkflowQueueMessage,
|
|
71
71
|
WorkflowQueueNextBatchOptions,
|
|
72
72
|
WorkflowQueueNextOptions,
|
|
73
|
-
WorkflowMessageDriver,
|
|
74
73
|
} from "./types.js";
|
|
75
|
-
import { sleep } from "./utils.js";
|
|
76
74
|
|
|
77
75
|
/**
|
|
78
76
|
* Default values for step configuration.
|
|
@@ -505,8 +503,7 @@ export class WorkflowContextImpl implements WorkflowContextInterface {
|
|
|
505
503
|
* Throws HistoryDivergedError if duplicate detected.
|
|
506
504
|
*/
|
|
507
505
|
private checkDuplicateName(name: string): void {
|
|
508
|
-
const fullKey =
|
|
509
|
-
locationToKey(this.storage, this.currentLocation) + "/" + name;
|
|
506
|
+
const fullKey = `${locationToKey(this.storage, this.currentLocation)}/${name}`;
|
|
510
507
|
if (this.usedNamesInExecution.has(fullKey)) {
|
|
511
508
|
throw new HistoryDivergedError(
|
|
512
509
|
`Duplicate entry name "${name}" at location "${locationToKey(this.storage, this.currentLocation)}". ` +
|
|
@@ -580,7 +577,7 @@ export class WorkflowContextImpl implements WorkflowContextInterface {
|
|
|
580
577
|
const isUnderPrefix =
|
|
581
578
|
prefix === ""
|
|
582
579
|
? true // Root: all keys are children
|
|
583
|
-
: key.startsWith(prefix
|
|
580
|
+
: key.startsWith(`${prefix}/`) || key === prefix;
|
|
584
581
|
|
|
585
582
|
if (isUnderPrefix) {
|
|
586
583
|
if (!this.visitedKeys.has(key)) {
|
|
@@ -603,25 +600,33 @@ export class WorkflowContextImpl implements WorkflowContextInterface {
|
|
|
603
600
|
}
|
|
604
601
|
|
|
605
602
|
/**
|
|
606
|
-
* Wait for
|
|
607
|
-
*
|
|
608
|
-
*
|
|
609
|
-
*
|
|
603
|
+
* Wait for `ms`, rejecting early with EvictedError if the workflow is
|
|
604
|
+
* evicted. Both the timer and the abort listener are torn down on either
|
|
605
|
+
* outcome, so a completed sleep never leaves a dangling listener on the
|
|
606
|
+
* long-lived run abort signal.
|
|
610
607
|
*/
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
608
|
+
private async sleepOrEvict(ms: number): Promise<void> {
|
|
609
|
+
if (this.abortSignal.aborted) {
|
|
610
|
+
throw new EvictedError();
|
|
611
|
+
}
|
|
612
|
+
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
613
|
+
let onAbort: (() => void) | undefined;
|
|
614
|
+
try {
|
|
615
|
+
await new Promise<void>((resolve, reject) => {
|
|
616
|
+
timer = setTimeout(resolve, ms);
|
|
617
|
+
onAbort = () => reject(new EvictedError());
|
|
618
|
+
this.abortSignal.addEventListener("abort", onAbort, {
|
|
619
|
+
once: true,
|
|
620
|
+
});
|
|
621
|
+
});
|
|
622
|
+
} finally {
|
|
623
|
+
if (timer !== undefined) {
|
|
624
|
+
clearTimeout(timer);
|
|
616
625
|
}
|
|
617
|
-
|
|
618
|
-
"abort",
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
},
|
|
622
|
-
{ once: true },
|
|
623
|
-
);
|
|
624
|
-
});
|
|
626
|
+
if (onAbort) {
|
|
627
|
+
this.abortSignal.removeEventListener("abort", onAbort);
|
|
628
|
+
}
|
|
629
|
+
}
|
|
625
630
|
}
|
|
626
631
|
|
|
627
632
|
// === Step ===
|
|
@@ -943,8 +948,9 @@ export class WorkflowContextImpl implements WorkflowContextInterface {
|
|
|
943
948
|
}
|
|
944
949
|
entry.dirty = true;
|
|
945
950
|
|
|
946
|
-
// Timeout errors are treated as critical
|
|
947
|
-
|
|
951
|
+
// Timeout errors are treated as critical by default. Steps opt
|
|
952
|
+
// into retrying on timeout with retryOnTimeout: true.
|
|
953
|
+
if (error instanceof StepTimeoutError && !config.retryOnTimeout) {
|
|
948
954
|
metadata.status = "exhausted";
|
|
949
955
|
metadata.error = String(error);
|
|
950
956
|
await this.notifyStepError(config, metadata.attempts, error, {
|
|
@@ -1010,7 +1016,10 @@ export class WorkflowContextImpl implements WorkflowContextInterface {
|
|
|
1010
1016
|
attachTryStepFailure(
|
|
1011
1017
|
new StepExhaustedError(config.name, String(error)),
|
|
1012
1018
|
{
|
|
1013
|
-
kind:
|
|
1019
|
+
kind:
|
|
1020
|
+
error instanceof StepTimeoutError
|
|
1021
|
+
? "timeout"
|
|
1022
|
+
: "exhausted",
|
|
1014
1023
|
stepName: config.name,
|
|
1015
1024
|
attempts: metadata.attempts,
|
|
1016
1025
|
error: extractErrorInfo(error),
|
|
@@ -1029,7 +1038,9 @@ export class WorkflowContextImpl implements WorkflowContextInterface {
|
|
|
1029
1038
|
*
|
|
1030
1039
|
* Note: This does NOT cancel the underlying operation. JavaScript Promises
|
|
1031
1040
|
* cannot be cancelled once started. When a timeout occurs:
|
|
1032
|
-
* - The step is
|
|
1041
|
+
* - The step is rejected with StepTimeoutError. By default this is treated
|
|
1042
|
+
* as a critical failure with no retry. Set retryOnTimeout: true on the
|
|
1043
|
+
* step config to retry timeouts like any other error.
|
|
1033
1044
|
* - The underlying async operation continues running in the background
|
|
1034
1045
|
* - Any side effects from the operation may still occur
|
|
1035
1046
|
*
|
|
@@ -1480,7 +1491,7 @@ export class WorkflowContextImpl implements WorkflowContextInterface {
|
|
|
1480
1491
|
|
|
1481
1492
|
// Short sleep: wait in memory
|
|
1482
1493
|
if (remaining < this.driver.workerPollInterval) {
|
|
1483
|
-
await
|
|
1494
|
+
await this.sleepOrEvict(remaining);
|
|
1484
1495
|
|
|
1485
1496
|
this.checkEvicted();
|
|
1486
1497
|
|
package/src/index.ts
CHANGED
|
@@ -13,6 +13,7 @@ export {
|
|
|
13
13
|
} from "./context.js";
|
|
14
14
|
// Driver
|
|
15
15
|
export type { EngineDriver, KVEntry, KVWrite } from "./driver.js";
|
|
16
|
+
export { extractErrorInfo } from "./error-utils.js";
|
|
16
17
|
// Errors
|
|
17
18
|
export {
|
|
18
19
|
CancelledError,
|
|
@@ -29,7 +30,6 @@ export {
|
|
|
29
30
|
StepExhaustedError,
|
|
30
31
|
StepFailedError,
|
|
31
32
|
} from "./errors.js";
|
|
32
|
-
export { extractErrorInfo } from "./error-utils.js";
|
|
33
33
|
|
|
34
34
|
// Location utilities
|
|
35
35
|
export {
|
|
@@ -82,9 +82,6 @@ export type {
|
|
|
82
82
|
PathSegment,
|
|
83
83
|
RaceEntry,
|
|
84
84
|
RemovedEntry,
|
|
85
|
-
WorkflowEntryMetadataSnapshot,
|
|
86
|
-
WorkflowHistoryEntry,
|
|
87
|
-
WorkflowHistorySnapshot,
|
|
88
85
|
RollbackCheckpointEntry,
|
|
89
86
|
RollbackContextInterface,
|
|
90
87
|
RunWorkflowOptions,
|
|
@@ -102,20 +99,23 @@ export type {
|
|
|
102
99
|
TryStepFailure,
|
|
103
100
|
TryStepResult,
|
|
104
101
|
WorkflowContextInterface,
|
|
102
|
+
WorkflowEntryMetadataSnapshot,
|
|
105
103
|
WorkflowError,
|
|
106
104
|
WorkflowErrorEvent,
|
|
107
105
|
WorkflowErrorHandler,
|
|
108
106
|
WorkflowFunction,
|
|
109
107
|
WorkflowHandle,
|
|
110
|
-
|
|
108
|
+
WorkflowHistoryEntry,
|
|
109
|
+
WorkflowHistorySnapshot,
|
|
110
|
+
WorkflowMessageDriver,
|
|
111
111
|
WorkflowQueue,
|
|
112
112
|
WorkflowQueueMessage,
|
|
113
113
|
WorkflowQueueNextBatchOptions,
|
|
114
114
|
WorkflowQueueNextOptions,
|
|
115
|
-
WorkflowMessageDriver,
|
|
116
115
|
WorkflowResult,
|
|
117
|
-
|
|
116
|
+
WorkflowRollbackErrorEvent,
|
|
118
117
|
WorkflowRunErrorEvent,
|
|
118
|
+
WorkflowRunMode,
|
|
119
119
|
WorkflowState,
|
|
120
120
|
WorkflowStepErrorEvent,
|
|
121
121
|
} from "./types.js";
|
|
@@ -185,9 +185,9 @@ import type {
|
|
|
185
185
|
RunWorkflowOptions,
|
|
186
186
|
Storage,
|
|
187
187
|
WorkflowErrorEvent,
|
|
188
|
-
WorkflowHistorySnapshot,
|
|
189
188
|
WorkflowFunction,
|
|
190
189
|
WorkflowHandle,
|
|
190
|
+
WorkflowHistorySnapshot,
|
|
191
191
|
WorkflowMessageDriver,
|
|
192
192
|
WorkflowResult,
|
|
193
193
|
WorkflowRunMode,
|
|
@@ -532,26 +532,46 @@ async function executeLiveWorkflow<TInput, TOutput>(
|
|
|
532
532
|
const hasDeadline = result.sleepUntil !== undefined;
|
|
533
533
|
|
|
534
534
|
if (hasMessages && hasDeadline) {
|
|
535
|
-
// Wait for EITHER a message OR the deadline (for queue.next timeout)
|
|
535
|
+
// Wait for EITHER a message OR the deadline (for queue.next timeout).
|
|
536
|
+
// Scope both waiters to a per-iteration controller chained to the run
|
|
537
|
+
// signal so that whichever loses the race is cancelled immediately.
|
|
538
|
+
// Otherwise the loser (a message waiter or an armed sleep timer) stays
|
|
539
|
+
// registered on the long-lived run signal and leaks once per cycle.
|
|
540
|
+
const iterationAbort = new AbortController();
|
|
541
|
+
const onRunAbort = () => iterationAbort.abort();
|
|
542
|
+
if (abortController.signal.aborted) {
|
|
543
|
+
iterationAbort.abort();
|
|
544
|
+
} else {
|
|
545
|
+
abortController.signal.addEventListener("abort", onRunAbort, {
|
|
546
|
+
once: true,
|
|
547
|
+
});
|
|
548
|
+
}
|
|
549
|
+
const messagePromise = awaitWithEviction(
|
|
550
|
+
driver.waitForMessages(
|
|
551
|
+
result.waitingForMessages!,
|
|
552
|
+
iterationAbort.signal,
|
|
553
|
+
),
|
|
554
|
+
iterationAbort.signal,
|
|
555
|
+
);
|
|
556
|
+
const sleepPromise = waitForSleep(
|
|
557
|
+
runtime,
|
|
558
|
+
result.sleepUntil!,
|
|
559
|
+
iterationAbort.signal,
|
|
560
|
+
);
|
|
561
|
+
// Swallow the loser's rejection once it is aborted below so it does
|
|
562
|
+
// not surface as an unhandled rejection.
|
|
563
|
+
messagePromise.catch(() => {});
|
|
564
|
+
sleepPromise.catch(() => {});
|
|
536
565
|
try {
|
|
537
|
-
const messagePromise = awaitWithEviction(
|
|
538
|
-
driver.waitForMessages(
|
|
539
|
-
result.waitingForMessages!,
|
|
540
|
-
abortController.signal,
|
|
541
|
-
),
|
|
542
|
-
abortController.signal,
|
|
543
|
-
);
|
|
544
|
-
const sleepPromise = waitForSleep(
|
|
545
|
-
runtime,
|
|
546
|
-
result.sleepUntil!,
|
|
547
|
-
abortController.signal,
|
|
548
|
-
);
|
|
549
566
|
await Promise.race([messagePromise, sleepPromise]);
|
|
550
567
|
} catch (error) {
|
|
551
568
|
if (error instanceof EvictedError) {
|
|
552
569
|
return lastResult;
|
|
553
570
|
}
|
|
554
571
|
throw error;
|
|
572
|
+
} finally {
|
|
573
|
+
iterationAbort.abort();
|
|
574
|
+
abortController.signal.removeEventListener("abort", onRunAbort);
|
|
555
575
|
}
|
|
556
576
|
continue;
|
|
557
577
|
}
|
package/src/location.ts
CHANGED
|
@@ -159,7 +159,7 @@ export function getChildEntries(
|
|
|
159
159
|
const isChild =
|
|
160
160
|
parentKey === ""
|
|
161
161
|
? true
|
|
162
|
-
: key.startsWith(parentKey
|
|
162
|
+
: key.startsWith(`${parentKey}/`) || key === parentKey;
|
|
163
163
|
|
|
164
164
|
if (isChild) {
|
|
165
165
|
// Return the actual entry's location, not the parent location
|
package/src/types.ts
CHANGED
|
@@ -399,6 +399,8 @@ export interface StepConfig<T> {
|
|
|
399
399
|
retryBackoffMax?: number;
|
|
400
400
|
/** Timeout in ms for step execution (default: 30000). Set to 0 to disable. */
|
|
401
401
|
timeout?: number;
|
|
402
|
+
/** If true, step timeouts retry like any other error instead of failing immediately as critical. Default: false. */
|
|
403
|
+
retryOnTimeout?: boolean;
|
|
402
404
|
}
|
|
403
405
|
|
|
404
406
|
export type TryStepCatchKind =
|
|
@@ -455,7 +457,7 @@ export type LoopResult<S, T> =
|
|
|
455
457
|
* `Loop.continue(undefined)`.
|
|
456
458
|
*/
|
|
457
459
|
export type LoopIterationResult<S, T> = Promise<
|
|
458
|
-
LoopResult<S, T> | (S extends undefined ?
|
|
460
|
+
LoopResult<S, T> | (S extends undefined ? undefined : never)
|
|
459
461
|
>;
|
|
460
462
|
|
|
461
463
|
/**
|