@rivetkit/workflow-engine 0.0.0-sqlite-profiling-compat.4a9a623 → 0.0.0-sqlite-sync-3x-release.a00b07f

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.
@@ -163,6 +163,7 @@ var KEY_PREFIX = {
163
163
  // Workflow metadata: [3, field]
164
164
  ENTRY_METADATA: 4
165
165
  // Entry metadata: [4, entryId]
166
+ // 5 is reserved for RivetKit's workflow trace context.
166
167
  };
167
168
  var WORKFLOW_FIELD = {
168
169
  STATE: 1,
@@ -670,6 +671,16 @@ function writeRemovedEntry(bc, x) {
670
671
  bare.writeString(bc, x.originalType);
671
672
  write1(bc, x.originalName);
672
673
  }
674
+ function readVersionCheckEntry(bc) {
675
+ return {
676
+ resolved: bare.readU32(bc),
677
+ latest: bare.readU32(bc)
678
+ };
679
+ }
680
+ function writeVersionCheckEntry(bc, x) {
681
+ bare.writeU32(bc, x.resolved);
682
+ bare.writeU32(bc, x.latest);
683
+ }
673
684
  function readEntryKind(bc) {
674
685
  const offset = bc.offset;
675
686
  const tag = bare.readU8(bc);
@@ -690,6 +701,8 @@ function readEntryKind(bc) {
690
701
  return { tag: "RaceEntry", val: readRaceEntry(bc) };
691
702
  case 7:
692
703
  return { tag: "RemovedEntry", val: readRemovedEntry(bc) };
704
+ case 8:
705
+ return { tag: "VersionCheckEntry", val: readVersionCheckEntry(bc) };
693
706
  default: {
694
707
  bc.offset = offset;
695
708
  throw new bare.BareError(offset, "invalid tag");
@@ -738,6 +751,11 @@ function writeEntryKind(bc, x) {
738
751
  writeRemovedEntry(bc, x.val);
739
752
  break;
740
753
  }
754
+ case "VersionCheckEntry": {
755
+ bare.writeU8(bc, 8);
756
+ writeVersionCheckEntry(bc, x.val);
757
+ break;
758
+ }
741
759
  }
742
760
  }
743
761
  function readEntry(bc) {
@@ -1182,6 +1200,14 @@ function entryKindToBare(kind) {
1182
1200
  originalName: _nullishCoalesce(kind.data.originalName, () => ( null))
1183
1201
  }
1184
1202
  };
1203
+ case "version_check":
1204
+ return {
1205
+ tag: "VersionCheckEntry",
1206
+ val: {
1207
+ resolved: kind.data.resolved,
1208
+ latest: kind.data.latest
1209
+ }
1210
+ };
1185
1211
  }
1186
1212
  }
1187
1213
  function entryKindFromBare(kind) {
@@ -1263,6 +1289,14 @@ function entryKindFromBare(kind) {
1263
1289
  originalName: _nullishCoalesce(kind.val.originalName, () => ( void 0))
1264
1290
  }
1265
1291
  };
1292
+ case "VersionCheckEntry":
1293
+ return {
1294
+ type: "version_check",
1295
+ data: {
1296
+ resolved: kind.val.resolved,
1297
+ latest: kind.val.latest
1298
+ }
1299
+ };
1266
1300
  default:
1267
1301
  throw new Error(
1268
1302
  `Unknown entry kind: ${kind.tag}`
@@ -1404,6 +1438,7 @@ function deserializeName(bytes) {
1404
1438
  // src/storage.ts
1405
1439
  var MAX_KV_BATCH_ENTRIES = 128;
1406
1440
  var MAX_KV_BATCH_PAYLOAD_BYTES = 976 * 1024;
1441
+ var MAX_CONCURRENT_DELETES = 64;
1407
1442
  function createStorage() {
1408
1443
  return {
1409
1444
  nameRegistry: [],
@@ -1574,23 +1609,17 @@ async function flush(storage, driver, onHistoryUpdated, pendingDeletions) {
1574
1609
  });
1575
1610
  }
1576
1611
  if (writes.length > 0) {
1577
- for (const chunk of splitBatchWrites(writes)) {
1578
- await driver.batch(chunk);
1612
+ if (driver.atomicBatch) {
1613
+ await driver.batch(writes);
1614
+ } else {
1615
+ for (const chunk of splitBatchWrites(writes)) {
1616
+ await driver.batch(chunk);
1617
+ }
1579
1618
  }
1580
1619
  }
1581
1620
  if (pendingDeletions) {
1582
- const deleteOps = [];
1583
- for (const prefix of pendingDeletions.prefixes) {
1584
- deleteOps.push(driver.deletePrefix(prefix));
1585
- }
1586
- for (const range of pendingDeletions.ranges) {
1587
- deleteOps.push(driver.deleteRange(range.start, range.end));
1588
- }
1589
- for (const key of pendingDeletions.keys) {
1590
- deleteOps.push(driver.delete(key));
1591
- }
1592
- if (deleteOps.length > 0) {
1593
- await Promise.all(deleteOps);
1621
+ const didChange = await runDeletes(driver, pendingDeletions);
1622
+ if (didChange) {
1594
1623
  historyUpdated = true;
1595
1624
  }
1596
1625
  }
@@ -1632,10 +1661,38 @@ function splitBatchWrites(writes) {
1632
1661
  }
1633
1662
  return chunks;
1634
1663
  }
1664
+ function splitBatchDeletes(keys) {
1665
+ const chunks = [];
1666
+ for (let i = 0; i < keys.length; i += MAX_KV_BATCH_ENTRIES) {
1667
+ chunks.push(keys.slice(i, i + MAX_KV_BATCH_ENTRIES));
1668
+ }
1669
+ return chunks;
1670
+ }
1671
+ async function runDeletes(driver, deletions) {
1672
+ const ops = [
1673
+ ...deletions.prefixes.map(
1674
+ (prefix) => () => driver.deletePrefix(prefix)
1675
+ ),
1676
+ ...deletions.ranges.map(
1677
+ (range) => () => driver.deleteRange(range.start, range.end)
1678
+ ),
1679
+ ...splitBatchDeletes(deletions.keys).map(
1680
+ (chunk) => () => driver.batchDelete(chunk)
1681
+ )
1682
+ ];
1683
+ if (ops.length === 0) {
1684
+ return false;
1685
+ }
1686
+ for (let i = 0; i < ops.length; i += MAX_CONCURRENT_DELETES) {
1687
+ await Promise.all(
1688
+ ops.slice(i, i + MAX_CONCURRENT_DELETES).map((op) => op())
1689
+ );
1690
+ }
1691
+ return true;
1692
+ }
1635
1693
  async function deleteEntriesWithPrefix(storage, driver, prefixLocation, onHistoryUpdated) {
1636
1694
  const deletions = collectDeletionsForPrefix(storage, prefixLocation);
1637
- await driver.deletePrefix(deletions.prefixes[0]);
1638
- await Promise.all(deletions.keys.map((key) => driver.delete(key)));
1695
+ await runDeletes(driver, deletions);
1639
1696
  if (deletions.keys.length > 0 && onHistoryUpdated) {
1640
1697
  onHistoryUpdated();
1641
1698
  }
@@ -1817,7 +1874,7 @@ function selectControlFlowError(current, candidate) {
1817
1874
  return controlFlowErrorPriority(candidate) < controlFlowErrorPriority(current) ? candidate : current;
1818
1875
  }
1819
1876
  var WorkflowContextImpl = (_class = class _WorkflowContextImpl {
1820
- constructor(workflowId, storage, driver, messageDriver, location = emptyLocation(), abortController, mode = "forward", rollbackActions, rollbackCheckpointSet = false, historyNotifier, onError, logger, visitedKeys) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);
1877
+ constructor(workflowId, storage, driver, messageDriver, location = emptyLocation(), abortController, mode = "forward", rollbackActions, rollbackCheckpointSet = false, historyNotifier, onError, logger, visitedKeys, runSpan) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);
1821
1878
  this.workflowId = workflowId;
1822
1879
  this.storage = storage;
1823
1880
  this.driver = driver;
@@ -1831,6 +1888,7 @@ var WorkflowContextImpl = (_class = class _WorkflowContextImpl {
1831
1888
  this.onError = onError;
1832
1889
  this.logger = logger;
1833
1890
  this.visitedKeys = _nullishCoalesce(visitedKeys, () => ( /* @__PURE__ */ new Set()));
1891
+ this.runSpan = runSpan;
1834
1892
  }
1835
1893
  __init() {this.entryInProgress = false}
1836
1894
 
@@ -1839,6 +1897,7 @@ var WorkflowContextImpl = (_class = class _WorkflowContextImpl {
1839
1897
 
1840
1898
 
1841
1899
 
1900
+
1842
1901
  /** Track names used in current execution to detect duplicates */
1843
1902
  __init2() {this.usedNamesInExecution = /* @__PURE__ */ new Set()}
1844
1903
  __init3() {this.pendingCompletableMessageIds = /* @__PURE__ */ new Set()}
@@ -1888,7 +1947,8 @@ var WorkflowContextImpl = (_class = class _WorkflowContextImpl {
1888
1947
  this.historyNotifier,
1889
1948
  this.onError,
1890
1949
  this.logger,
1891
- this.visitedKeys
1950
+ this.visitedKeys,
1951
+ this.runSpan
1892
1952
  );
1893
1953
  }
1894
1954
  /**
@@ -2155,6 +2215,7 @@ var WorkflowContextImpl = (_class = class _WorkflowContextImpl {
2155
2215
  }
2156
2216
  }
2157
2217
  async executeStep(config2) {
2218
+ var _a;
2158
2219
  this.ensureRollbackCheckpoint(config2);
2159
2220
  if (this.mode === "rollback") {
2160
2221
  return await this.executeStepRollback(config2);
@@ -2246,9 +2307,13 @@ var WorkflowContextImpl = (_class = class _WorkflowContextImpl {
2246
2307
  metadata.lastAttemptAt = Date.now();
2247
2308
  metadata.dirty = true;
2248
2309
  const timeout = _nullishCoalesce(config2.timeout, () => ( DEFAULT_STEP_TIMEOUT));
2310
+ const stepSpan = (_a = this.runSpan) == null ? void 0 : _a.startStep(
2311
+ config2.name,
2312
+ metadata.attempts
2313
+ );
2249
2314
  try {
2250
2315
  const output = await this.executeWithTimeout(
2251
- config2.run(),
2316
+ stepSpan ? stepSpan.run(() => config2.run()) : config2.run(),
2252
2317
  timeout,
2253
2318
  config2.name
2254
2319
  );
@@ -2267,6 +2332,7 @@ var WorkflowContextImpl = (_class = class _WorkflowContextImpl {
2267
2332
  });
2268
2333
  await this.flushStorage();
2269
2334
  }
2335
+ stepSpan == null ? void 0 : stepSpan.finish("ok");
2270
2336
  this.log("debug", {
2271
2337
  msg: "step completed",
2272
2338
  step: config2.name,
@@ -2279,6 +2345,7 @@ var WorkflowContextImpl = (_class = class _WorkflowContextImpl {
2279
2345
  }
2280
2346
  entry.dirty = true;
2281
2347
  if (error instanceof StepTimeoutError && !config2.retryOnTimeout) {
2348
+ stepSpan == null ? void 0 : stepSpan.finish("failed", error);
2282
2349
  metadata.status = "exhausted";
2283
2350
  metadata.error = String(error);
2284
2351
  await this.notifyStepError(config2, metadata.attempts, error, {
@@ -2294,6 +2361,7 @@ var WorkflowContextImpl = (_class = class _WorkflowContextImpl {
2294
2361
  );
2295
2362
  }
2296
2363
  if (error instanceof CriticalError || error instanceof RollbackError) {
2364
+ stepSpan == null ? void 0 : stepSpan.finish("failed", error);
2297
2365
  metadata.status = "exhausted";
2298
2366
  metadata.error = String(error);
2299
2367
  await this.notifyStepError(config2, metadata.attempts, error, {
@@ -2309,6 +2377,7 @@ var WorkflowContextImpl = (_class = class _WorkflowContextImpl {
2309
2377
  );
2310
2378
  }
2311
2379
  const willRetry = metadata.attempts <= maxRetries;
2380
+ stepSpan == null ? void 0 : stepSpan.finish(willRetry ? "retry" : "failed", error);
2312
2381
  metadata.status = willRetry ? "failed" : "exhausted";
2313
2382
  metadata.error = String(error);
2314
2383
  if (willRetry) {
@@ -3488,6 +3557,65 @@ var WorkflowContextImpl = (_class = class _WorkflowContextImpl {
3488
3557
  setEntry(this.storage, location, entry);
3489
3558
  await this.flushStorage();
3490
3559
  }
3560
+ // === Version ===
3561
+ async getVersion(name, latest) {
3562
+ this.assertNotInProgress();
3563
+ this.checkEvicted();
3564
+ this.entryInProgress = true;
3565
+ try {
3566
+ return await this.executeGetVersion(name, latest);
3567
+ } finally {
3568
+ this.entryInProgress = false;
3569
+ }
3570
+ }
3571
+ async executeGetVersion(name, latest) {
3572
+ if (!Number.isInteger(latest) || latest < 1) {
3573
+ throw new Error(
3574
+ `getVersion("${name}", ${latest}): latest must be an integer >= 1`
3575
+ );
3576
+ }
3577
+ this.checkDuplicateName(name);
3578
+ const location = appendName(this.storage, this.currentLocation, name);
3579
+ const key = locationToKey(this.storage, location);
3580
+ const existing = this.storage.history.entries.get(key);
3581
+ this.markVisited(key);
3582
+ this.stopRollbackIfMissing(existing);
3583
+ if (existing) {
3584
+ if (existing.kind.type !== "version_check") {
3585
+ throw new HistoryDivergedError(
3586
+ `Expected version_check at ${key}, found ${existing.kind.type}`
3587
+ );
3588
+ }
3589
+ return existing.kind.data.resolved;
3590
+ }
3591
+ const resolved = this.hasUnvisitedUnderCurrentScope(key) ? 1 : latest;
3592
+ const entry = createEntry(location, {
3593
+ type: "version_check",
3594
+ data: { resolved, latest }
3595
+ });
3596
+ setEntry(this.storage, location, entry);
3597
+ await this.flushStorage();
3598
+ return resolved;
3599
+ }
3600
+ /**
3601
+ * Returns true if any history entry under the current location scope
3602
+ * (other than `excludeKey`) has not yet been visited this run. Used by
3603
+ * getVersion to detect an old in-flight instance whose scope was already
3604
+ * executed by code that predates a version gate.
3605
+ */
3606
+ hasUnvisitedUnderCurrentScope(excludeKey) {
3607
+ const prefix = locationToKey(this.storage, this.currentLocation);
3608
+ for (const key of this.storage.history.entries.keys()) {
3609
+ if (key === excludeKey) {
3610
+ continue;
3611
+ }
3612
+ const isUnderPrefix = prefix === "" ? true : key.startsWith(`${prefix}/`) || key === prefix;
3613
+ if (isUnderPrefix && !this.visitedKeys.has(key)) {
3614
+ return true;
3615
+ }
3616
+ }
3617
+ return false;
3618
+ }
3491
3619
  }, _class);
3492
3620
 
3493
3621
  // src/utils.ts
@@ -3569,7 +3697,7 @@ async function awaitWithEviction(promise, abortSignal) {
3569
3697
  cleanup();
3570
3698
  }
3571
3699
  }
3572
- async function executeRollback(workflowId, workflowFn, input, driver, messageDriver, abortController, storage, historyNotifier, onError, logger) {
3700
+ async function executeRollback(workflowId, workflowFn, input, driver, messageDriver, abortController, storage, historyNotifier, onError, logger, runSpan) {
3573
3701
  const rollbackActions = [];
3574
3702
  const ctx = new WorkflowContextImpl(
3575
3703
  workflowId,
@@ -3583,7 +3711,9 @@ async function executeRollback(workflowId, workflowFn, input, driver, messageDri
3583
3711
  false,
3584
3712
  historyNotifier,
3585
3713
  onError,
3586
- logger
3714
+ logger,
3715
+ void 0,
3716
+ runSpan
3587
3717
  );
3588
3718
  try {
3589
3719
  await workflowFn(ctx, input);
@@ -3719,16 +3849,20 @@ async function waitForSleep(runtime, deadline, abortSignal) {
3719
3849
  async function executeLiveWorkflow(workflowId, workflowFn, input, driver, messageDriver, abortController, runtime, onHistoryUpdated, onError, logger) {
3720
3850
  let lastResult;
3721
3851
  while (true) {
3722
- const result = await executeWorkflow(
3723
- workflowId,
3724
- workflowFn,
3725
- input,
3852
+ const result = await traceRun(
3726
3853
  driver,
3727
- messageDriver,
3728
- abortController,
3729
- onHistoryUpdated,
3730
- onError,
3731
- logger
3854
+ (runSpan) => executeWorkflow(
3855
+ workflowId,
3856
+ workflowFn,
3857
+ input,
3858
+ driver,
3859
+ messageDriver,
3860
+ abortController,
3861
+ onHistoryUpdated,
3862
+ onError,
3863
+ logger,
3864
+ runSpan
3865
+ )
3732
3866
  );
3733
3867
  lastResult = result;
3734
3868
  if (result.state !== "sleeping") {
@@ -3827,16 +3961,20 @@ function runWorkflow(workflowId, workflowFn, input, driver, options = {}) {
3827
3961
  options.onHistoryUpdated,
3828
3962
  options.onError,
3829
3963
  logger
3830
- ) : executeWorkflow(
3831
- workflowId,
3832
- workflowFn,
3833
- input,
3964
+ ) : traceRun(
3834
3965
  driver,
3835
- messageDriver,
3836
- abortController,
3837
- options.onHistoryUpdated,
3838
- options.onError,
3839
- logger
3966
+ (runSpan) => executeWorkflow(
3967
+ workflowId,
3968
+ workflowFn,
3969
+ input,
3970
+ driver,
3971
+ messageDriver,
3972
+ abortController,
3973
+ options.onHistoryUpdated,
3974
+ options.onError,
3975
+ logger,
3976
+ runSpan
3977
+ )
3840
3978
  );
3841
3979
  return {
3842
3980
  workflowId,
@@ -4012,7 +4150,42 @@ function findReplayBoundaryEntry(entries, target) {
4012
4150
  }
4013
4151
  return boundary;
4014
4152
  }
4015
- async function executeWorkflow(workflowId, workflowFn, input, driver, messageDriver, abortController, onHistoryUpdated, onError, logger) {
4153
+ function runOutcomeFromState(state) {
4154
+ switch (state) {
4155
+ case "completed":
4156
+ return "completed";
4157
+ case "sleeping":
4158
+ return "sleeping";
4159
+ case "failed":
4160
+ return "failed";
4161
+ case "cancelled":
4162
+ return "cancelled";
4163
+ case "pending":
4164
+ case "running":
4165
+ case "rolling_back":
4166
+ return "evicted";
4167
+ }
4168
+ }
4169
+ async function traceRun(driver, run) {
4170
+ if (!driver.telemetry) {
4171
+ return await run();
4172
+ }
4173
+ const span = await driver.telemetry.startSpan();
4174
+ let outcome = "failed";
4175
+ try {
4176
+ const result = await span.run(() => run(span));
4177
+ outcome = runOutcomeFromState(result.state);
4178
+ return result;
4179
+ } catch (error) {
4180
+ if (error instanceof EvictedError) {
4181
+ outcome = "cancelled";
4182
+ }
4183
+ throw error;
4184
+ } finally {
4185
+ await span.finish(outcome);
4186
+ }
4187
+ }
4188
+ async function executeWorkflow(workflowId, workflowFn, input, driver, messageDriver, abortController, onHistoryUpdated, onError, logger, runSpan) {
4016
4189
  var _a;
4017
4190
  const storage = await loadStorage(driver);
4018
4191
  const historyNotifier = onHistoryUpdated ? () => onHistoryUpdated(createHistorySnapshot(storage)) : void 0;
@@ -4055,7 +4228,8 @@ async function executeWorkflow(workflowId, workflowFn, input, driver, messageDri
4055
4228
  storage,
4056
4229
  historyNotifier,
4057
4230
  onError,
4058
- logger
4231
+ logger,
4232
+ runSpan
4059
4233
  );
4060
4234
  } catch (error) {
4061
4235
  if (error instanceof EvictedError) {
@@ -4083,7 +4257,9 @@ async function executeWorkflow(workflowId, workflowFn, input, driver, messageDri
4083
4257
  false,
4084
4258
  historyNotifier,
4085
4259
  onError,
4086
- logger
4260
+ logger,
4261
+ void 0,
4262
+ runSpan
4087
4263
  );
4088
4264
  storage.state = "running";
4089
4265
  try {
@@ -4150,7 +4326,8 @@ async function executeWorkflow(workflowId, workflowFn, input, driver, messageDri
4150
4326
  storage,
4151
4327
  historyNotifier,
4152
4328
  onError,
4153
- logger
4329
+ logger,
4330
+ runSpan
4154
4331
  );
4155
4332
  } catch (rollbackError) {
4156
4333
  if (rollbackError instanceof EvictedError) {
@@ -4225,4 +4402,4 @@ async function executeWorkflow(workflowId, workflowFn, input, driver, messageDri
4225
4402
 
4226
4403
 
4227
4404
  exports.extractErrorInfo = extractErrorInfo; exports.CriticalError = CriticalError; exports.RollbackError = RollbackError; exports.RollbackCheckpointError = RollbackCheckpointError; exports.SleepError = SleepError; exports.MessageWaitError = MessageWaitError; exports.EvictedError = EvictedError; exports.HistoryDivergedError = HistoryDivergedError; exports.StepExhaustedError = StepExhaustedError; exports.StepFailedError = StepFailedError; exports.JoinError = JoinError; exports.RaceError = RaceError; exports.CancelledError = CancelledError; exports.EntryInProgressError = EntryInProgressError; exports.keyStartsWith = keyStartsWith; exports.compareKeys = compareKeys; exports.keyToHex = keyToHex; exports.isLoopIterationMarker = isLoopIterationMarker; exports.registerName = registerName; exports.resolveName = resolveName; exports.locationToKey = locationToKey; exports.appendName = appendName; exports.appendLoopIteration = appendLoopIteration; exports.emptyLocation = emptyLocation; exports.parentLocation = parentLocation; exports.isLocationPrefix = isLocationPrefix; exports.locationsEqual = locationsEqual; exports.createStorage = createStorage; exports.createHistorySnapshot = createHistorySnapshot; exports.generateId = generateId; exports.createEntry = createEntry; exports.getOrCreateMetadata = getOrCreateMetadata; exports.loadStorage = loadStorage; exports.loadMetadata = loadMetadata; exports.flush = flush; exports.deleteEntriesWithPrefix = deleteEntriesWithPrefix; exports.getEntry = getEntry; exports.setEntry = setEntry; exports.DEFAULT_MAX_RETRIES = DEFAULT_MAX_RETRIES; exports.DEFAULT_RETRY_BACKOFF_BASE = DEFAULT_RETRY_BACKOFF_BASE; exports.DEFAULT_RETRY_BACKOFF_MAX = DEFAULT_RETRY_BACKOFF_MAX; exports.DEFAULT_LOOP_HISTORY_PRUNE_INTERVAL = DEFAULT_LOOP_HISTORY_PRUNE_INTERVAL; exports.DEFAULT_STEP_TIMEOUT = DEFAULT_STEP_TIMEOUT; exports.WorkflowContextImpl = WorkflowContextImpl; exports.sleep = sleep; exports.Loop = Loop; exports.runWorkflow = runWorkflow; exports.replayWorkflowFromStep = replayWorkflowFromStep;
4228
- //# sourceMappingURL=chunk-GQWOLYBA.cjs.map
4405
+ //# sourceMappingURL=chunk-XRITRTKT.cjs.map