@rivetkit/workflow-engine 2.3.0-rc.4 → 2.3.0-rc.5

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.
@@ -47,7 +47,7 @@
47
47
 
48
48
 
49
49
 
50
- var _chunk4SWXLWKLcjs = require('./chunk-4SWXLWKL.cjs');
50
+ var _chunkSFJQFMCWcjs = require('./chunk-SFJQFMCW.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, _chunkSFJQFMCWcjs.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, _chunkSFJQFMCWcjs.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 _chunkSFJQFMCWcjs.sleep.call(void 0, this.latency);
162
+ const entry = this.kv.get(_chunkSFJQFMCWcjs.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 _chunkSFJQFMCWcjs.sleep.call(void 0, this.latency);
167
+ this.kv.set(_chunkSFJQFMCWcjs.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 _chunkSFJQFMCWcjs.sleep.call(void 0, this.latency);
171
+ this.kv.delete(_chunkSFJQFMCWcjs.keyToHex.call(void 0, key));
172
172
  }
173
173
  async deletePrefix(prefix) {
174
- await _chunk4SWXLWKLcjs.sleep.call(void 0, this.latency);
174
+ await _chunkSFJQFMCWcjs.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 (_chunkSFJQFMCWcjs.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 _chunkSFJQFMCWcjs.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 (_chunkSFJQFMCWcjs.compareKeys.call(void 0, entry.key, start) >= 0 && _chunkSFJQFMCWcjs.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 _chunkSFJQFMCWcjs.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 (_chunkSFJQFMCWcjs.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) => _chunkSFJQFMCWcjs.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 _chunkSFJQFMCWcjs.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(_chunkSFJQFMCWcjs.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 _chunkSFJQFMCWcjs.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 _chunkSFJQFMCWcjs.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, _chunkSFJQFMCWcjs.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 _chunkSFJQFMCWcjs.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 = _chunkSFJQFMCWcjs.CancelledError; exports.CriticalError = _chunkSFJQFMCWcjs.CriticalError; exports.DEFAULT_LOOP_HISTORY_PRUNE_INTERVAL = _chunkSFJQFMCWcjs.DEFAULT_LOOP_HISTORY_PRUNE_INTERVAL; exports.DEFAULT_MAX_RETRIES = _chunkSFJQFMCWcjs.DEFAULT_MAX_RETRIES; exports.DEFAULT_RETRY_BACKOFF_BASE = _chunkSFJQFMCWcjs.DEFAULT_RETRY_BACKOFF_BASE; exports.DEFAULT_RETRY_BACKOFF_MAX = _chunkSFJQFMCWcjs.DEFAULT_RETRY_BACKOFF_MAX; exports.DEFAULT_STEP_TIMEOUT = _chunkSFJQFMCWcjs.DEFAULT_STEP_TIMEOUT; exports.EntryInProgressError = _chunkSFJQFMCWcjs.EntryInProgressError; exports.EvictedError = _chunkSFJQFMCWcjs.EvictedError; exports.HistoryDivergedError = _chunkSFJQFMCWcjs.HistoryDivergedError; exports.InMemoryDriver = InMemoryDriver; exports.JoinError = _chunkSFJQFMCWcjs.JoinError; exports.Loop = _chunkSFJQFMCWcjs.Loop; exports.MessageWaitError = _chunkSFJQFMCWcjs.MessageWaitError; exports.RaceError = _chunkSFJQFMCWcjs.RaceError; exports.RollbackCheckpointError = _chunkSFJQFMCWcjs.RollbackCheckpointError; exports.RollbackError = _chunkSFJQFMCWcjs.RollbackError; exports.SleepError = _chunkSFJQFMCWcjs.SleepError; exports.StepExhaustedError = _chunkSFJQFMCWcjs.StepExhaustedError; exports.StepFailedError = _chunkSFJQFMCWcjs.StepFailedError; exports.WorkflowContextImpl = _chunkSFJQFMCWcjs.WorkflowContextImpl; exports.appendLoopIteration = _chunkSFJQFMCWcjs.appendLoopIteration; exports.appendName = _chunkSFJQFMCWcjs.appendName; exports.createEntry = _chunkSFJQFMCWcjs.createEntry; exports.createHistorySnapshot = _chunkSFJQFMCWcjs.createHistorySnapshot; exports.createStorage = _chunkSFJQFMCWcjs.createStorage; exports.deleteEntriesWithPrefix = _chunkSFJQFMCWcjs.deleteEntriesWithPrefix; exports.emptyLocation = _chunkSFJQFMCWcjs.emptyLocation; exports.extractErrorInfo = _chunkSFJQFMCWcjs.extractErrorInfo; exports.flush = _chunkSFJQFMCWcjs.flush; exports.generateId = _chunkSFJQFMCWcjs.generateId; exports.getEntry = _chunkSFJQFMCWcjs.getEntry; exports.getOrCreateMetadata = _chunkSFJQFMCWcjs.getOrCreateMetadata; exports.isLocationPrefix = _chunkSFJQFMCWcjs.isLocationPrefix; exports.isLoopIterationMarker = _chunkSFJQFMCWcjs.isLoopIterationMarker; exports.loadMetadata = _chunkSFJQFMCWcjs.loadMetadata; exports.loadStorage = _chunkSFJQFMCWcjs.loadStorage; exports.locationToKey = _chunkSFJQFMCWcjs.locationToKey; exports.locationsEqual = _chunkSFJQFMCWcjs.locationsEqual; exports.parentLocation = _chunkSFJQFMCWcjs.parentLocation; exports.registerName = _chunkSFJQFMCWcjs.registerName; exports.replayWorkflowFromStep = _chunkSFJQFMCWcjs.replayWorkflowFromStep; exports.resolveName = _chunkSFJQFMCWcjs.resolveName; exports.runWorkflow = _chunkSFJQFMCWcjs.runWorkflow; exports.setEntry = _chunkSFJQFMCWcjs.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-CIDHCIH7.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": "2.3.0-rc.4",
3
+ "version": "2.3.0-rc.5",
4
4
  "description": "Durable workflow engine with reentrant execution",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [
package/src/context.ts CHANGED
@@ -954,15 +954,12 @@ export class WorkflowContextImpl implements WorkflowContextInterface {
954
954
  willRetry: false,
955
955
  });
956
956
  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
- ),
957
+ attachTryStepFailure(new CriticalError(error.message), {
958
+ kind: "timeout",
959
+ stepName: config.name,
960
+ attempts: metadata.attempts,
961
+ error: extractErrorInfo(error),
962
+ }),
966
963
  );
967
964
  }
968
965
 
@@ -1224,8 +1221,12 @@ export class WorkflowContextImpl implements WorkflowContextInterface {
1224
1221
  }
1225
1222
 
1226
1223
  const historyPruneInterval =
1227
- config.historyPruneInterval ?? DEFAULT_LOOP_HISTORY_PRUNE_INTERVAL;
1228
- const historySize = config.historySize ?? historyPruneInterval;
1224
+ config.historyPruneInterval ??
1225
+ config.commitInterval ??
1226
+ config.historyEvery ??
1227
+ DEFAULT_LOOP_HISTORY_PRUNE_INTERVAL;
1228
+ const historySize =
1229
+ config.historySize ?? config.historyKeep ?? historyPruneInterval;
1229
1230
 
1230
1231
  // Track the last iteration we pruned up to so we only delete
1231
1232
  // newly-expired iterations instead of re-scanning from 0.
package/src/storage.ts CHANGED
@@ -40,6 +40,9 @@ import type {
40
40
  WorkflowHistorySnapshot,
41
41
  } from "./types.js";
42
42
 
43
+ export const MAX_KV_BATCH_ENTRIES = 128;
44
+ export const MAX_KV_BATCH_PAYLOAD_BYTES = 976 * 1024;
45
+
43
46
  /**
44
47
  * Create an empty storage instance.
45
48
  */
@@ -238,6 +241,8 @@ export async function flush(
238
241
  pendingDeletions?: PendingDeletions,
239
242
  ): Promise<void> {
240
243
  const writes: KVWrite[] = [];
244
+ const dirtyEntries: Entry[] = [];
245
+ const dirtyMetadata: EntryMetadata[] = [];
241
246
  let historyUpdated = false;
242
247
 
243
248
  // Flush only new names (those added since last flush)
@@ -263,7 +268,7 @@ export async function flush(
263
268
  key: buildHistoryKey(entry.location),
264
269
  value: serializeEntry(entry),
265
270
  });
266
- entry.dirty = false;
271
+ dirtyEntries.push(entry);
267
272
  historyUpdated = true;
268
273
  }
269
274
  }
@@ -275,7 +280,7 @@ export async function flush(
275
280
  key: buildEntryMetadataKey(id),
276
281
  value: serializeEntryMetadata(metadata),
277
282
  });
278
- metadata.dirty = false;
283
+ dirtyMetadata.push(metadata);
279
284
  historyUpdated = true;
280
285
  }
281
286
  }
@@ -313,7 +318,9 @@ export async function flush(
313
318
  }
314
319
 
315
320
  if (writes.length > 0) {
316
- await driver.batch(writes);
321
+ for (const chunk of splitBatchWrites(writes)) {
322
+ await driver.batch(chunk);
323
+ }
317
324
  }
318
325
 
319
326
  // Apply pending deletions after the batch write. These are collected
@@ -336,6 +343,12 @@ export async function flush(
336
343
  }
337
344
 
338
345
  // Update flushed tracking after successful write
346
+ for (const entry of dirtyEntries) {
347
+ entry.dirty = false;
348
+ }
349
+ for (const metadata of dirtyMetadata) {
350
+ metadata.dirty = false;
351
+ }
339
352
  storage.flushedNameCount = storage.nameRegistry.length;
340
353
  storage.flushedState = storage.state;
341
354
  storage.flushedOutput = storage.output;
@@ -346,6 +359,40 @@ export async function flush(
346
359
  }
347
360
  }
348
361
 
362
+ function splitBatchWrites(writes: KVWrite[]): KVWrite[][] {
363
+ const chunks: KVWrite[][] = [];
364
+ let chunk: KVWrite[] = [];
365
+ let chunkBytes = 0;
366
+
367
+ for (const write of writes) {
368
+ const writeBytes = write.key.byteLength + write.value.byteLength;
369
+ if (writeBytes > MAX_KV_BATCH_PAYLOAD_BYTES) {
370
+ throw new Error(
371
+ `KV batch write is ${writeBytes} bytes, exceeding the ${MAX_KV_BATCH_PAYLOAD_BYTES} byte limit`,
372
+ );
373
+ }
374
+
375
+ if (
376
+ chunk.length >= MAX_KV_BATCH_ENTRIES ||
377
+ (chunk.length > 0 &&
378
+ chunkBytes + writeBytes > MAX_KV_BATCH_PAYLOAD_BYTES)
379
+ ) {
380
+ chunks.push(chunk);
381
+ chunk = [];
382
+ chunkBytes = 0;
383
+ }
384
+
385
+ chunk.push(write);
386
+ chunkBytes += writeBytes;
387
+ }
388
+
389
+ if (chunk.length > 0) {
390
+ chunks.push(chunk);
391
+ }
392
+
393
+ return chunks;
394
+ }
395
+
349
396
  /**
350
397
  * Delete entries with a given location prefix (used for loop forgetting).
351
398
  * Also cleans up associated metadata from both memory and driver.
package/src/types.ts CHANGED
@@ -422,11 +422,7 @@ export interface TryStepConfig<T> extends StepConfig<T> {
422
422
  catch?: readonly TryStepCatchKind[];
423
423
  }
424
424
 
425
- export type TryBlockCatchKind =
426
- | "step"
427
- | "join"
428
- | "race"
429
- | "rollback";
425
+ export type TryBlockCatchKind = "step" | "join" | "race" | "rollback";
430
426
 
431
427
  export interface TryBlockFailure {
432
428
  source: "step" | "join" | "race" | "block";
@@ -473,6 +469,12 @@ export interface LoopConfig<S, T> {
473
469
  historyPruneInterval?: number;
474
470
  /** Number of past iterations to retain when pruning. Defaults to historyPruneInterval. */
475
471
  historySize?: number;
472
+ /** @deprecated Use historyPruneInterval. */
473
+ commitInterval?: number;
474
+ /** @deprecated Use historyPruneInterval. */
475
+ historyEvery?: number;
476
+ /** @deprecated Use historySize. */
477
+ historyKeep?: number;
476
478
  }
477
479
 
478
480
  /**