@rivetkit/workflow-engine 0.0.0-main.14140ce → 0.0.0-main.17f6330

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.
@@ -43,7 +43,7 @@
43
43
 
44
44
 
45
45
 
46
- var _chunk4SWXLWKLcjs = require('./chunk-4SWXLWKL.cjs');
46
+ var _chunkGQWOLYBAcjs = require('./chunk-GQWOLYBA.cjs');
47
47
 
48
48
 
49
49
 
@@ -89,5 +89,5 @@ var _chunk4SWXLWKLcjs = require('./chunk-4SWXLWKL.cjs');
89
89
 
90
90
 
91
91
 
92
- exports.CancelledError = _chunk4SWXLWKLcjs.CancelledError; exports.CriticalError = _chunk4SWXLWKLcjs.CriticalError; exports.DEFAULT_LOOP_HISTORY_PRUNE_INTERVAL = _chunk4SWXLWKLcjs.DEFAULT_LOOP_HISTORY_PRUNE_INTERVAL; exports.DEFAULT_MAX_RETRIES = _chunk4SWXLWKLcjs.DEFAULT_MAX_RETRIES; exports.DEFAULT_RETRY_BACKOFF_BASE = _chunk4SWXLWKLcjs.DEFAULT_RETRY_BACKOFF_BASE; exports.DEFAULT_RETRY_BACKOFF_MAX = _chunk4SWXLWKLcjs.DEFAULT_RETRY_BACKOFF_MAX; exports.DEFAULT_STEP_TIMEOUT = _chunk4SWXLWKLcjs.DEFAULT_STEP_TIMEOUT; exports.EntryInProgressError = _chunk4SWXLWKLcjs.EntryInProgressError; exports.EvictedError = _chunk4SWXLWKLcjs.EvictedError; exports.HistoryDivergedError = _chunk4SWXLWKLcjs.HistoryDivergedError; exports.JoinError = _chunk4SWXLWKLcjs.JoinError; exports.Loop = _chunk4SWXLWKLcjs.Loop; exports.MessageWaitError = _chunk4SWXLWKLcjs.MessageWaitError; exports.RaceError = _chunk4SWXLWKLcjs.RaceError; exports.RollbackCheckpointError = _chunk4SWXLWKLcjs.RollbackCheckpointError; exports.RollbackError = _chunk4SWXLWKLcjs.RollbackError; exports.SleepError = _chunk4SWXLWKLcjs.SleepError; exports.StepExhaustedError = _chunk4SWXLWKLcjs.StepExhaustedError; exports.StepFailedError = _chunk4SWXLWKLcjs.StepFailedError; exports.WorkflowContextImpl = _chunk4SWXLWKLcjs.WorkflowContextImpl; exports.appendLoopIteration = _chunk4SWXLWKLcjs.appendLoopIteration; exports.appendName = _chunk4SWXLWKLcjs.appendName; exports.createEntry = _chunk4SWXLWKLcjs.createEntry; exports.createHistorySnapshot = _chunk4SWXLWKLcjs.createHistorySnapshot; exports.createStorage = _chunk4SWXLWKLcjs.createStorage; exports.deleteEntriesWithPrefix = _chunk4SWXLWKLcjs.deleteEntriesWithPrefix; exports.emptyLocation = _chunk4SWXLWKLcjs.emptyLocation; exports.extractErrorInfo = _chunk4SWXLWKLcjs.extractErrorInfo; exports.flush = _chunk4SWXLWKLcjs.flush; exports.generateId = _chunk4SWXLWKLcjs.generateId; exports.getEntry = _chunk4SWXLWKLcjs.getEntry; exports.getOrCreateMetadata = _chunk4SWXLWKLcjs.getOrCreateMetadata; exports.isLocationPrefix = _chunk4SWXLWKLcjs.isLocationPrefix; exports.isLoopIterationMarker = _chunk4SWXLWKLcjs.isLoopIterationMarker; exports.loadMetadata = _chunk4SWXLWKLcjs.loadMetadata; exports.loadStorage = _chunk4SWXLWKLcjs.loadStorage; exports.locationToKey = _chunk4SWXLWKLcjs.locationToKey; exports.locationsEqual = _chunk4SWXLWKLcjs.locationsEqual; exports.parentLocation = _chunk4SWXLWKLcjs.parentLocation; exports.registerName = _chunk4SWXLWKLcjs.registerName; exports.replayWorkflowFromStep = _chunk4SWXLWKLcjs.replayWorkflowFromStep; exports.resolveName = _chunk4SWXLWKLcjs.resolveName; exports.runWorkflow = _chunk4SWXLWKLcjs.runWorkflow; exports.setEntry = _chunk4SWXLWKLcjs.setEntry;
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
@@ -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 ? void : never)>;
403
+ type LoopIterationResult<S, T> = Promise<LoopResult<S, T> | (S extends undefined ? undefined : never)>;
402
404
  /**
403
405
  * Configuration for a loop.
404
406
  */
@@ -410,6 +412,12 @@ interface LoopConfig<S, T> {
410
412
  historyPruneInterval?: number;
411
413
  /** Number of past iterations to retain when pruning. Defaults to historyPruneInterval. */
412
414
  historySize?: number;
415
+ /** @deprecated Use historyPruneInterval. */
416
+ commitInterval?: number;
417
+ /** @deprecated Use historyPruneInterval. */
418
+ historyEvery?: number;
419
+ /** @deprecated Use historySize. */
420
+ historyKeep?: number;
413
421
  }
414
422
  /**
415
423
  * Configuration for a branch in join/race.
@@ -691,12 +699,12 @@ declare class WorkflowContextImpl implements WorkflowContextInterface {
691
699
  */
692
700
  evict(): void;
693
701
  /**
694
- * Wait for eviction message.
695
- *
696
- * The event listener uses { once: true } to auto-remove after firing,
697
- * preventing memory leaks if this method is called multiple times.
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.
698
706
  */
699
- waitForEviction(): Promise<never>;
707
+ private sleepOrEvict;
700
708
  step<T>(nameOrConfig: string | StepConfig<T>, run?: () => Promise<T>): Promise<T>;
701
709
  tryStep<T>(nameOrConfig: string | TryStepConfig<T>, run?: () => Promise<T>): Promise<TryStepResult<T>>;
702
710
  try<T>(nameOrConfig: string | TryBlockConfig<T>, run?: (ctx: WorkflowContextInterface) => Promise<T>): Promise<TryBlockResult<T>>;
@@ -707,7 +715,9 @@ declare class WorkflowContextImpl implements WorkflowContextInterface {
707
715
  *
708
716
  * Note: This does NOT cancel the underlying operation. JavaScript Promises
709
717
  * cannot be cancelled once started. When a timeout occurs:
710
- * - The step is marked as failed with StepTimeoutError
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.
711
721
  * - The underlying async operation continues running in the background
712
722
  * - Any side effects from the operation may still occur
713
723
  *
@@ -773,6 +783,11 @@ declare class WorkflowContextImpl implements WorkflowContextInterface {
773
783
  private executeRemoved;
774
784
  }
775
785
 
786
+ /**
787
+ * Extract structured error information from an error.
788
+ */
789
+ declare function extractErrorInfo(error: unknown): WorkflowError;
790
+
776
791
  /**
777
792
  * Thrown from steps to prevent retry.
778
793
  * Use this when an error is unrecoverable and retrying would be pointless.
@@ -877,11 +892,6 @@ declare class EntryInProgressError extends Error {
877
892
  constructor();
878
893
  }
879
894
 
880
- /**
881
- * Extract structured error information from an error.
882
- */
883
- declare function extractErrorInfo(error: unknown): WorkflowError;
884
-
885
895
  /**
886
896
  * Check if a path segment is a loop iteration marker.
887
897
  */
@@ -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 ? void : never)>;
403
+ type LoopIterationResult<S, T> = Promise<LoopResult<S, T> | (S extends undefined ? undefined : never)>;
402
404
  /**
403
405
  * Configuration for a loop.
404
406
  */
@@ -410,6 +412,12 @@ interface LoopConfig<S, T> {
410
412
  historyPruneInterval?: number;
411
413
  /** Number of past iterations to retain when pruning. Defaults to historyPruneInterval. */
412
414
  historySize?: number;
415
+ /** @deprecated Use historyPruneInterval. */
416
+ commitInterval?: number;
417
+ /** @deprecated Use historyPruneInterval. */
418
+ historyEvery?: number;
419
+ /** @deprecated Use historySize. */
420
+ historyKeep?: number;
413
421
  }
414
422
  /**
415
423
  * Configuration for a branch in join/race.
@@ -691,12 +699,12 @@ declare class WorkflowContextImpl implements WorkflowContextInterface {
691
699
  */
692
700
  evict(): void;
693
701
  /**
694
- * Wait for eviction message.
695
- *
696
- * The event listener uses { once: true } to auto-remove after firing,
697
- * preventing memory leaks if this method is called multiple times.
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.
698
706
  */
699
- waitForEviction(): Promise<never>;
707
+ private sleepOrEvict;
700
708
  step<T>(nameOrConfig: string | StepConfig<T>, run?: () => Promise<T>): Promise<T>;
701
709
  tryStep<T>(nameOrConfig: string | TryStepConfig<T>, run?: () => Promise<T>): Promise<TryStepResult<T>>;
702
710
  try<T>(nameOrConfig: string | TryBlockConfig<T>, run?: (ctx: WorkflowContextInterface) => Promise<T>): Promise<TryBlockResult<T>>;
@@ -707,7 +715,9 @@ declare class WorkflowContextImpl implements WorkflowContextInterface {
707
715
  *
708
716
  * Note: This does NOT cancel the underlying operation. JavaScript Promises
709
717
  * cannot be cancelled once started. When a timeout occurs:
710
- * - The step is marked as failed with StepTimeoutError
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.
711
721
  * - The underlying async operation continues running in the background
712
722
  * - Any side effects from the operation may still occur
713
723
  *
@@ -773,6 +783,11 @@ declare class WorkflowContextImpl implements WorkflowContextInterface {
773
783
  private executeRemoved;
774
784
  }
775
785
 
786
+ /**
787
+ * Extract structured error information from an error.
788
+ */
789
+ declare function extractErrorInfo(error: unknown): WorkflowError;
790
+
776
791
  /**
777
792
  * Thrown from steps to prevent retry.
778
793
  * Use this when an error is unrecoverable and retrying would be pointless.
@@ -877,11 +892,6 @@ declare class EntryInProgressError extends Error {
877
892
  constructor();
878
893
  }
879
894
 
880
- /**
881
- * Extract structured error information from an error.
882
- */
883
- declare function extractErrorInfo(error: unknown): WorkflowError;
884
-
885
895
  /**
886
896
  * Check if a path segment is a loop iteration marker.
887
897
  */
@@ -43,7 +43,7 @@ import {
43
43
  resolveName,
44
44
  runWorkflow,
45
45
  setEntry
46
- } from "./chunk-UMFB2AR3.js";
46
+ } from "./chunk-KA2T56AJ.js";
47
47
  export {
48
48
  CancelledError,
49
49
  CriticalError,
@@ -47,7 +47,7 @@
47
47
 
48
48
 
49
49
 
50
- var _chunk4SWXLWKLcjs = require('./chunk-4SWXLWKL.cjs');
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, _chunk4SWXLWKLcjs.EvictedError)();
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, _chunk4SWXLWKLcjs.EvictedError)());
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 _chunk4SWXLWKLcjs.sleep.call(void 0, this.latency);
162
- const entry = this.kv.get(_chunk4SWXLWKLcjs.keyToHex.call(void 0, key));
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 _chunk4SWXLWKLcjs.sleep.call(void 0, this.latency);
167
- this.kv.set(_chunk4SWXLWKLcjs.keyToHex.call(void 0, key), { key, value });
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 _chunk4SWXLWKLcjs.sleep.call(void 0, this.latency);
171
- this.kv.delete(_chunk4SWXLWKLcjs.keyToHex.call(void 0, key));
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 _chunk4SWXLWKLcjs.sleep.call(void 0, this.latency);
174
+ await _chunkGQWOLYBAcjs.sleep.call(void 0, this.latency);
175
175
  for (const [hexKey, entry] of this.kv) {
176
- if (_chunk4SWXLWKLcjs.keyStartsWith.call(void 0, entry.key, prefix)) {
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 _chunk4SWXLWKLcjs.sleep.call(void 0, this.latency);
182
+ await _chunkGQWOLYBAcjs.sleep.call(void 0, this.latency);
183
183
  for (const [hexKey, entry] of this.kv) {
184
- if (_chunk4SWXLWKLcjs.compareKeys.call(void 0, entry.key, start) >= 0 && _chunk4SWXLWKLcjs.compareKeys.call(void 0, entry.key, end) < 0) {
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 _chunk4SWXLWKLcjs.sleep.call(void 0, this.latency);
190
+ await _chunkGQWOLYBAcjs.sleep.call(void 0, this.latency);
191
191
  const results = [];
192
192
  for (const entry of this.kv.values()) {
193
- if (_chunk4SWXLWKLcjs.keyStartsWith.call(void 0, entry.key, prefix)) {
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) => _chunk4SWXLWKLcjs.compareKeys.call(void 0, a.key, b.key));
197
+ return results.sort((a, b) => _chunkGQWOLYBAcjs.compareKeys.call(void 0, a.key, b.key));
198
198
  }
199
199
  async batch(writes) {
200
- await _chunk4SWXLWKLcjs.sleep.call(void 0, this.latency);
200
+ await _chunkGQWOLYBAcjs.sleep.call(void 0, this.latency);
201
201
  for (const { key, value } of writes) {
202
- this.kv.set(_chunk4SWXLWKLcjs.keyToHex.call(void 0, key), { key, value });
202
+ this.kv.set(_chunkGQWOLYBAcjs.keyToHex.call(void 0, key), { key, value });
203
203
  }
204
204
  }
205
205
  async setAlarm(workflowId, wakeAt) {
206
- await _chunk4SWXLWKLcjs.sleep.call(void 0, this.latency);
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 _chunk4SWXLWKLcjs.sleep.call(void 0, this.latency);
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, _chunk4SWXLWKLcjs.EvictedError)();
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 _chunk4SWXLWKLcjs.sleep.call(void 0, Math.max(1, this.latency));
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 = _chunk4SWXLWKLcjs.CancelledError; exports.CriticalError = _chunk4SWXLWKLcjs.CriticalError; exports.DEFAULT_LOOP_HISTORY_PRUNE_INTERVAL = _chunk4SWXLWKLcjs.DEFAULT_LOOP_HISTORY_PRUNE_INTERVAL; exports.DEFAULT_MAX_RETRIES = _chunk4SWXLWKLcjs.DEFAULT_MAX_RETRIES; exports.DEFAULT_RETRY_BACKOFF_BASE = _chunk4SWXLWKLcjs.DEFAULT_RETRY_BACKOFF_BASE; exports.DEFAULT_RETRY_BACKOFF_MAX = _chunk4SWXLWKLcjs.DEFAULT_RETRY_BACKOFF_MAX; exports.DEFAULT_STEP_TIMEOUT = _chunk4SWXLWKLcjs.DEFAULT_STEP_TIMEOUT; exports.EntryInProgressError = _chunk4SWXLWKLcjs.EntryInProgressError; exports.EvictedError = _chunk4SWXLWKLcjs.EvictedError; exports.HistoryDivergedError = _chunk4SWXLWKLcjs.HistoryDivergedError; exports.InMemoryDriver = InMemoryDriver; exports.JoinError = _chunk4SWXLWKLcjs.JoinError; exports.Loop = _chunk4SWXLWKLcjs.Loop; exports.MessageWaitError = _chunk4SWXLWKLcjs.MessageWaitError; exports.RaceError = _chunk4SWXLWKLcjs.RaceError; exports.RollbackCheckpointError = _chunk4SWXLWKLcjs.RollbackCheckpointError; exports.RollbackError = _chunk4SWXLWKLcjs.RollbackError; exports.SleepError = _chunk4SWXLWKLcjs.SleepError; exports.StepExhaustedError = _chunk4SWXLWKLcjs.StepExhaustedError; exports.StepFailedError = _chunk4SWXLWKLcjs.StepFailedError; exports.WorkflowContextImpl = _chunk4SWXLWKLcjs.WorkflowContextImpl; exports.appendLoopIteration = _chunk4SWXLWKLcjs.appendLoopIteration; exports.appendName = _chunk4SWXLWKLcjs.appendName; exports.createEntry = _chunk4SWXLWKLcjs.createEntry; exports.createHistorySnapshot = _chunk4SWXLWKLcjs.createHistorySnapshot; exports.createStorage = _chunk4SWXLWKLcjs.createStorage; exports.deleteEntriesWithPrefix = _chunk4SWXLWKLcjs.deleteEntriesWithPrefix; exports.emptyLocation = _chunk4SWXLWKLcjs.emptyLocation; exports.extractErrorInfo = _chunk4SWXLWKLcjs.extractErrorInfo; exports.flush = _chunk4SWXLWKLcjs.flush; exports.generateId = _chunk4SWXLWKLcjs.generateId; exports.getEntry = _chunk4SWXLWKLcjs.getEntry; exports.getOrCreateMetadata = _chunk4SWXLWKLcjs.getOrCreateMetadata; exports.isLocationPrefix = _chunk4SWXLWKLcjs.isLocationPrefix; exports.isLoopIterationMarker = _chunk4SWXLWKLcjs.isLoopIterationMarker; exports.loadMetadata = _chunk4SWXLWKLcjs.loadMetadata; exports.loadStorage = _chunk4SWXLWKLcjs.loadStorage; exports.locationToKey = _chunk4SWXLWKLcjs.locationToKey; exports.locationsEqual = _chunk4SWXLWKLcjs.locationsEqual; exports.parentLocation = _chunk4SWXLWKLcjs.parentLocation; exports.registerName = _chunk4SWXLWKLcjs.registerName; exports.replayWorkflowFromStep = _chunk4SWXLWKLcjs.replayWorkflowFromStep; exports.resolveName = _chunk4SWXLWKLcjs.resolveName; exports.runWorkflow = _chunk4SWXLWKLcjs.runWorkflow; exports.setEntry = _chunk4SWXLWKLcjs.setEntry;
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
@@ -47,7 +47,7 @@ import {
47
47
  runWorkflow,
48
48
  setEntry,
49
49
  sleep
50
- } from "./chunk-UMFB2AR3.js";
50
+ } from "./chunk-KA2T56AJ.js";
51
51
 
52
52
  // src/testing.ts
53
53
  var InMemoryWorkflowMessageDriver = class {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rivetkit/workflow-engine",
3
- "version": "0.0.0-main.14140ce",
3
+ "version": "0.0.0-main.17f6330",
4
4
  "description": "Durable workflow engine with reentrant execution",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [
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 assertNumber(
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 { buildLoopIterationRange, buildEntryMetadataKey } from "./keys.js";
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 + "/") || key === 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 eviction message.
607
- *
608
- * The event listener uses { once: true } to auto-remove after firing,
609
- * preventing memory leaks if this method is called multiple times.
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
- waitForEviction(): Promise<never> {
612
- return new Promise((_, reject) => {
613
- if (this.abortSignal.aborted) {
614
- reject(new EvictedError());
615
- return;
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
- this.abortSignal.addEventListener(
618
- "abort",
619
- () => {
620
- reject(new EvictedError());
621
- },
622
- { once: true },
623
- );
624
- });
626
+ if (onAbort) {
627
+ this.abortSignal.removeEventListener("abort", onAbort);
628
+ }
629
+ }
625
630
  }
626
631
 
627
632
  // === Step ===
@@ -825,10 +830,7 @@ export class WorkflowContextImpl implements WorkflowContextInterface {
825
830
  const maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;
826
831
 
827
832
  if (metadata.attempts > maxRetries) {
828
- // Prefer step history error, but fall back to metadata since
829
- // driver implementations may persist metadata without the history
830
- // entry error (e.g. partial writes/crashes between attempts).
831
- const lastError = stepData.error ?? metadata.error;
833
+ const lastError = metadata.error;
832
834
  const exhaustedError = new StepExhaustedError(
833
835
  config.name,
834
836
  lastError,
@@ -941,28 +943,26 @@ export class WorkflowContextImpl implements WorkflowContextInterface {
941
943
  });
942
944
  return output;
943
945
  } catch (error) {
944
- // Timeout errors are treated as critical (no retry)
945
- if (error instanceof StepTimeoutError) {
946
- if (entry.kind.type === "step") {
947
- entry.kind.data.error = String(error);
948
- }
949
- entry.dirty = true;
946
+ if (entry.kind.type === "step") {
947
+ entry.kind.data.error = String(error);
948
+ }
949
+ entry.dirty = true;
950
+
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) {
950
954
  metadata.status = "exhausted";
951
955
  metadata.error = String(error);
952
- await this.flushStorage();
953
956
  await this.notifyStepError(config, metadata.attempts, error, {
954
957
  willRetry: false,
955
958
  });
956
959
  throw markErrorReported(
957
- attachTryStepFailure(
958
- new CriticalError(error.message),
959
- {
960
- kind: "timeout",
961
- stepName: config.name,
962
- attempts: metadata.attempts,
963
- error: extractErrorInfo(error),
964
- },
965
- ),
960
+ attachTryStepFailure(new CriticalError(error.message), {
961
+ kind: "timeout",
962
+ stepName: config.name,
963
+ attempts: metadata.attempts,
964
+ error: extractErrorInfo(error),
965
+ }),
966
966
  );
967
967
  }
968
968
 
@@ -970,13 +970,8 @@ export class WorkflowContextImpl implements WorkflowContextInterface {
970
970
  error instanceof CriticalError ||
971
971
  error instanceof RollbackError
972
972
  ) {
973
- if (entry.kind.type === "step") {
974
- entry.kind.data.error = String(error);
975
- }
976
- entry.dirty = true;
977
973
  metadata.status = "exhausted";
978
974
  metadata.error = String(error);
979
- await this.flushStorage();
980
975
  await this.notifyStepError(config, metadata.attempts, error, {
981
976
  willRetry: false,
982
977
  });
@@ -993,15 +988,10 @@ export class WorkflowContextImpl implements WorkflowContextInterface {
993
988
  );
994
989
  }
995
990
 
996
- if (entry.kind.type === "step") {
997
- entry.kind.data.error = String(error);
998
- }
999
- entry.dirty = true;
1000
991
  const willRetry = metadata.attempts <= maxRetries;
1001
992
  metadata.status = willRetry ? "failed" : "exhausted";
1002
993
  metadata.error = String(error);
1003
994
 
1004
- await this.flushStorage();
1005
995
  if (willRetry) {
1006
996
  const retryDelay = calculateBackoff(
1007
997
  metadata.attempts,
@@ -1026,7 +1016,10 @@ export class WorkflowContextImpl implements WorkflowContextInterface {
1026
1016
  attachTryStepFailure(
1027
1017
  new StepExhaustedError(config.name, String(error)),
1028
1018
  {
1029
- kind: "exhausted",
1019
+ kind:
1020
+ error instanceof StepTimeoutError
1021
+ ? "timeout"
1022
+ : "exhausted",
1030
1023
  stepName: config.name,
1031
1024
  attempts: metadata.attempts,
1032
1025
  error: extractErrorInfo(error),
@@ -1045,7 +1038,9 @@ export class WorkflowContextImpl implements WorkflowContextInterface {
1045
1038
  *
1046
1039
  * Note: This does NOT cancel the underlying operation. JavaScript Promises
1047
1040
  * cannot be cancelled once started. When a timeout occurs:
1048
- * - The step is marked as failed with StepTimeoutError
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.
1049
1044
  * - The underlying async operation continues running in the background
1050
1045
  * - Any side effects from the operation may still occur
1051
1046
  *
@@ -1224,8 +1219,12 @@ export class WorkflowContextImpl implements WorkflowContextInterface {
1224
1219
  }
1225
1220
 
1226
1221
  const historyPruneInterval =
1227
- config.historyPruneInterval ?? DEFAULT_LOOP_HISTORY_PRUNE_INTERVAL;
1228
- const historySize = config.historySize ?? historyPruneInterval;
1222
+ config.historyPruneInterval ??
1223
+ config.commitInterval ??
1224
+ config.historyEvery ??
1225
+ DEFAULT_LOOP_HISTORY_PRUNE_INTERVAL;
1226
+ const historySize =
1227
+ config.historySize ?? config.historyKeep ?? historyPruneInterval;
1229
1228
 
1230
1229
  // Track the last iteration we pruned up to so we only delete
1231
1230
  // newly-expired iterations instead of re-scanning from 0.
@@ -1492,7 +1491,7 @@ export class WorkflowContextImpl implements WorkflowContextInterface {
1492
1491
 
1493
1492
  // Short sleep: wait in memory
1494
1493
  if (remaining < this.driver.workerPollInterval) {
1495
- await Promise.race([sleep(remaining), this.waitForEviction()]);
1494
+ await this.sleepOrEvict(remaining);
1496
1495
 
1497
1496
  this.checkEvicted();
1498
1497