@mastra/inngest 0.18.5 → 0.18.6
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.
- package/CHANGELOG.md +52 -0
- package/dist/index.cjs +254 -31
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +59 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +255 -32
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,57 @@
|
|
|
1
1
|
# @mastra/inngest
|
|
2
2
|
|
|
3
|
+
## 0.18.6
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Handle state update and bailing in foreach steps ([#10826](https://github.com/mastra-ai/mastra/pull/10826))
|
|
8
|
+
|
|
9
|
+
- Add restart method to workflow run that allows restarting an active workflow run ([#10703](https://github.com/mastra-ai/mastra/pull/10703))
|
|
10
|
+
Add status filter to `getWorkflowRuns`
|
|
11
|
+
Add automatic restart to restart active workflow runs when server starts
|
|
12
|
+
|
|
13
|
+
- Add timeTravel to workflows. This makes it possible to start a workflow run from a particular step in the workflow ([#10717](https://github.com/mastra-ai/mastra/pull/10717))
|
|
14
|
+
|
|
15
|
+
Example code:
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
const result = await run.timeTravel({
|
|
19
|
+
step: 'step2',
|
|
20
|
+
inputData: {
|
|
21
|
+
value: 'input',
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
- Updated dependencies [[`5cc85aa`](https://github.com/mastra-ai/mastra/commit/5cc85aa4329773cac8314f3aa0146227b6b158e4), [`c53f8e6`](https://github.com/mastra-ai/mastra/commit/c53f8e68df42464935f9a63eb0fc765a65aacb83), [`386ab43`](https://github.com/mastra-ai/mastra/commit/386ab4350cf2a814fb4ac0a5fc6983ca93158ffe), [`2b62302`](https://github.com/mastra-ai/mastra/commit/2b623027a9d65c1dbc963bf651e9e6a9d09da1fa), [`7d85da4`](https://github.com/mastra-ai/mastra/commit/7d85da42a5fab56009a959a9c20328558d14f4b5), [`3d7c5bd`](https://github.com/mastra-ai/mastra/commit/3d7c5bdbee1b2693cd45bf207b960dd9b7277680), [`31b381e`](https://github.com/mastra-ai/mastra/commit/31b381efb48e031c0ecc46bc6e410ae6e67b88e5), [`54cc99c`](https://github.com/mastra-ai/mastra/commit/54cc99cb99483b9e08ec41fa1502f43b71b4c351), [`e77a5f9`](https://github.com/mastra-ai/mastra/commit/e77a5f9718dc418e29e3c8a389299ed6dc0a6401), [`b685c9c`](https://github.com/mastra-ai/mastra/commit/b685c9c0b89f49e0d4542c4ac72569682db69794), [`b069af5`](https://github.com/mastra-ai/mastra/commit/b069af514c4dcfc4fdcb164303569bfff1c26e3d), [`7dc8304`](https://github.com/mastra-ai/mastra/commit/7dc830420296db516b86dcec663e54d0309b8fb8), [`6942109`](https://github.com/mastra-ai/mastra/commit/694210903c70e3c26b5ce8ca4f4637ca2d9eb369), [`62d13f4`](https://github.com/mastra-ai/mastra/commit/62d13f4d1db1c16742831f210fe4c2caf8a26d57), [`358ab98`](https://github.com/mastra-ai/mastra/commit/358ab98024c388e383aca15616e8988bf4a5b66e)]:
|
|
27
|
+
- @mastra/core@0.24.7
|
|
28
|
+
|
|
29
|
+
## 0.18.6-alpha.0
|
|
30
|
+
|
|
31
|
+
### Patch Changes
|
|
32
|
+
|
|
33
|
+
- Handle state update and bailing in foreach steps ([#10826](https://github.com/mastra-ai/mastra/pull/10826))
|
|
34
|
+
|
|
35
|
+
- Add restart method to workflow run that allows restarting an active workflow run ([#10703](https://github.com/mastra-ai/mastra/pull/10703))
|
|
36
|
+
Add status filter to `getWorkflowRuns`
|
|
37
|
+
Add automatic restart to restart active workflow runs when server starts
|
|
38
|
+
|
|
39
|
+
- Add timeTravel to workflows. This makes it possible to start a workflow run from a particular step in the workflow ([#10717](https://github.com/mastra-ai/mastra/pull/10717))
|
|
40
|
+
|
|
41
|
+
Example code:
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
const result = await run.timeTravel({
|
|
45
|
+
step: 'step2',
|
|
46
|
+
inputData: {
|
|
47
|
+
value: 'input',
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
- Updated dependencies [[`5cc85aa`](https://github.com/mastra-ai/mastra/commit/5cc85aa4329773cac8314f3aa0146227b6b158e4), [`c53f8e6`](https://github.com/mastra-ai/mastra/commit/c53f8e68df42464935f9a63eb0fc765a65aacb83), [`386ab43`](https://github.com/mastra-ai/mastra/commit/386ab4350cf2a814fb4ac0a5fc6983ca93158ffe), [`2b62302`](https://github.com/mastra-ai/mastra/commit/2b623027a9d65c1dbc963bf651e9e6a9d09da1fa), [`7d85da4`](https://github.com/mastra-ai/mastra/commit/7d85da42a5fab56009a959a9c20328558d14f4b5), [`3d7c5bd`](https://github.com/mastra-ai/mastra/commit/3d7c5bdbee1b2693cd45bf207b960dd9b7277680), [`31b381e`](https://github.com/mastra-ai/mastra/commit/31b381efb48e031c0ecc46bc6e410ae6e67b88e5), [`e77a5f9`](https://github.com/mastra-ai/mastra/commit/e77a5f9718dc418e29e3c8a389299ed6dc0a6401), [`b069af5`](https://github.com/mastra-ai/mastra/commit/b069af514c4dcfc4fdcb164303569bfff1c26e3d), [`7dc8304`](https://github.com/mastra-ai/mastra/commit/7dc830420296db516b86dcec663e54d0309b8fb8), [`6942109`](https://github.com/mastra-ai/mastra/commit/694210903c70e3c26b5ce8ca4f4637ca2d9eb369), [`62d13f4`](https://github.com/mastra-ai/mastra/commit/62d13f4d1db1c16742831f210fe4c2caf8a26d57), [`358ab98`](https://github.com/mastra-ai/mastra/commit/358ab98024c388e383aca15616e8988bf4a5b66e)]:
|
|
53
|
+
- @mastra/core@0.24.7-alpha.1
|
|
54
|
+
|
|
3
55
|
## 0.18.5
|
|
4
56
|
|
|
5
57
|
### Patch Changes
|
package/dist/index.cjs
CHANGED
|
@@ -105,7 +105,8 @@ var InngestRun = class extends workflows.Run {
|
|
|
105
105
|
resourceId: this.resourceId,
|
|
106
106
|
snapshot: {
|
|
107
107
|
...snapshot,
|
|
108
|
-
status: "canceled"
|
|
108
|
+
status: "canceled",
|
|
109
|
+
value: snapshot.value
|
|
109
110
|
}
|
|
110
111
|
});
|
|
111
112
|
}
|
|
@@ -121,14 +122,15 @@ var InngestRun = class extends workflows.Run {
|
|
|
121
122
|
snapshot: {
|
|
122
123
|
runId: this.runId,
|
|
123
124
|
serializedStepGraph: this.serializedStepGraph,
|
|
125
|
+
status: "running",
|
|
124
126
|
value: {},
|
|
125
127
|
context: {},
|
|
126
128
|
activePaths: [],
|
|
127
129
|
suspendedPaths: {},
|
|
130
|
+
activeStepsPath: {},
|
|
128
131
|
resumeLabels: {},
|
|
129
132
|
waitingPaths: {},
|
|
130
|
-
timestamp: Date.now()
|
|
131
|
-
status: "running"
|
|
133
|
+
timestamp: Date.now()
|
|
132
134
|
}
|
|
133
135
|
});
|
|
134
136
|
const inputDataToUse = await this._validateInput(inputData);
|
|
@@ -168,10 +170,16 @@ var InngestRun = class extends workflows.Run {
|
|
|
168
170
|
return p;
|
|
169
171
|
}
|
|
170
172
|
async _resume(params) {
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
)
|
|
174
|
-
|
|
173
|
+
const storage = this.#mastra?.getStorage();
|
|
174
|
+
let steps = [];
|
|
175
|
+
if (typeof params.step === "string") {
|
|
176
|
+
steps = params.step.split(".");
|
|
177
|
+
} else {
|
|
178
|
+
steps = (Array.isArray(params.step) ? params.step : [params.step]).map(
|
|
179
|
+
(step) => typeof step === "string" ? step : step?.id
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
const snapshot = await storage?.loadWorkflowSnapshot({
|
|
175
183
|
workflowName: this.workflowId,
|
|
176
184
|
runId: this.runId
|
|
177
185
|
});
|
|
@@ -228,6 +236,97 @@ var InngestRun = class extends workflows.Run {
|
|
|
228
236
|
});
|
|
229
237
|
};
|
|
230
238
|
}
|
|
239
|
+
async timeTravel(params) {
|
|
240
|
+
const p = this._timeTravel(params).then((result) => {
|
|
241
|
+
if (result.status !== "suspended") {
|
|
242
|
+
this.closeStreamAction?.().catch(() => {
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
return result;
|
|
246
|
+
});
|
|
247
|
+
this.executionResults = p;
|
|
248
|
+
return p;
|
|
249
|
+
}
|
|
250
|
+
async _timeTravel(params) {
|
|
251
|
+
if (!params.step || Array.isArray(params.step) && params.step?.length === 0) {
|
|
252
|
+
throw new Error("Step is required and must be a valid step or array of steps");
|
|
253
|
+
}
|
|
254
|
+
let steps = [];
|
|
255
|
+
if (typeof params.step === "string") {
|
|
256
|
+
steps = params.step.split(".");
|
|
257
|
+
} else {
|
|
258
|
+
steps = (Array.isArray(params.step) ? params.step : [params.step]).map(
|
|
259
|
+
(step) => typeof step === "string" ? step : step?.id
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
if (steps.length === 0) {
|
|
263
|
+
throw new Error("No steps provided to timeTravel");
|
|
264
|
+
}
|
|
265
|
+
const storage = this.#mastra?.getStorage();
|
|
266
|
+
const snapshot = await storage?.loadWorkflowSnapshot({
|
|
267
|
+
workflowName: this.workflowId,
|
|
268
|
+
runId: this.runId
|
|
269
|
+
});
|
|
270
|
+
if (!snapshot) {
|
|
271
|
+
await storage?.persistWorkflowSnapshot({
|
|
272
|
+
workflowName: this.workflowId,
|
|
273
|
+
runId: this.runId,
|
|
274
|
+
resourceId: this.resourceId,
|
|
275
|
+
snapshot: {
|
|
276
|
+
runId: this.runId,
|
|
277
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
278
|
+
status: "pending",
|
|
279
|
+
value: {},
|
|
280
|
+
context: {},
|
|
281
|
+
activePaths: [],
|
|
282
|
+
suspendedPaths: {},
|
|
283
|
+
activeStepsPath: {},
|
|
284
|
+
resumeLabels: {},
|
|
285
|
+
waitingPaths: {},
|
|
286
|
+
timestamp: Date.now()
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
if (snapshot?.status === "running") {
|
|
291
|
+
throw new Error("This workflow run is still running, cannot time travel");
|
|
292
|
+
}
|
|
293
|
+
let inputDataToUse = params.inputData;
|
|
294
|
+
if (inputDataToUse && steps.length === 1) {
|
|
295
|
+
inputDataToUse = await this._validateTimetravelInputData(params.inputData, this.workflowSteps[steps[0]]);
|
|
296
|
+
}
|
|
297
|
+
const timeTravelData = workflows.createTimeTravelExecutionParams({
|
|
298
|
+
steps,
|
|
299
|
+
inputData: inputDataToUse,
|
|
300
|
+
resumeData: params.resumeData,
|
|
301
|
+
context: params.context,
|
|
302
|
+
nestedStepsContext: params.nestedStepsContext,
|
|
303
|
+
snapshot: snapshot ?? { context: {} },
|
|
304
|
+
graph: this.executionGraph,
|
|
305
|
+
initialState: params.initialState
|
|
306
|
+
});
|
|
307
|
+
const eventOutput = await this.inngest.send({
|
|
308
|
+
name: `workflow.${this.workflowId}`,
|
|
309
|
+
data: {
|
|
310
|
+
initialState: timeTravelData.state,
|
|
311
|
+
runId: this.runId,
|
|
312
|
+
workflowId: this.workflowId,
|
|
313
|
+
stepResults: timeTravelData.stepResults,
|
|
314
|
+
timeTravel: timeTravelData,
|
|
315
|
+
tracingOptions: params.tracingOptions,
|
|
316
|
+
outputOptions: params.outputOptions
|
|
317
|
+
}
|
|
318
|
+
});
|
|
319
|
+
const eventId = eventOutput.ids[0];
|
|
320
|
+
if (!eventId) {
|
|
321
|
+
throw new Error("Event ID is not set");
|
|
322
|
+
}
|
|
323
|
+
const runOutput = await this.getRunOutput(eventId);
|
|
324
|
+
const result = runOutput?.output?.result;
|
|
325
|
+
if (result.status === "failed") {
|
|
326
|
+
result.error = new Error(result.error);
|
|
327
|
+
}
|
|
328
|
+
return result;
|
|
329
|
+
}
|
|
231
330
|
streamLegacy({ inputData, runtimeContext } = {}) {
|
|
232
331
|
const { readable, writable } = new TransformStream();
|
|
233
332
|
const writer = writable.getWriter();
|
|
@@ -315,6 +414,74 @@ var InngestRun = class extends workflows.Run {
|
|
|
315
414
|
});
|
|
316
415
|
return streamOutput;
|
|
317
416
|
}
|
|
417
|
+
timeTravelStream({
|
|
418
|
+
inputData,
|
|
419
|
+
resumeData,
|
|
420
|
+
initialState,
|
|
421
|
+
step,
|
|
422
|
+
context,
|
|
423
|
+
nestedStepsContext,
|
|
424
|
+
runtimeContext,
|
|
425
|
+
tracingOptions,
|
|
426
|
+
outputOptions
|
|
427
|
+
}) {
|
|
428
|
+
const self = this;
|
|
429
|
+
let streamOutput;
|
|
430
|
+
const stream$1 = new web.ReadableStream({
|
|
431
|
+
async start(controller) {
|
|
432
|
+
const unwatch = self.watch(async ({ type, from = stream.ChunkFrom.WORKFLOW, payload }) => {
|
|
433
|
+
controller.enqueue({
|
|
434
|
+
type,
|
|
435
|
+
runId: self.runId,
|
|
436
|
+
from,
|
|
437
|
+
payload: {
|
|
438
|
+
stepName: payload?.id,
|
|
439
|
+
...payload
|
|
440
|
+
}
|
|
441
|
+
});
|
|
442
|
+
}, "watch-v2");
|
|
443
|
+
self.closeStreamAction = async () => {
|
|
444
|
+
unwatch();
|
|
445
|
+
try {
|
|
446
|
+
await controller.close();
|
|
447
|
+
} catch (err) {
|
|
448
|
+
console.error("Error closing stream:", err);
|
|
449
|
+
}
|
|
450
|
+
};
|
|
451
|
+
const executionResultsPromise = self._timeTravel({
|
|
452
|
+
inputData,
|
|
453
|
+
step,
|
|
454
|
+
context,
|
|
455
|
+
nestedStepsContext,
|
|
456
|
+
resumeData,
|
|
457
|
+
initialState,
|
|
458
|
+
runtimeContext,
|
|
459
|
+
tracingOptions,
|
|
460
|
+
outputOptions
|
|
461
|
+
});
|
|
462
|
+
self.executionResults = executionResultsPromise;
|
|
463
|
+
let executionResults;
|
|
464
|
+
try {
|
|
465
|
+
executionResults = await executionResultsPromise;
|
|
466
|
+
self.closeStreamAction?.().catch(() => {
|
|
467
|
+
});
|
|
468
|
+
if (streamOutput) {
|
|
469
|
+
streamOutput.updateResults(executionResults);
|
|
470
|
+
}
|
|
471
|
+
} catch (err) {
|
|
472
|
+
streamOutput?.rejectResults(err);
|
|
473
|
+
self.closeStreamAction?.().catch(() => {
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
});
|
|
478
|
+
streamOutput = new stream.WorkflowRunOutput({
|
|
479
|
+
runId: this.runId,
|
|
480
|
+
workflowId: this.workflowId,
|
|
481
|
+
stream: stream$1
|
|
482
|
+
});
|
|
483
|
+
return streamOutput;
|
|
484
|
+
}
|
|
318
485
|
};
|
|
319
486
|
var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
320
487
|
#mastra;
|
|
@@ -324,6 +491,7 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
|
324
491
|
constructor(params, inngest) {
|
|
325
492
|
const { concurrency, rateLimit, throttle, debounce, priority, ...workflowParams } = params;
|
|
326
493
|
super(workflowParams);
|
|
494
|
+
this.engineType = "inngest";
|
|
327
495
|
const flowControlEntries = Object.entries({ concurrency, rateLimit, throttle, debounce, priority }).filter(
|
|
328
496
|
([_, value]) => value !== void 0
|
|
329
497
|
);
|
|
@@ -388,7 +556,9 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
|
388
556
|
mastra: this.#mastra,
|
|
389
557
|
retryConfig: this.retryConfig,
|
|
390
558
|
cleanup: () => this.runs.delete(runIdToUse),
|
|
391
|
-
workflowSteps: this.steps
|
|
559
|
+
workflowSteps: this.steps,
|
|
560
|
+
workflowEngineType: this.engineType,
|
|
561
|
+
validateInputs: this.options.validateInputs
|
|
392
562
|
},
|
|
393
563
|
this.inngest
|
|
394
564
|
);
|
|
@@ -409,6 +579,7 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
|
409
579
|
value: {},
|
|
410
580
|
context: {},
|
|
411
581
|
activePaths: [],
|
|
582
|
+
activeStepsPath: {},
|
|
412
583
|
waitingPaths: {},
|
|
413
584
|
serializedStepGraph: this.serializedStepGraph,
|
|
414
585
|
suspendedPaths: {},
|
|
@@ -437,7 +608,7 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
|
437
608
|
},
|
|
438
609
|
{ event: `workflow.${this.id}` },
|
|
439
610
|
async ({ event, step, attempt, publish }) => {
|
|
440
|
-
let { inputData, initialState, runId, resourceId, resume, outputOptions } = event.data;
|
|
611
|
+
let { inputData, initialState, runId, resourceId, resume, outputOptions, timeTravel } = event.data;
|
|
441
612
|
if (!runId) {
|
|
442
613
|
runId = await step.run(`workflow.${this.id}.runIdGen`, async () => {
|
|
443
614
|
return crypto.randomUUID();
|
|
@@ -479,6 +650,7 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
|
479
650
|
runtimeContext: new di.RuntimeContext(),
|
|
480
651
|
// TODO
|
|
481
652
|
resume,
|
|
653
|
+
timeTravel,
|
|
482
654
|
abortController: new AbortController(),
|
|
483
655
|
currentSpan: void 0,
|
|
484
656
|
// TODO: Pass actual parent AI span from workflow execution context
|
|
@@ -939,6 +1111,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
939
1111
|
stepResults,
|
|
940
1112
|
executionContext,
|
|
941
1113
|
resume,
|
|
1114
|
+
timeTravel,
|
|
942
1115
|
prevOutput,
|
|
943
1116
|
emitter,
|
|
944
1117
|
abortController,
|
|
@@ -1002,6 +1175,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1002
1175
|
const isResume = !!resume?.steps?.length;
|
|
1003
1176
|
let result;
|
|
1004
1177
|
let runId;
|
|
1178
|
+
const isTimeTravel = !!(timeTravel && timeTravel.steps?.length > 1 && timeTravel.steps[0] === step.id);
|
|
1005
1179
|
try {
|
|
1006
1180
|
if (isResume) {
|
|
1007
1181
|
runId = stepResults[resume?.steps?.[0]]?.suspendPayload?.__workflow_meta?.runId ?? crypto.randomUUID();
|
|
@@ -1029,6 +1203,32 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1029
1203
|
result = invokeResp.result;
|
|
1030
1204
|
runId = invokeResp.runId;
|
|
1031
1205
|
executionContext.state = invokeResp.result.state;
|
|
1206
|
+
} else if (isTimeTravel) {
|
|
1207
|
+
const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
|
|
1208
|
+
workflowName: step.id,
|
|
1209
|
+
runId: executionContext.runId
|
|
1210
|
+
}) ?? { context: {} };
|
|
1211
|
+
const timeTravelParams = workflows.createTimeTravelExecutionParams({
|
|
1212
|
+
steps: timeTravel.steps.slice(1),
|
|
1213
|
+
inputData: timeTravel.inputData,
|
|
1214
|
+
resumeData: timeTravel.resumeData,
|
|
1215
|
+
context: timeTravel.nestedStepResults?.[step.id] ?? {},
|
|
1216
|
+
nestedStepsContext: timeTravel.nestedStepResults ?? {},
|
|
1217
|
+
snapshot,
|
|
1218
|
+
graph: step.buildExecutionGraph()
|
|
1219
|
+
});
|
|
1220
|
+
const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
|
|
1221
|
+
function: step.getFunction(),
|
|
1222
|
+
data: {
|
|
1223
|
+
timeTravel: timeTravelParams,
|
|
1224
|
+
initialState: executionContext.state ?? {},
|
|
1225
|
+
runId: executionContext.runId,
|
|
1226
|
+
outputOptions: { includeState: true }
|
|
1227
|
+
}
|
|
1228
|
+
});
|
|
1229
|
+
result = invokeResp.result;
|
|
1230
|
+
runId = invokeResp.runId;
|
|
1231
|
+
executionContext.state = invokeResp.result.state;
|
|
1032
1232
|
} else {
|
|
1033
1233
|
const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
|
|
1034
1234
|
function: step.getFunction(),
|
|
@@ -1089,12 +1289,12 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1089
1289
|
});
|
|
1090
1290
|
return { executionContext, result: { status: "failed", error: result?.error } };
|
|
1091
1291
|
} else if (result.status === "suspended") {
|
|
1092
|
-
const suspendedSteps = Object.entries(result.steps).filter(([_stepName,
|
|
1093
|
-
const stepRes2 =
|
|
1292
|
+
const suspendedSteps = Object.entries(result.steps).filter(([_stepName, stepResult2]) => {
|
|
1293
|
+
const stepRes2 = stepResult2;
|
|
1094
1294
|
return stepRes2?.status === "suspended";
|
|
1095
1295
|
});
|
|
1096
|
-
for (const [stepName,
|
|
1097
|
-
const suspendPath = [stepName, ...
|
|
1296
|
+
for (const [stepName, stepResult2] of suspendedSteps) {
|
|
1297
|
+
const suspendPath = [stepName, ...stepResult2?.suspendPayload?.__workflow_meta?.path ?? []];
|
|
1098
1298
|
executionContext.suspendedPaths[step.id] = executionContext.executionPath;
|
|
1099
1299
|
await emitter.emit("watch", {
|
|
1100
1300
|
type: "watch",
|
|
@@ -1102,9 +1302,9 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1102
1302
|
currentStep: {
|
|
1103
1303
|
id: step.id,
|
|
1104
1304
|
status: "suspended",
|
|
1105
|
-
payload:
|
|
1305
|
+
payload: stepResult2.payload,
|
|
1106
1306
|
suspendPayload: {
|
|
1107
|
-
...
|
|
1307
|
+
...stepResult2?.suspendPayload,
|
|
1108
1308
|
__workflow_meta: { runId, path: suspendPath }
|
|
1109
1309
|
}
|
|
1110
1310
|
},
|
|
@@ -1128,9 +1328,9 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1128
1328
|
executionContext,
|
|
1129
1329
|
result: {
|
|
1130
1330
|
status: "suspended",
|
|
1131
|
-
payload:
|
|
1331
|
+
payload: stepResult2.payload,
|
|
1132
1332
|
suspendPayload: {
|
|
1133
|
-
...
|
|
1333
|
+
...stepResult2?.suspendPayload,
|
|
1134
1334
|
__workflow_meta: { runId, path: suspendPath }
|
|
1135
1335
|
}
|
|
1136
1336
|
}
|
|
@@ -1197,7 +1397,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1197
1397
|
}
|
|
1198
1398
|
);
|
|
1199
1399
|
Object.assign(executionContext, res.executionContext);
|
|
1200
|
-
|
|
1400
|
+
const stepResult = {
|
|
1201
1401
|
...res.result,
|
|
1202
1402
|
startedAt,
|
|
1203
1403
|
endedAt: Date.now(),
|
|
@@ -1205,6 +1405,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1205
1405
|
resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
|
|
1206
1406
|
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
|
|
1207
1407
|
};
|
|
1408
|
+
return { result: stepResult, executionContextState: executionContext.state };
|
|
1208
1409
|
}
|
|
1209
1410
|
let stepRes;
|
|
1210
1411
|
try {
|
|
@@ -1212,6 +1413,21 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1212
1413
|
let execResults;
|
|
1213
1414
|
let suspended;
|
|
1214
1415
|
let bailed;
|
|
1416
|
+
const { resumeData: timeTravelResumeData, validationError: timeTravelResumeValidationError } = await workflows.validateStepResumeData({
|
|
1417
|
+
resumeData: timeTravel?.stepResults[step.id]?.status === "suspended" ? timeTravel?.resumeData : void 0,
|
|
1418
|
+
step
|
|
1419
|
+
});
|
|
1420
|
+
let resumeDataToUse;
|
|
1421
|
+
if (timeTravelResumeData && !timeTravelResumeValidationError) {
|
|
1422
|
+
resumeDataToUse = timeTravelResumeData;
|
|
1423
|
+
} else if (timeTravelResumeData && timeTravelResumeValidationError) {
|
|
1424
|
+
this.logger.warn("Time travel resume data validation failed", {
|
|
1425
|
+
stepId: step.id,
|
|
1426
|
+
error: timeTravelResumeValidationError.message
|
|
1427
|
+
});
|
|
1428
|
+
} else if (resume?.steps[0] === step.id) {
|
|
1429
|
+
resumeDataToUse = resume?.resumePayload;
|
|
1430
|
+
}
|
|
1215
1431
|
try {
|
|
1216
1432
|
if (validationError) {
|
|
1217
1433
|
throw validationError;
|
|
@@ -1226,7 +1442,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1226
1442
|
executionContext.state = state;
|
|
1227
1443
|
},
|
|
1228
1444
|
inputData,
|
|
1229
|
-
resumeData:
|
|
1445
|
+
resumeData: resumeDataToUse,
|
|
1230
1446
|
tracingContext: {
|
|
1231
1447
|
currentSpan: stepAISpan
|
|
1232
1448
|
},
|
|
@@ -1267,8 +1483,8 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1267
1483
|
startedAt,
|
|
1268
1484
|
endedAt,
|
|
1269
1485
|
payload: inputData,
|
|
1270
|
-
resumedAt:
|
|
1271
|
-
resumePayload:
|
|
1486
|
+
resumedAt: resumeDataToUse ? startedAt : void 0,
|
|
1487
|
+
resumePayload: resumeDataToUse
|
|
1272
1488
|
};
|
|
1273
1489
|
} catch (e) {
|
|
1274
1490
|
const stepFailure = {
|
|
@@ -1277,8 +1493,8 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1277
1493
|
error: e instanceof Error ? e.stack ?? e.message : String(e),
|
|
1278
1494
|
endedAt: Date.now(),
|
|
1279
1495
|
startedAt,
|
|
1280
|
-
resumedAt:
|
|
1281
|
-
resumePayload:
|
|
1496
|
+
resumedAt: resumeDataToUse ? startedAt : void 0,
|
|
1497
|
+
resumePayload: resumeDataToUse
|
|
1282
1498
|
};
|
|
1283
1499
|
execResults = stepFailure;
|
|
1284
1500
|
const fallbackErrorMessage = `Step ${step.id} failed`;
|
|
@@ -1294,8 +1510,8 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1294
1510
|
payload: inputData,
|
|
1295
1511
|
suspendedAt: Date.now(),
|
|
1296
1512
|
startedAt,
|
|
1297
|
-
resumedAt:
|
|
1298
|
-
resumePayload:
|
|
1513
|
+
resumedAt: resumeDataToUse ? startedAt : void 0,
|
|
1514
|
+
resumePayload: resumeDataToUse
|
|
1299
1515
|
};
|
|
1300
1516
|
} else if (bailed) {
|
|
1301
1517
|
execResults = {
|
|
@@ -1398,9 +1614,11 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1398
1614
|
});
|
|
1399
1615
|
}
|
|
1400
1616
|
Object.assign(executionContext.suspendedPaths, stepRes.executionContext.suspendedPaths);
|
|
1401
|
-
Object.assign(stepResults, stepRes.stepResults);
|
|
1402
1617
|
executionContext.state = stepRes.executionContext.state;
|
|
1403
|
-
return
|
|
1618
|
+
return {
|
|
1619
|
+
result: stepRes.result,
|
|
1620
|
+
executionContextState: stepRes.executionContext.state
|
|
1621
|
+
};
|
|
1404
1622
|
}
|
|
1405
1623
|
async persistStepUpdate({
|
|
1406
1624
|
workflowId,
|
|
@@ -1426,14 +1644,15 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1426
1644
|
resourceId,
|
|
1427
1645
|
snapshot: {
|
|
1428
1646
|
runId,
|
|
1647
|
+
status: workflowStatus,
|
|
1429
1648
|
value: executionContext.state,
|
|
1430
1649
|
context: stepResults,
|
|
1431
|
-
activePaths:
|
|
1650
|
+
activePaths: executionContext.executionPath,
|
|
1651
|
+
activeStepsPath: executionContext.activeStepsPath,
|
|
1432
1652
|
suspendedPaths: executionContext.suspendedPaths,
|
|
1433
1653
|
resumeLabels: executionContext.resumeLabels,
|
|
1434
1654
|
waitingPaths: {},
|
|
1435
1655
|
serializedStepGraph,
|
|
1436
|
-
status: workflowStatus,
|
|
1437
1656
|
result,
|
|
1438
1657
|
error,
|
|
1439
1658
|
// @ts-ignore
|
|
@@ -1449,6 +1668,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1449
1668
|
entry,
|
|
1450
1669
|
prevOutput,
|
|
1451
1670
|
stepResults,
|
|
1671
|
+
timeTravel,
|
|
1452
1672
|
resume,
|
|
1453
1673
|
executionContext,
|
|
1454
1674
|
emitter,
|
|
@@ -1559,10 +1779,12 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1559
1779
|
prevOutput,
|
|
1560
1780
|
stepResults,
|
|
1561
1781
|
resume,
|
|
1782
|
+
timeTravel,
|
|
1562
1783
|
executionContext: {
|
|
1563
1784
|
workflowId,
|
|
1564
1785
|
runId,
|
|
1565
1786
|
executionPath: [...executionContext.executionPath, index],
|
|
1787
|
+
activeStepsPath: executionContext.activeStepsPath,
|
|
1566
1788
|
suspendedPaths: executionContext.suspendedPaths,
|
|
1567
1789
|
resumeLabels: executionContext.resumeLabels,
|
|
1568
1790
|
retryConfig: executionContext.retryConfig,
|
|
@@ -1578,8 +1800,9 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1578
1800
|
currentSpan: conditionalSpan
|
|
1579
1801
|
}
|
|
1580
1802
|
});
|
|
1581
|
-
stepResults[step.step.id] = result;
|
|
1582
|
-
|
|
1803
|
+
stepResults[step.step.id] = result.result;
|
|
1804
|
+
executionContext.state = result.executionContextState;
|
|
1805
|
+
return result.result;
|
|
1583
1806
|
})
|
|
1584
1807
|
);
|
|
1585
1808
|
const hasFailed = results.find((result) => result.status === "failed");
|