rivetkit 2.3.24-rc.1 → 2.3.25

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.
Files changed (115) hide show
  1. package/dist/browser/client.d.ts +3 -2
  2. package/dist/browser/client.js +36 -17
  3. package/dist/browser/client.js.map +1 -1
  4. package/dist/browser/inspector/client.js +1 -1
  5. package/dist/browser/inspector/client.js.map +1 -1
  6. package/dist/tsup/agent-os/index.cjs +1 -1
  7. package/dist/tsup/agent-os/index.cjs.map +1 -1
  8. package/dist/tsup/agent-os/index.d.cts +0 -2
  9. package/dist/tsup/agent-os/index.d.ts +0 -2
  10. package/dist/tsup/agent-os/index.js +1 -1
  11. package/dist/tsup/agent-os/index.js.map +1 -1
  12. package/dist/tsup/{chunk-OB5JLDBM.js → chunk-3KHT4UQA.js} +2 -2
  13. package/dist/tsup/{chunk-R3UI7MO3.cjs → chunk-4C2R5ZGV.cjs} +165 -146
  14. package/dist/tsup/chunk-4C2R5ZGV.cjs.map +1 -0
  15. package/dist/tsup/{chunk-JKDAOE4T.js → chunk-7YQ2BGJR.js} +4 -4
  16. package/dist/tsup/{chunk-QQ454DVR.js → chunk-BRYK7XVR.js} +2 -2
  17. package/dist/tsup/{chunk-JJCUSUWO.js → chunk-BSQWFYSP.js} +2 -2
  18. package/dist/tsup/chunk-BSQWFYSP.js.map +1 -0
  19. package/dist/tsup/{chunk-LTGBHN5Z.js → chunk-CSOHAAZK.js} +1 -1
  20. package/dist/tsup/chunk-CSOHAAZK.js.map +1 -0
  21. package/dist/tsup/{chunk-PFHGTLF2.cjs → chunk-EOEB2O7Z.cjs} +10 -10
  22. package/dist/tsup/{chunk-PFHGTLF2.cjs.map → chunk-EOEB2O7Z.cjs.map} +1 -1
  23. package/dist/tsup/{chunk-M5J3PXNU.js → chunk-FHRRLHJE.js} +2 -2
  24. package/dist/tsup/{chunk-CE6NBGOL.cjs → chunk-FTHC2AMB.cjs} +3 -3
  25. package/dist/tsup/{chunk-CE6NBGOL.cjs.map → chunk-FTHC2AMB.cjs.map} +1 -1
  26. package/dist/tsup/{chunk-B6WTPGOR.js → chunk-FV63WBQ5.js} +30 -11
  27. package/dist/tsup/chunk-FV63WBQ5.js.map +1 -0
  28. package/dist/tsup/{chunk-64CRWLOX.js → chunk-HAKSJXR4.js} +3 -3
  29. package/dist/tsup/{chunk-SWQCSORE.cjs → chunk-NP7HZL6X.cjs} +3 -3
  30. package/dist/tsup/{chunk-SWQCSORE.cjs.map → chunk-NP7HZL6X.cjs.map} +1 -1
  31. package/dist/tsup/{chunk-NGJWQMUU.cjs → chunk-NWCAIWHL.cjs} +1 -1
  32. package/dist/tsup/chunk-NWCAIWHL.cjs.map +1 -0
  33. package/dist/tsup/{chunk-JMO6AVUC.cjs → chunk-NWHEYTL2.cjs} +3 -3
  34. package/dist/tsup/{chunk-JMO6AVUC.cjs.map → chunk-NWHEYTL2.cjs.map} +1 -1
  35. package/dist/tsup/{chunk-ERBNWARB.cjs → chunk-RIZ57PM3.cjs} +4 -4
  36. package/dist/tsup/{chunk-ERBNWARB.cjs.map → chunk-RIZ57PM3.cjs.map} +1 -1
  37. package/dist/tsup/{chunk-6HW3TU7Q.js → chunk-WIRWF3Q2.js} +2 -2
  38. package/dist/tsup/{chunk-YVVFOKEP.cjs → chunk-WMRE434Q.cjs} +2 -2
  39. package/dist/tsup/chunk-WMRE434Q.cjs.map +1 -0
  40. package/dist/tsup/{chunk-DAC73W53.cjs → chunk-XVEADNHV.cjs} +7 -7
  41. package/dist/tsup/{chunk-DAC73W53.cjs.map → chunk-XVEADNHV.cjs.map} +1 -1
  42. package/dist/tsup/client/mod.cjs +5 -5
  43. package/dist/tsup/client/mod.d.cts +5 -2
  44. package/dist/tsup/client/mod.d.ts +5 -2
  45. package/dist/tsup/client/mod.js +4 -4
  46. package/dist/tsup/common/log.cjs +2 -2
  47. package/dist/tsup/common/log.js +1 -1
  48. package/dist/tsup/common/websocket.cjs +3 -3
  49. package/dist/tsup/common/websocket.js +2 -2
  50. package/dist/tsup/{config-RV6gIa2L.d.ts → config-Cv6pjCt-.d.ts} +0 -4
  51. package/dist/tsup/{config-CuKzfH58.d.cts → config-osdJqQwX.d.cts} +0 -4
  52. package/dist/tsup/{context-DoMKZBQA.d.ts → context-CoVbKBuk.d.ts} +1 -1
  53. package/dist/tsup/{context-DPCxyjax.d.cts → context-DpjrM7n7.d.cts} +1 -1
  54. package/dist/tsup/db/drizzle.cjs +2 -2
  55. package/dist/tsup/db/drizzle.js +1 -1
  56. package/dist/tsup/db/mod.cjs +3 -3
  57. package/dist/tsup/db/mod.js +2 -2
  58. package/dist/tsup/dynamic/mod.cjs +2 -2
  59. package/dist/tsup/dynamic/mod.d.cts +1 -1
  60. package/dist/tsup/dynamic/mod.d.ts +1 -1
  61. package/dist/tsup/dynamic/mod.js +1 -1
  62. package/dist/tsup/inspector/mod.cjs +5 -5
  63. package/dist/tsup/inspector/mod.js +4 -4
  64. package/dist/tsup/inspector/workflow.cjs +4 -4
  65. package/dist/tsup/inspector/workflow.js +3 -3
  66. package/dist/tsup/inspector-tab/mod.cjs +2 -2
  67. package/dist/tsup/inspector-tab/mod.d.cts +2 -2
  68. package/dist/tsup/inspector-tab/mod.d.ts +2 -2
  69. package/dist/tsup/inspector-tab/mod.js +1 -1
  70. package/dist/tsup/mod.cjs +189 -417
  71. package/dist/tsup/mod.cjs.map +1 -1
  72. package/dist/tsup/mod.d.cts +3 -3
  73. package/dist/tsup/mod.d.ts +3 -3
  74. package/dist/tsup/mod.js +94 -322
  75. package/dist/tsup/mod.js.map +1 -1
  76. package/dist/tsup/test/mod.cjs +6 -6
  77. package/dist/tsup/test/mod.d.cts +1 -1
  78. package/dist/tsup/test/mod.d.ts +1 -1
  79. package/dist/tsup/test/mod.js +4 -4
  80. package/dist/tsup/utils.cjs +2 -2
  81. package/dist/tsup/utils.js +1 -1
  82. package/dist/tsup/workflow/mod.cjs +21 -69
  83. package/dist/tsup/workflow/mod.cjs.map +1 -1
  84. package/dist/tsup/workflow/mod.d.cts +3 -3
  85. package/dist/tsup/workflow/mod.d.ts +3 -3
  86. package/dist/tsup/workflow/mod.js +16 -64
  87. package/dist/tsup/workflow/mod.js.map +1 -1
  88. package/package.json +9 -9
  89. package/src/actor/config.ts +0 -2
  90. package/src/client/config.ts +3 -0
  91. package/src/client/raw-utils.ts +7 -2
  92. package/src/common/fetch-like.ts +14 -0
  93. package/src/engine-client/actor-http-client.ts +16 -6
  94. package/src/registry/napi-runtime.ts +0 -8
  95. package/src/registry/native.ts +65 -332
  96. package/src/registry/run-handler-coordinator.test.ts +0 -102
  97. package/src/registry/run-handler-coordinator.ts +17 -84
  98. package/src/registry/runtime.ts +0 -2
  99. package/src/registry/wasm-runtime.ts +0 -8
  100. package/src/workflow/context.ts +0 -20
  101. package/src/workflow/driver.ts +1 -25
  102. package/src/workflow/mod.ts +12 -46
  103. package/dist/tsup/chunk-B6WTPGOR.js.map +0 -1
  104. package/dist/tsup/chunk-JJCUSUWO.js.map +0 -1
  105. package/dist/tsup/chunk-LTGBHN5Z.js.map +0 -1
  106. package/dist/tsup/chunk-NGJWQMUU.cjs.map +0 -1
  107. package/dist/tsup/chunk-R3UI7MO3.cjs.map +0 -1
  108. package/dist/tsup/chunk-YVVFOKEP.cjs.map +0 -1
  109. package/src/registry/lost-callbacks.test.ts +0 -64
  110. /package/dist/tsup/{chunk-OB5JLDBM.js.map → chunk-3KHT4UQA.js.map} +0 -0
  111. /package/dist/tsup/{chunk-JKDAOE4T.js.map → chunk-7YQ2BGJR.js.map} +0 -0
  112. /package/dist/tsup/{chunk-QQ454DVR.js.map → chunk-BRYK7XVR.js.map} +0 -0
  113. /package/dist/tsup/{chunk-M5J3PXNU.js.map → chunk-FHRRLHJE.js.map} +0 -0
  114. /package/dist/tsup/{chunk-64CRWLOX.js.map → chunk-HAKSJXR4.js.map} +0 -0
  115. /package/dist/tsup/{chunk-6HW3TU7Q.js.map → chunk-WIRWF3Q2.js.map} +0 -0
@@ -1,6 +1,5 @@
1
1
  import { describe, expect, test, vi } from "vitest";
2
2
  import { defineRunHandler, type RunControl } from "@/actor/config";
3
- import { workflow } from "@/workflow/mod";
4
3
  import { RunHandlerCoordinator } from "./run-handler-coordinator";
5
4
 
6
5
  class Deferred<T = void> {
@@ -52,107 +51,6 @@ function createCoordinator() {
52
51
  }
53
52
 
54
53
  describe("RunHandlerCoordinator", () => {
55
- test("workflow inspector registrations stay per generation", () => {
56
- const coordinator = new RunHandlerCoordinator(workflow(async () => {}));
57
- const restart = vi.fn();
58
-
59
- const oldInspector = coordinator.getInspector(
60
- "actor-1",
61
- restart,
62
- 1,
63
- )?.workflow;
64
- const newInspector = coordinator.getInspector(
65
- "actor-1",
66
- restart,
67
- 2,
68
- )?.workflow;
69
- expect(oldInspector).toBeDefined();
70
- expect(newInspector).toBeDefined();
71
- expect(newInspector).not.toBe(oldInspector);
72
-
73
- // A superseded generation cannot re-initialize or rebind the current generation's
74
- // workflow registration.
75
- expect(coordinator.getInspector("actor-1", restart, 1)).toBeUndefined();
76
- expect(coordinator.getInspector("actor-1", restart, 2)?.workflow).toBe(
77
- newInspector,
78
- );
79
- });
80
-
81
- test("a superseded generation's run is rejected before it touches the inspector", async () => {
82
- const coordinator = new RunHandlerCoordinator(workflow(async () => {}));
83
- const restart = vi.fn();
84
- const newInspector = coordinator.getInspector(
85
- "actor-1",
86
- restart,
87
- 2,
88
- )?.workflow;
89
-
90
- await expect(
91
- coordinator.run("actor-1", restart, async () => {}, 1),
92
- ).resolves.toBe("closed");
93
- expect(coordinator.getInspector("actor-1", restart, 2)?.workflow).toBe(
94
- newInspector,
95
- );
96
- });
97
-
98
- test("a newer generation does not wait on an older generation's stuck run", async () => {
99
- const coordinator = new RunHandlerCoordinator(
100
- defineRunHandler(async () => {}, {
101
- inspectorKind: "workflow",
102
- createInspector: () => ({
103
- inspector: {
104
- workflow: {
105
- getHistory: () => null,
106
- getState: async () => null,
107
- onHistoryUpdated: () => () => {},
108
- replayFromStep: async () => null,
109
- },
110
- },
111
- }),
112
- }),
113
- );
114
- const oldRun = new Deferred();
115
- const oldOutcome = coordinator.run(
116
- "actor-1",
117
- () => {},
118
- () => oldRun.promise,
119
- 1,
120
- );
121
-
122
- // The lost generation's JS callback cannot be cancelled, so it stays active.
123
- await expect(
124
- coordinator.run(
125
- "actor-1",
126
- () => {},
127
- async () => {},
128
- 2,
129
- ),
130
- ).resolves.toBe("ran");
131
-
132
- // The superseded generation cannot start new runs, and its late destroy leaves the
133
- // newer generation's state in place.
134
- await expect(
135
- coordinator.run(
136
- "actor-1",
137
- () => {},
138
- async () => {},
139
- 1,
140
- ),
141
- ).resolves.toBe("closed");
142
- coordinator.destroy("actor-1", 1);
143
- await expect(
144
- coordinator.run(
145
- "actor-1",
146
- () => {},
147
- async () => {},
148
- 2,
149
- ),
150
- ).resolves.toBe("ran");
151
-
152
- oldRun.resolve();
153
- await expect(oldOutcome).resolves.toBe("ran");
154
- });
155
-
156
54
  test("fails explicitly when a JavaScript factory omits required workflow controls", async () => {
157
55
  const coordinator = new RunHandlerCoordinator(
158
56
  defineRunHandler(async () => {}, {
@@ -11,8 +11,6 @@ import { RivetError } from "@/actor/errors";
11
11
  type RunHandler = ((...args: any[]) => any) | { run: (...args: any[]) => any };
12
12
 
13
13
  interface ActorRunState {
14
- /** Actor generation that owns this state, when the runtime reports one. */
15
- actorGeneration: number | undefined;
16
14
  active: boolean;
17
15
  closed: boolean;
18
16
  exclusive: boolean;
@@ -48,32 +46,6 @@ function notifyStateChanged(state: ActorRunState): void {
48
46
  }
49
47
  }
50
48
 
51
- function createRunState(actorGeneration: number | undefined): ActorRunState {
52
- return {
53
- actorGeneration,
54
- active: false,
55
- closed: false,
56
- exclusive: false,
57
- exclusiveGeneration: 0,
58
- inspectorInitialized: false,
59
- queued: 0,
60
- waiters: new Set(),
61
- };
62
- }
63
-
64
- /**
65
- * Closes run state. The inspector disposer is user code, so it is skipped for a generation
66
- * that was declared lost.
67
- */
68
- function closeRunState(state: ActorRunState, disposeInspector = true): void {
69
- state.closed = true;
70
- if (disposeInspector) {
71
- state.inspector?.dispose?.();
72
- }
73
- state.inspector = undefined;
74
- notifyStateChanged(state);
75
- }
76
-
77
49
  function waitForStateChange(state: ActorRunState): Promise<void> {
78
50
  return new Promise((resolve) => {
79
51
  state.waiters.add(resolve);
@@ -97,14 +69,8 @@ export class RunHandlerCoordinator {
97
69
  actorId: string,
98
70
  restart: () => void | Promise<void>,
99
71
  callback: () => void | Promise<void>,
100
- actorGeneration?: number,
101
72
  ): Promise<RunHandlerOutcome> {
102
- const state = this.#getOrCreate(actorId, actorGeneration);
103
- // Closed state belongs to a superseded generation. It must not initialize an inspector,
104
- // which would rebind the workflow registration of the current generation.
105
- if (state.closed) {
106
- return "closed";
107
- }
73
+ const state = this.#getOrCreate(actorId);
108
74
  state.restart = restart;
109
75
  this.#initializeInspector(actorId, state);
110
76
  state.queued += 1;
@@ -144,37 +110,21 @@ export class RunHandlerCoordinator {
144
110
  getInspector(
145
111
  actorId: string,
146
112
  restart: () => void | Promise<void>,
147
- actorGeneration?: number,
148
113
  ): RunInspectorConfig | undefined {
149
- const state = this.#getOrCreate(actorId, actorGeneration);
150
- if (state.closed) {
151
- return undefined;
152
- }
114
+ const state = this.#getOrCreate(actorId);
153
115
  state.restart = restart;
154
116
  this.#initializeInspector(actorId, state);
155
117
  return state.inspector?.inspector;
156
118
  }
157
119
 
158
- /**
159
- * Closes the run state for `actorId`. With `actorGeneration`, only state owned by that
160
- * generation is closed, so an older generation's late cleanup cannot close a newer one.
161
- */
162
- destroy(
163
- actorId: string,
164
- actorGeneration?: number,
165
- options: { disposeInspector?: boolean } = {},
166
- ): void {
120
+ destroy(actorId: string): void {
167
121
  const state = this.#states.get(actorId);
168
122
  if (!state) return;
169
- if (
170
- actorGeneration !== undefined &&
171
- state.actorGeneration !== undefined &&
172
- state.actorGeneration !== actorGeneration
173
- ) {
174
- return;
175
- }
176
123
 
177
- closeRunState(state, options.disposeInspector ?? true);
124
+ state.closed = true;
125
+ state.inspector?.dispose?.();
126
+ state.inspector = undefined;
127
+ notifyStateChanged(state);
178
128
  this.#states.delete(actorId);
179
129
  }
180
130
 
@@ -223,34 +173,18 @@ export class RunHandlerCoordinator {
223
173
  };
224
174
  }
225
175
 
226
- #getOrCreate(
227
- actorId: string,
228
- actorGeneration: number | undefined,
229
- ): ActorRunState {
176
+ #getOrCreate(actorId: string): ActorRunState {
230
177
  let state = this.#states.get(actorId);
231
- if (
232
- state &&
233
- actorGeneration !== undefined &&
234
- state.actorGeneration !== undefined &&
235
- state.actorGeneration !== actorGeneration
236
- ) {
237
- if (actorGeneration < state.actorGeneration) {
238
- // A superseded generation gets closed, detached state so it cannot run or
239
- // block the current generation.
240
- const detached = createRunState(actorGeneration);
241
- detached.closed = true;
242
- return detached;
243
- }
244
- // A newer generation replaces state left by an older one, which may still be
245
- // marked active because its JS callback cannot be cancelled. That generation did not
246
- // clean up after itself, which only happens when it was lost, so its user inspector
247
- // disposer is not called.
248
- closeRunState(state, false);
249
- this.#states.delete(actorId);
250
- state = undefined;
251
- }
252
178
  if (!state) {
253
- state = createRunState(actorGeneration);
179
+ state = {
180
+ active: false,
181
+ closed: false,
182
+ exclusive: false,
183
+ exclusiveGeneration: 0,
184
+ inspectorInitialized: false,
185
+ queued: 0,
186
+ waiters: new Set(),
187
+ };
254
188
  this.#states.set(actorId, state);
255
189
  }
256
190
  return state;
@@ -260,7 +194,6 @@ export class RunHandlerCoordinator {
260
194
  if (state.inspectorInitialized) return;
261
195
  const inspector = createRunInspector(this.#run, {
262
196
  actorId,
263
- actorGeneration: state.actorGeneration,
264
197
  control: this.#control(actorId, state),
265
198
  });
266
199
  if (this.inspectorKind === "workflow") {
@@ -583,8 +583,6 @@ export interface CoreRuntime {
583
583
  writes: RuntimeWorkflowKvWrite[],
584
584
  ): Promise<void>;
585
585
  actorId(ctx: ActorContextHandle): string;
586
- actorGeneration(ctx: ActorContextHandle): number | undefined;
587
- actorIsLost(ctx: ActorContextHandle): boolean;
588
586
  /**
589
587
  * Runs one actor callback with `ctx` as the current invocation: operations
590
588
  * on retained handles for the same actor resolve to it, and its Core span
@@ -538,14 +538,6 @@ export class WasmCoreRuntime implements CoreRuntime {
538
538
  return callHandle(asWasmActorContext(ctx), "actorId");
539
539
  }
540
540
 
541
- actorGeneration(ctx: ActorContextHandle): number | undefined {
542
- return callHandle(asWasmActorContext(ctx), "generation") ?? undefined;
543
- }
544
-
545
- actorIsLost(ctx: ActorContextHandle): boolean {
546
- return callHandle(asWasmActorContext(ctx), "isLost");
547
- }
548
-
549
541
  runWithActorInvocationContext<T>(
550
542
  _ctx: ActorContextHandle,
551
543
  run: () => T,
@@ -12,7 +12,6 @@ import type {
12
12
  WorkflowContextInterface,
13
13
  WorkflowQueueMessage,
14
14
  } from "@rivetkit/workflow-engine";
15
- import { EvictedError } from "@rivetkit/workflow-engine";
16
15
  import type {
17
16
  QueueFilterName,
18
17
  QueueNextBatchOptions,
@@ -20,7 +19,6 @@ import type {
20
19
  QueueResultMessageForName,
21
20
  RunContext,
22
21
  } from "@/actor/config";
23
- import { ACTOR_CONTEXT_INTERNAL_SYMBOL } from "@/actor/config";
24
22
  import type {
25
23
  AnyActorDefinition,
26
24
  BaseActorDefinition,
@@ -284,20 +282,6 @@ export type WorkflowBranchConfig<
284
282
  // never appears on the public surface.
285
283
  const DEACTIVATE_STEP = Symbol("workflow.step.deactivate");
286
284
 
287
- /**
288
- * Stops the workflow before it starts more user code once its actor generation was declared
289
- * lost. The engine treats the eviction like a sleep and replays from history in the next
290
- * generation.
291
- */
292
- export function throwIfGenerationLost(runCtx: unknown): void {
293
- const actor = (
294
- runCtx as { [ACTOR_CONTEXT_INTERNAL_SYMBOL]?: { isLost?: boolean } }
295
- )[ACTOR_CONTEXT_INTERNAL_SYMBOL];
296
- if (actor?.isLost === true) {
297
- throw new EvictedError();
298
- }
299
- }
300
-
301
285
  /**
302
286
  * The context handed to a workflow step (`step` / `tryStep` callbacks). This is
303
287
  * the only scope where actor data (state, vars, db, client) and side effects
@@ -1010,7 +994,6 @@ export class WorkflowContext<
1010
994
  TQueues
1011
995
  >(this.#runCtx, () => this.#markGuardTriggered());
1012
996
 
1013
- throwIfGenerationLost(this.#runCtx);
1014
997
  try {
1015
998
  return await run(stepCtx);
1016
999
  } finally {
@@ -1061,7 +1044,6 @@ export class WorkflowContext<
1061
1044
  TEvents,
1062
1045
  TQueues
1063
1046
  >(this.#runCtx, () => this.#markGuardTriggered());
1064
- throwIfGenerationLost(this.#runCtx);
1065
1047
  try {
1066
1048
  await rollback(stepCtx, output);
1067
1049
  } finally {
@@ -1115,8 +1097,6 @@ export class WorkflowContext<
1115
1097
  TEvents,
1116
1098
  TQueues
1117
1099
  > {
1118
- // Every try, loop, join, and race body runs through a child context.
1119
- throwIfGenerationLost(this.#runCtx);
1120
1100
  return new WorkflowContext(ctx, this.#runCtx);
1121
1101
  }
1122
1102
  }
@@ -10,7 +10,6 @@ import type { RunContext } from "@/actor/config";
10
10
  import type { AnyStaticActorInstance } from "@/actor/definition";
11
11
  import { makeWorkflowKey, workflowStoragePrefix } from "@/actor/keys";
12
12
  import type { RawAccess } from "@/common/database/config";
13
- import { throwIfGenerationLost } from "./context";
14
13
 
15
14
  const WORKFLOW_STORAGE_PREFIX = workflowStoragePrefix();
16
15
  // Keep workflow flushes below depot's 320-dirty-page commit ceiling. The
@@ -70,26 +69,6 @@ function normalizeSqlBlob(value: unknown): Uint8Array {
70
69
  throw new Error("workflow sqlite value was not a blob");
71
70
  }
72
71
 
73
- function guardRawAccessAgainstLost(
74
- access: RawAccess,
75
- runCtx: RunContext<any, any, any, any, any, any, any, any> | undefined,
76
- ): RawAccess {
77
- return {
78
- ...access,
79
- execute: ((...args: Parameters<RawAccess["execute"]>) => {
80
- throwIfGenerationLost(runCtx);
81
- return access.execute(...args);
82
- }) as RawAccess["execute"],
83
- transaction: (callback, options) => {
84
- throwIfGenerationLost(runCtx);
85
- return access.transaction(
86
- (tx) => callback(guardRawAccessAgainstLost(tx, runCtx)),
87
- options,
88
- );
89
- },
90
- };
91
- }
92
-
93
72
  function runtimeDbFromContext(
94
73
  runCtx?: RunContext<any, any, any, any, any, any, any, any>,
95
74
  ): RawAccess | undefined {
@@ -100,10 +79,7 @@ function runtimeDbFromContext(
100
79
  "execute" in db &&
101
80
  "transaction" in db
102
81
  ) {
103
- // The client can come from a user database provider. Workflow storage calls it after
104
- // awaits, including inside its own transactions, so every call checks that the
105
- // generation was not lost first.
106
- return guardRawAccessAgainstLost(db as RawAccess, runCtx);
82
+ return db as RawAccess;
107
83
  }
108
84
  return undefined;
109
85
  }
@@ -24,7 +24,7 @@ import { isActorAbortedError, RivetError } from "@/actor/errors";
24
24
  import type { EventSchemaConfig, QueueSchemaConfig } from "@/actor/schema";
25
25
  import type { AnyDatabaseProvider } from "@/common/database/config";
26
26
  import { stringifyError } from "@/utils";
27
- import { throwIfGenerationLost, WorkflowContext } from "./context";
27
+ import { WorkflowContext } from "./context";
28
28
  import { ActorWorkflowControlDriver, ActorWorkflowDriver } from "./driver";
29
29
  import { createWorkflowInspectorAdapter } from "./inspector";
30
30
 
@@ -178,28 +178,13 @@ export function workflow<
178
178
  type WorkflowInspectorRegistration = ReturnType<
179
179
  typeof createWorkflowInspectorAdapter
180
180
  > & { control?: RunControl };
181
- // Keyed by actor id and generation so a lost generation that is still running cannot rebind
182
- // the control or state of the generation that replaced it.
183
181
  const workflowInspectors = new Map<string, WorkflowInspectorRegistration>();
184
182
 
185
- function workflowInspectorKey(
186
- actorId: string,
187
- actorGeneration: number | undefined,
188
- ): string {
189
- return actorGeneration === undefined
190
- ? actorId
191
- : `${actorId}#${actorGeneration}`;
192
- }
193
-
194
- function getWorkflowInspector(
195
- actorId: string,
196
- actorGeneration: number | undefined,
197
- ) {
198
- const key = workflowInspectorKey(actorId, actorGeneration);
199
- let workflowInspector = workflowInspectors.get(key);
183
+ function getWorkflowInspector(actorId: string) {
184
+ let workflowInspector = workflowInspectors.get(actorId);
200
185
  if (!workflowInspector) {
201
186
  workflowInspector = createWorkflowInspectorAdapter();
202
- workflowInspectors.set(key, workflowInspector);
187
+ workflowInspectors.set(actorId, workflowInspector);
203
188
  }
204
189
  return workflowInspector;
205
190
  }
@@ -222,11 +207,7 @@ export function workflow<
222
207
  }
223
208
  )[ACTOR_CONTEXT_INTERNAL_SYMBOL];
224
209
  invariant(actor, "workflow() requires an actor instance");
225
- const actorGeneration = (actor as { generation?: number }).generation;
226
- const workflowInspector = getWorkflowInspector(
227
- actor.id,
228
- actorGeneration,
229
- );
210
+ const workflowInspector = getWorkflowInspector(actor.id);
230
211
 
231
212
  const driver = new ActorWorkflowDriver(actor, runCtx);
232
213
  const controlDriver = new ActorWorkflowControlDriver(actor, runCtx);
@@ -265,10 +246,7 @@ export function workflow<
265
246
 
266
247
  const handle = runWorkflow(
267
248
  actor.id,
268
- async (ctx) => {
269
- throwIfGenerationLost(runCtx);
270
- return await fn(new WorkflowContext(ctx, runCtx));
271
- },
249
+ async (ctx) => await fn(new WorkflowContext(ctx, runCtx)),
272
250
  undefined,
273
251
  driver,
274
252
  {
@@ -278,15 +256,7 @@ export function workflow<
278
256
  logger: runCtx.log as RunWorkflowOptions["logger"],
279
257
  onHistoryUpdated: workflowInspector.update,
280
258
  onError: onError
281
- ? async (event) => {
282
- // A lost generation starts no new user hook.
283
- if (
284
- (actor as { isLost?: boolean }).isLost === true
285
- ) {
286
- return;
287
- }
288
- await onError(runCtx, event);
289
- }
259
+ ? async (event) => await onError(runCtx, event)
290
260
  : undefined,
291
261
  },
292
262
  );
@@ -332,20 +302,16 @@ export function workflow<
332
302
  return defineRunHandler(run, {
333
303
  icon: "diagram-project",
334
304
  inspectorKind: "workflow",
335
- createInspector: ({ actorId, actorGeneration, control }) => {
336
- const key = workflowInspectorKey(actorId, actorGeneration);
337
- const workflowInspector = getWorkflowInspector(
338
- actorId,
339
- actorGeneration,
340
- );
305
+ createInspector: ({ actorId, control }) => {
306
+ const workflowInspector = getWorkflowInspector(actorId);
341
307
  workflowInspector.control = control;
342
308
  return {
343
309
  inspector: { workflow: workflowInspector.adapter },
344
310
  dispose: () => {
345
311
  // Do not let a stale disposer remove a newly-created adapter for
346
- // the same actor generation.
347
- if (workflowInspectors.get(key) === workflowInspector) {
348
- workflowInspectors.delete(key);
312
+ // the same actor id.
313
+ if (workflowInspectors.get(actorId) === workflowInspector) {
314
+ workflowInspectors.delete(actorId);
349
315
  }
350
316
  },
351
317
  };