@rivetkit/workflow-engine 2.3.2 → 2.3.3-rc.2

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 _chunkGQWOLYBAcjs = require('./chunk-GQWOLYBA.cjs');
46
+ var _chunkOCUQRGRScjs = require('./chunk-OCUQRGRS.cjs');
47
47
 
48
48
 
49
49
 
@@ -89,5 +89,5 @@ var _chunkGQWOLYBAcjs = require('./chunk-GQWOLYBA.cjs');
89
89
 
90
90
 
91
91
 
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;
92
+ exports.CancelledError = _chunkOCUQRGRScjs.CancelledError; exports.CriticalError = _chunkOCUQRGRScjs.CriticalError; exports.DEFAULT_LOOP_HISTORY_PRUNE_INTERVAL = _chunkOCUQRGRScjs.DEFAULT_LOOP_HISTORY_PRUNE_INTERVAL; exports.DEFAULT_MAX_RETRIES = _chunkOCUQRGRScjs.DEFAULT_MAX_RETRIES; exports.DEFAULT_RETRY_BACKOFF_BASE = _chunkOCUQRGRScjs.DEFAULT_RETRY_BACKOFF_BASE; exports.DEFAULT_RETRY_BACKOFF_MAX = _chunkOCUQRGRScjs.DEFAULT_RETRY_BACKOFF_MAX; exports.DEFAULT_STEP_TIMEOUT = _chunkOCUQRGRScjs.DEFAULT_STEP_TIMEOUT; exports.EntryInProgressError = _chunkOCUQRGRScjs.EntryInProgressError; exports.EvictedError = _chunkOCUQRGRScjs.EvictedError; exports.HistoryDivergedError = _chunkOCUQRGRScjs.HistoryDivergedError; exports.JoinError = _chunkOCUQRGRScjs.JoinError; exports.Loop = _chunkOCUQRGRScjs.Loop; exports.MessageWaitError = _chunkOCUQRGRScjs.MessageWaitError; exports.RaceError = _chunkOCUQRGRScjs.RaceError; exports.RollbackCheckpointError = _chunkOCUQRGRScjs.RollbackCheckpointError; exports.RollbackError = _chunkOCUQRGRScjs.RollbackError; exports.SleepError = _chunkOCUQRGRScjs.SleepError; exports.StepExhaustedError = _chunkOCUQRGRScjs.StepExhaustedError; exports.StepFailedError = _chunkOCUQRGRScjs.StepFailedError; exports.WorkflowContextImpl = _chunkOCUQRGRScjs.WorkflowContextImpl; exports.appendLoopIteration = _chunkOCUQRGRScjs.appendLoopIteration; exports.appendName = _chunkOCUQRGRScjs.appendName; exports.createEntry = _chunkOCUQRGRScjs.createEntry; exports.createHistorySnapshot = _chunkOCUQRGRScjs.createHistorySnapshot; exports.createStorage = _chunkOCUQRGRScjs.createStorage; exports.deleteEntriesWithPrefix = _chunkOCUQRGRScjs.deleteEntriesWithPrefix; exports.emptyLocation = _chunkOCUQRGRScjs.emptyLocation; exports.extractErrorInfo = _chunkOCUQRGRScjs.extractErrorInfo; exports.flush = _chunkOCUQRGRScjs.flush; exports.generateId = _chunkOCUQRGRScjs.generateId; exports.getEntry = _chunkOCUQRGRScjs.getEntry; exports.getOrCreateMetadata = _chunkOCUQRGRScjs.getOrCreateMetadata; exports.isLocationPrefix = _chunkOCUQRGRScjs.isLocationPrefix; exports.isLoopIterationMarker = _chunkOCUQRGRScjs.isLoopIterationMarker; exports.loadMetadata = _chunkOCUQRGRScjs.loadMetadata; exports.loadStorage = _chunkOCUQRGRScjs.loadStorage; exports.locationToKey = _chunkOCUQRGRScjs.locationToKey; exports.locationsEqual = _chunkOCUQRGRScjs.locationsEqual; exports.parentLocation = _chunkOCUQRGRScjs.parentLocation; exports.registerName = _chunkOCUQRGRScjs.registerName; exports.replayWorkflowFromStep = _chunkOCUQRGRScjs.replayWorkflowFromStep; exports.resolveName = _chunkOCUQRGRScjs.resolveName; exports.runWorkflow = _chunkOCUQRGRScjs.runWorkflow; exports.setEntry = _chunkOCUQRGRScjs.setEntry;
93
93
  //# sourceMappingURL=index.cjs.map
@@ -101,10 +101,20 @@ interface RemovedEntry {
101
101
  originalType: EntryKindType;
102
102
  originalName?: string;
103
103
  }
104
+ /**
105
+ * Version check entry data - records which version of a code path this
106
+ * workflow instance is pinned to at a given location.
107
+ */
108
+ interface VersionCheckEntry {
109
+ /** The version this instance resolved to at this location. */
110
+ resolved: number;
111
+ /** The `latest` value seen when this entry was first resolved (diagnostics). */
112
+ latest: number;
113
+ }
104
114
  /**
105
115
  * All possible entry kind types.
106
116
  */
107
- type EntryKindType = "step" | "loop" | "sleep" | "message" | "rollback_checkpoint" | "join" | "race" | "removed";
117
+ type EntryKindType = "step" | "loop" | "sleep" | "message" | "rollback_checkpoint" | "join" | "race" | "removed" | "version_check";
108
118
  /**
109
119
  * Type-specific entry data.
110
120
  */
@@ -132,6 +142,9 @@ type EntryKind = {
132
142
  } | {
133
143
  type: "removed";
134
144
  data: RemovedEntry;
145
+ } | {
146
+ type: "version_check";
147
+ data: VersionCheckEntry;
135
148
  };
136
149
  /**
137
150
  * An entry in the workflow history.
@@ -458,6 +471,7 @@ interface WorkflowContextInterface {
458
471
  value: T;
459
472
  }>;
460
473
  removed(name: string, originalType: EntryKindType): Promise<void>;
474
+ getVersion(name: string, latest: number): Promise<number>;
461
475
  isEvicted(): boolean;
462
476
  }
463
477
  /**
@@ -781,6 +795,15 @@ declare class WorkflowContextImpl implements WorkflowContextInterface {
781
795
  private executeRace;
782
796
  removed(name: string, originalType: EntryKindType): Promise<void>;
783
797
  private executeRemoved;
798
+ getVersion(name: string, latest: number): Promise<number>;
799
+ private executeGetVersion;
800
+ /**
801
+ * Returns true if any history entry under the current location scope
802
+ * (other than `excludeKey`) has not yet been visited this run. Used by
803
+ * getVersion to detect an old in-flight instance whose scope was already
804
+ * executed by code that predates a version gate.
805
+ */
806
+ private hasUnvisitedUnderCurrentScope;
784
807
  }
785
808
 
786
809
  /**
@@ -101,10 +101,20 @@ interface RemovedEntry {
101
101
  originalType: EntryKindType;
102
102
  originalName?: string;
103
103
  }
104
+ /**
105
+ * Version check entry data - records which version of a code path this
106
+ * workflow instance is pinned to at a given location.
107
+ */
108
+ interface VersionCheckEntry {
109
+ /** The version this instance resolved to at this location. */
110
+ resolved: number;
111
+ /** The `latest` value seen when this entry was first resolved (diagnostics). */
112
+ latest: number;
113
+ }
104
114
  /**
105
115
  * All possible entry kind types.
106
116
  */
107
- type EntryKindType = "step" | "loop" | "sleep" | "message" | "rollback_checkpoint" | "join" | "race" | "removed";
117
+ type EntryKindType = "step" | "loop" | "sleep" | "message" | "rollback_checkpoint" | "join" | "race" | "removed" | "version_check";
108
118
  /**
109
119
  * Type-specific entry data.
110
120
  */
@@ -132,6 +142,9 @@ type EntryKind = {
132
142
  } | {
133
143
  type: "removed";
134
144
  data: RemovedEntry;
145
+ } | {
146
+ type: "version_check";
147
+ data: VersionCheckEntry;
135
148
  };
136
149
  /**
137
150
  * An entry in the workflow history.
@@ -458,6 +471,7 @@ interface WorkflowContextInterface {
458
471
  value: T;
459
472
  }>;
460
473
  removed(name: string, originalType: EntryKindType): Promise<void>;
474
+ getVersion(name: string, latest: number): Promise<number>;
461
475
  isEvicted(): boolean;
462
476
  }
463
477
  /**
@@ -781,6 +795,15 @@ declare class WorkflowContextImpl implements WorkflowContextInterface {
781
795
  private executeRace;
782
796
  removed(name: string, originalType: EntryKindType): Promise<void>;
783
797
  private executeRemoved;
798
+ getVersion(name: string, latest: number): Promise<number>;
799
+ private executeGetVersion;
800
+ /**
801
+ * Returns true if any history entry under the current location scope
802
+ * (other than `excludeKey`) has not yet been visited this run. Used by
803
+ * getVersion to detect an old in-flight instance whose scope was already
804
+ * executed by code that predates a version gate.
805
+ */
806
+ private hasUnvisitedUnderCurrentScope;
784
807
  }
785
808
 
786
809
  /**
@@ -43,7 +43,7 @@ import {
43
43
  resolveName,
44
44
  runWorkflow,
45
45
  setEntry
46
- } from "./chunk-KA2T56AJ.js";
46
+ } from "./chunk-Z3WC5MXC.js";
47
47
  export {
48
48
  CancelledError,
49
49
  CriticalError,
@@ -47,7 +47,7 @@
47
47
 
48
48
 
49
49
 
50
- var _chunkGQWOLYBAcjs = require('./chunk-GQWOLYBA.cjs');
50
+ var _chunkOCUQRGRScjs = require('./chunk-OCUQRGRS.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, _chunkGQWOLYBAcjs.EvictedError)();
100
+ throw new (0, _chunkOCUQRGRScjs.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, _chunkGQWOLYBAcjs.EvictedError)());
121
+ waiter.reject(new (0, _chunkOCUQRGRScjs.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 _chunkGQWOLYBAcjs.sleep.call(void 0, this.latency);
162
- const entry = this.kv.get(_chunkGQWOLYBAcjs.keyToHex.call(void 0, key));
161
+ await _chunkOCUQRGRScjs.sleep.call(void 0, this.latency);
162
+ const entry = this.kv.get(_chunkOCUQRGRScjs.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 _chunkGQWOLYBAcjs.sleep.call(void 0, this.latency);
167
- this.kv.set(_chunkGQWOLYBAcjs.keyToHex.call(void 0, key), { key, value });
166
+ await _chunkOCUQRGRScjs.sleep.call(void 0, this.latency);
167
+ this.kv.set(_chunkOCUQRGRScjs.keyToHex.call(void 0, key), { key, value });
168
168
  }
169
169
  async delete(key) {
170
- await _chunkGQWOLYBAcjs.sleep.call(void 0, this.latency);
171
- this.kv.delete(_chunkGQWOLYBAcjs.keyToHex.call(void 0, key));
170
+ await _chunkOCUQRGRScjs.sleep.call(void 0, this.latency);
171
+ this.kv.delete(_chunkOCUQRGRScjs.keyToHex.call(void 0, key));
172
172
  }
173
173
  async deletePrefix(prefix) {
174
- await _chunkGQWOLYBAcjs.sleep.call(void 0, this.latency);
174
+ await _chunkOCUQRGRScjs.sleep.call(void 0, this.latency);
175
175
  for (const [hexKey, entry] of this.kv) {
176
- if (_chunkGQWOLYBAcjs.keyStartsWith.call(void 0, entry.key, prefix)) {
176
+ if (_chunkOCUQRGRScjs.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 _chunkGQWOLYBAcjs.sleep.call(void 0, this.latency);
182
+ await _chunkOCUQRGRScjs.sleep.call(void 0, this.latency);
183
183
  for (const [hexKey, entry] of this.kv) {
184
- if (_chunkGQWOLYBAcjs.compareKeys.call(void 0, entry.key, start) >= 0 && _chunkGQWOLYBAcjs.compareKeys.call(void 0, entry.key, end) < 0) {
184
+ if (_chunkOCUQRGRScjs.compareKeys.call(void 0, entry.key, start) >= 0 && _chunkOCUQRGRScjs.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 _chunkGQWOLYBAcjs.sleep.call(void 0, this.latency);
190
+ await _chunkOCUQRGRScjs.sleep.call(void 0, this.latency);
191
191
  const results = [];
192
192
  for (const entry of this.kv.values()) {
193
- if (_chunkGQWOLYBAcjs.keyStartsWith.call(void 0, entry.key, prefix)) {
193
+ if (_chunkOCUQRGRScjs.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) => _chunkGQWOLYBAcjs.compareKeys.call(void 0, a.key, b.key));
197
+ return results.sort((a, b) => _chunkOCUQRGRScjs.compareKeys.call(void 0, a.key, b.key));
198
198
  }
199
199
  async batch(writes) {
200
- await _chunkGQWOLYBAcjs.sleep.call(void 0, this.latency);
200
+ await _chunkOCUQRGRScjs.sleep.call(void 0, this.latency);
201
201
  for (const { key, value } of writes) {
202
- this.kv.set(_chunkGQWOLYBAcjs.keyToHex.call(void 0, key), { key, value });
202
+ this.kv.set(_chunkOCUQRGRScjs.keyToHex.call(void 0, key), { key, value });
203
203
  }
204
204
  }
205
205
  async setAlarm(workflowId, wakeAt) {
206
- await _chunkGQWOLYBAcjs.sleep.call(void 0, this.latency);
206
+ await _chunkOCUQRGRScjs.sleep.call(void 0, this.latency);
207
207
  this.alarms.set(workflowId, wakeAt);
208
208
  }
209
209
  async clearAlarm(workflowId) {
210
- await _chunkGQWOLYBAcjs.sleep.call(void 0, this.latency);
210
+ await _chunkOCUQRGRScjs.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, _chunkGQWOLYBAcjs.EvictedError)();
221
+ throw new (0, _chunkOCUQRGRScjs.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 _chunkGQWOLYBAcjs.sleep.call(void 0, Math.max(1, this.latency));
231
+ await _chunkOCUQRGRScjs.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 = _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;
327
+ exports.CancelledError = _chunkOCUQRGRScjs.CancelledError; exports.CriticalError = _chunkOCUQRGRScjs.CriticalError; exports.DEFAULT_LOOP_HISTORY_PRUNE_INTERVAL = _chunkOCUQRGRScjs.DEFAULT_LOOP_HISTORY_PRUNE_INTERVAL; exports.DEFAULT_MAX_RETRIES = _chunkOCUQRGRScjs.DEFAULT_MAX_RETRIES; exports.DEFAULT_RETRY_BACKOFF_BASE = _chunkOCUQRGRScjs.DEFAULT_RETRY_BACKOFF_BASE; exports.DEFAULT_RETRY_BACKOFF_MAX = _chunkOCUQRGRScjs.DEFAULT_RETRY_BACKOFF_MAX; exports.DEFAULT_STEP_TIMEOUT = _chunkOCUQRGRScjs.DEFAULT_STEP_TIMEOUT; exports.EntryInProgressError = _chunkOCUQRGRScjs.EntryInProgressError; exports.EvictedError = _chunkOCUQRGRScjs.EvictedError; exports.HistoryDivergedError = _chunkOCUQRGRScjs.HistoryDivergedError; exports.InMemoryDriver = InMemoryDriver; exports.JoinError = _chunkOCUQRGRScjs.JoinError; exports.Loop = _chunkOCUQRGRScjs.Loop; exports.MessageWaitError = _chunkOCUQRGRScjs.MessageWaitError; exports.RaceError = _chunkOCUQRGRScjs.RaceError; exports.RollbackCheckpointError = _chunkOCUQRGRScjs.RollbackCheckpointError; exports.RollbackError = _chunkOCUQRGRScjs.RollbackError; exports.SleepError = _chunkOCUQRGRScjs.SleepError; exports.StepExhaustedError = _chunkOCUQRGRScjs.StepExhaustedError; exports.StepFailedError = _chunkOCUQRGRScjs.StepFailedError; exports.WorkflowContextImpl = _chunkOCUQRGRScjs.WorkflowContextImpl; exports.appendLoopIteration = _chunkOCUQRGRScjs.appendLoopIteration; exports.appendName = _chunkOCUQRGRScjs.appendName; exports.createEntry = _chunkOCUQRGRScjs.createEntry; exports.createHistorySnapshot = _chunkOCUQRGRScjs.createHistorySnapshot; exports.createStorage = _chunkOCUQRGRScjs.createStorage; exports.deleteEntriesWithPrefix = _chunkOCUQRGRScjs.deleteEntriesWithPrefix; exports.emptyLocation = _chunkOCUQRGRScjs.emptyLocation; exports.extractErrorInfo = _chunkOCUQRGRScjs.extractErrorInfo; exports.flush = _chunkOCUQRGRScjs.flush; exports.generateId = _chunkOCUQRGRScjs.generateId; exports.getEntry = _chunkOCUQRGRScjs.getEntry; exports.getOrCreateMetadata = _chunkOCUQRGRScjs.getOrCreateMetadata; exports.isLocationPrefix = _chunkOCUQRGRScjs.isLocationPrefix; exports.isLoopIterationMarker = _chunkOCUQRGRScjs.isLoopIterationMarker; exports.loadMetadata = _chunkOCUQRGRScjs.loadMetadata; exports.loadStorage = _chunkOCUQRGRScjs.loadStorage; exports.locationToKey = _chunkOCUQRGRScjs.locationToKey; exports.locationsEqual = _chunkOCUQRGRScjs.locationsEqual; exports.parentLocation = _chunkOCUQRGRScjs.parentLocation; exports.registerName = _chunkOCUQRGRScjs.registerName; exports.replayWorkflowFromStep = _chunkOCUQRGRScjs.replayWorkflowFromStep; exports.resolveName = _chunkOCUQRGRScjs.resolveName; exports.runWorkflow = _chunkOCUQRGRScjs.runWorkflow; exports.setEntry = _chunkOCUQRGRScjs.setEntry;
328
328
  //# sourceMappingURL=testing.cjs.map
@@ -47,7 +47,7 @@ import {
47
47
  runWorkflow,
48
48
  setEntry,
49
49
  sleep
50
- } from "./chunk-KA2T56AJ.js";
50
+ } from "./chunk-Z3WC5MXC.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.2",
3
+ "version": "2.3.3-rc.2",
4
4
  "description": "Durable workflow engine with reentrant execution",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [
package/schemas/serde.ts CHANGED
@@ -307,6 +307,14 @@ function entryKindToBare(kind: InternalEntryKind): v1.EntryKind {
307
307
  originalName: kind.data.originalName ?? null,
308
308
  },
309
309
  };
310
+ case "version_check":
311
+ return {
312
+ tag: "VersionCheckEntry",
313
+ val: {
314
+ resolved: kind.data.resolved,
315
+ latest: kind.data.latest,
316
+ },
317
+ };
310
318
  }
311
319
  }
312
320
 
@@ -396,6 +404,14 @@ function entryKindFromBare(kind: v1.EntryKind): InternalEntryKind {
396
404
  originalName: kind.val.originalName ?? undefined,
397
405
  },
398
406
  };
407
+ case "VersionCheckEntry":
408
+ return {
409
+ type: "version_check",
410
+ data: {
411
+ resolved: kind.val.resolved,
412
+ latest: kind.val.latest,
413
+ },
414
+ };
399
415
  default:
400
416
  throw new Error(
401
417
  `Unknown entry kind: ${(kind as { tag: string }).tag}`,
package/schemas/v1.bare CHANGED
@@ -122,6 +122,14 @@ type RemovedEntry struct {
122
122
  originalName: optional<str>
123
123
  }
124
124
 
125
+ # MARK: Version Check Entry
126
+ type VersionCheckEntry struct {
127
+ # The version this instance resolved to at this location
128
+ resolved: u32
129
+ # The `latest` value seen when first resolved (diagnostics)
130
+ latest: u32
131
+ }
132
+
125
133
  # MARK: Entry Kind
126
134
  # Type-specific entry data
127
135
  type EntryKind union {
@@ -132,7 +140,8 @@ type EntryKind union {
132
140
  RollbackCheckpointEntry |
133
141
  JoinEntry |
134
142
  RaceEntry |
135
- RemovedEntry
143
+ RemovedEntry |
144
+ VersionCheckEntry
136
145
  }
137
146
 
138
147
  # MARK: Entry
@@ -19,6 +19,7 @@ export type {
19
19
  RemovedEntry,
20
20
  SleepEntry,
21
21
  StepEntry,
22
+ VersionCheckEntry,
22
23
  WorkflowMetadata,
23
24
  } from "../dist/schemas/v1.js";
24
25
 
package/src/context.ts CHANGED
@@ -2581,4 +2581,97 @@ export class WorkflowContextImpl implements WorkflowContextInterface {
2581
2581
  setEntry(this.storage, location, entry);
2582
2582
  await this.flushStorage();
2583
2583
  }
2584
+
2585
+ // === Version ===
2586
+
2587
+ async getVersion(name: string, latest: number): Promise<number> {
2588
+ this.assertNotInProgress();
2589
+ this.checkEvicted();
2590
+
2591
+ this.entryInProgress = true;
2592
+ try {
2593
+ return await this.executeGetVersion(name, latest);
2594
+ } finally {
2595
+ this.entryInProgress = false;
2596
+ }
2597
+ }
2598
+
2599
+ private async executeGetVersion(
2600
+ name: string,
2601
+ latest: number,
2602
+ ): Promise<number> {
2603
+ if (!Number.isInteger(latest) || latest < 1) {
2604
+ throw new Error(
2605
+ `getVersion("${name}", ${latest}): latest must be an integer >= 1`,
2606
+ );
2607
+ }
2608
+
2609
+ // Check for duplicate name in current execution
2610
+ this.checkDuplicateName(name);
2611
+
2612
+ const location = appendName(this.storage, this.currentLocation, name);
2613
+ const key = locationToKey(this.storage, location);
2614
+ const existing = this.storage.history.entries.get(key);
2615
+
2616
+ // Mark this entry as visited for validateComplete
2617
+ this.markVisited(key);
2618
+
2619
+ this.stopRollbackIfMissing(existing);
2620
+
2621
+ if (existing) {
2622
+ if (existing.kind.type !== "version_check") {
2623
+ throw new HistoryDivergedError(
2624
+ `Expected version_check at ${key}, found ${existing.kind.type}`,
2625
+ );
2626
+ }
2627
+ // Pure replay: this instance is already pinned at this location.
2628
+ return existing.kind.data.resolved;
2629
+ }
2630
+
2631
+ // No recorded version at this location. Decide whether this instance
2632
+ // already executed past this point under older code (old in-flight) or
2633
+ // is reaching it fresh at the live frontier.
2634
+ //
2635
+ // The discriminator is "is there any unvisited history entry under the
2636
+ // current scope?". Entries created earlier in this same run are already
2637
+ // marked visited, so the only unvisited entries under the scope are
2638
+ // leftovers from a prior run, which proves this scope already executed
2639
+ // under code that predates this gate. Such instances resolve to the
2640
+ // implicit floor version 1 (old branch); fresh instances resolve to
2641
+ // `latest`.
2642
+ const resolved = this.hasUnvisitedUnderCurrentScope(key) ? 1 : latest;
2643
+
2644
+ const entry = createEntry(location, {
2645
+ type: "version_check",
2646
+ data: { resolved, latest },
2647
+ });
2648
+ setEntry(this.storage, location, entry);
2649
+ await this.flushStorage();
2650
+
2651
+ return resolved;
2652
+ }
2653
+
2654
+ /**
2655
+ * Returns true if any history entry under the current location scope
2656
+ * (other than `excludeKey`) has not yet been visited this run. Used by
2657
+ * getVersion to detect an old in-flight instance whose scope was already
2658
+ * executed by code that predates a version gate.
2659
+ */
2660
+ private hasUnvisitedUnderCurrentScope(excludeKey: string): boolean {
2661
+ const prefix = locationToKey(this.storage, this.currentLocation);
2662
+
2663
+ for (const key of this.storage.history.entries.keys()) {
2664
+ if (key === excludeKey) {
2665
+ continue;
2666
+ }
2667
+ const isUnderPrefix =
2668
+ prefix === ""
2669
+ ? true
2670
+ : key.startsWith(`${prefix}/`) || key === prefix;
2671
+ if (isUnderPrefix && !this.visitedKeys.has(key)) {
2672
+ return true;
2673
+ }
2674
+ }
2675
+ return false;
2676
+ }
2584
2677
  }
package/src/types.ts CHANGED
@@ -135,6 +135,17 @@ export interface RemovedEntry {
135
135
  originalName?: string;
136
136
  }
137
137
 
138
+ /**
139
+ * Version check entry data - records which version of a code path this
140
+ * workflow instance is pinned to at a given location.
141
+ */
142
+ export interface VersionCheckEntry {
143
+ /** The version this instance resolved to at this location. */
144
+ resolved: number;
145
+ /** The `latest` value seen when this entry was first resolved (diagnostics). */
146
+ latest: number;
147
+ }
148
+
138
149
  /**
139
150
  * All possible entry kind types.
140
151
  */
@@ -146,7 +157,8 @@ export type EntryKindType =
146
157
  | "rollback_checkpoint"
147
158
  | "join"
148
159
  | "race"
149
- | "removed";
160
+ | "removed"
161
+ | "version_check";
150
162
 
151
163
  /**
152
164
  * Type-specific entry data.
@@ -159,7 +171,8 @@ export type EntryKind =
159
171
  | { type: "rollback_checkpoint"; data: RollbackCheckpointEntry }
160
172
  | { type: "join"; data: JoinEntry }
161
173
  | { type: "race"; data: RaceEntry }
162
- | { type: "removed"; data: RemovedEntry };
174
+ | { type: "removed"; data: RemovedEntry }
175
+ | { type: "version_check"; data: VersionCheckEntry };
163
176
 
164
177
  /**
165
178
  * An entry in the workflow history.
@@ -539,6 +552,8 @@ export interface WorkflowContextInterface {
539
552
 
540
553
  removed(name: string, originalType: EntryKindType): Promise<void>;
541
554
 
555
+ getVersion(name: string, latest: number): Promise<number>;
556
+
542
557
  isEvicted(): boolean;
543
558
  }
544
559