@mastra/inngest 0.11.0 → 0.11.1
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/.turbo/turbo-build.log +7 -7
- package/CHANGELOG.md +52 -0
- package/dist/_tsup-dts-rollup.d.cts +9 -13
- package/dist/_tsup-dts-rollup.d.ts +9 -13
- package/dist/index.cjs +106 -39
- package/dist/index.js +106 -39
- package/package.json +7 -7
- package/src/index.test.ts +257 -52
- package/src/index.ts +109 -39
package/src/index.ts
CHANGED
|
@@ -33,13 +33,17 @@ export type InngestEngineType = {
|
|
|
33
33
|
|
|
34
34
|
export function serve({ mastra, inngest }: { mastra: Mastra; inngest: Inngest }): ReturnType<typeof inngestServe> {
|
|
35
35
|
const wfs = mastra.getWorkflows();
|
|
36
|
-
const functions =
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
36
|
+
const functions = Array.from(
|
|
37
|
+
new Set(
|
|
38
|
+
Object.values(wfs).flatMap(wf => {
|
|
39
|
+
if (wf instanceof InngestWorkflow) {
|
|
40
|
+
wf.__registerMastra(mastra);
|
|
41
|
+
return wf.getFunctions();
|
|
42
|
+
}
|
|
43
|
+
return [];
|
|
44
|
+
}),
|
|
45
|
+
),
|
|
46
|
+
);
|
|
43
47
|
return inngestServe({
|
|
44
48
|
client: inngest,
|
|
45
49
|
functions,
|
|
@@ -94,8 +98,14 @@ export class InngestRun<
|
|
|
94
98
|
while (runs?.[0]?.status !== 'Completed' || runs?.[0]?.event_id !== eventId) {
|
|
95
99
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
96
100
|
runs = await this.getRuns(eventId);
|
|
97
|
-
if (runs?.[0]?.status === 'Failed'
|
|
101
|
+
if (runs?.[0]?.status === 'Failed') {
|
|
98
102
|
throw new Error(`Function run ${runs?.[0]?.status}`);
|
|
103
|
+
} else if (runs?.[0]?.status === 'Cancelled') {
|
|
104
|
+
const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
|
|
105
|
+
workflowName: this.workflowId,
|
|
106
|
+
runId: this.runId,
|
|
107
|
+
});
|
|
108
|
+
return { output: { result: { steps: snapshot?.context, status: 'canceled' } } };
|
|
99
109
|
}
|
|
100
110
|
}
|
|
101
111
|
return runs?.[0];
|
|
@@ -108,6 +118,30 @@ export class InngestRun<
|
|
|
108
118
|
});
|
|
109
119
|
}
|
|
110
120
|
|
|
121
|
+
async cancel() {
|
|
122
|
+
await this.inngest.send({
|
|
123
|
+
name: `cancel.workflow.${this.workflowId}`,
|
|
124
|
+
data: {
|
|
125
|
+
runId: this.runId,
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
|
|
130
|
+
workflowName: this.workflowId,
|
|
131
|
+
runId: this.runId,
|
|
132
|
+
});
|
|
133
|
+
if (snapshot) {
|
|
134
|
+
await this.#mastra?.storage?.persistWorkflowSnapshot({
|
|
135
|
+
workflowName: this.workflowId,
|
|
136
|
+
runId: this.runId,
|
|
137
|
+
snapshot: {
|
|
138
|
+
...snapshot,
|
|
139
|
+
status: 'canceled' as any,
|
|
140
|
+
},
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
111
145
|
async start({
|
|
112
146
|
inputData,
|
|
113
147
|
}: {
|
|
@@ -147,7 +181,9 @@ export class InngestRun<
|
|
|
147
181
|
result.error = new Error(result.error);
|
|
148
182
|
}
|
|
149
183
|
|
|
150
|
-
|
|
184
|
+
if (result.status !== 'suspended') {
|
|
185
|
+
this.cleanup?.();
|
|
186
|
+
}
|
|
151
187
|
return result;
|
|
152
188
|
}
|
|
153
189
|
|
|
@@ -432,23 +468,27 @@ export class InngestWorkflow<
|
|
|
432
468
|
|
|
433
469
|
this.runs.set(runIdToUse, run);
|
|
434
470
|
|
|
435
|
-
await this.
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
471
|
+
const workflowSnapshotInStorage = await this.getWorkflowRunExecutionResult(runIdToUse);
|
|
472
|
+
|
|
473
|
+
if (!workflowSnapshotInStorage) {
|
|
474
|
+
await this.mastra?.getStorage()?.persistWorkflowSnapshot({
|
|
475
|
+
workflowName: this.id,
|
|
439
476
|
runId: runIdToUse,
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
477
|
+
snapshot: {
|
|
478
|
+
runId: runIdToUse,
|
|
479
|
+
status: 'pending',
|
|
480
|
+
value: {},
|
|
481
|
+
context: {},
|
|
482
|
+
activePaths: [],
|
|
483
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
484
|
+
suspendedPaths: {},
|
|
485
|
+
result: undefined,
|
|
486
|
+
error: undefined,
|
|
487
|
+
// @ts-ignore
|
|
488
|
+
timestamp: Date.now(),
|
|
489
|
+
},
|
|
490
|
+
});
|
|
491
|
+
}
|
|
452
492
|
|
|
453
493
|
return run;
|
|
454
494
|
}
|
|
@@ -458,8 +498,12 @@ export class InngestWorkflow<
|
|
|
458
498
|
return this.function;
|
|
459
499
|
}
|
|
460
500
|
this.function = this.inngest.createFunction(
|
|
461
|
-
|
|
462
|
-
|
|
501
|
+
{
|
|
502
|
+
id: `workflow.${this.id}`,
|
|
503
|
+
// @ts-ignore
|
|
504
|
+
retries: this.retryConfig?.attempts ?? 0,
|
|
505
|
+
cancelOn: [{ event: `cancel.workflow.${this.id}` }],
|
|
506
|
+
},
|
|
463
507
|
{ event: `workflow.${this.id}` },
|
|
464
508
|
async ({ event, step, attempt, publish }) => {
|
|
465
509
|
let { inputData, runId, resume } = event.data;
|
|
@@ -508,6 +552,7 @@ export class InngestWorkflow<
|
|
|
508
552
|
retryConfig: this.retryConfig,
|
|
509
553
|
runtimeContext: new RuntimeContext(), // TODO
|
|
510
554
|
resume,
|
|
555
|
+
abortController: new AbortController(),
|
|
511
556
|
});
|
|
512
557
|
|
|
513
558
|
return { result, runId };
|
|
@@ -630,7 +675,7 @@ export function createStep<
|
|
|
630
675
|
outputSchema: z.object({
|
|
631
676
|
text: z.string(),
|
|
632
677
|
}),
|
|
633
|
-
execute: async ({ inputData, [EMITTER_SYMBOL]: emitter, runtimeContext }) => {
|
|
678
|
+
execute: async ({ inputData, [EMITTER_SYMBOL]: emitter, runtimeContext, abortSignal, abort }) => {
|
|
634
679
|
let streamPromise = {} as {
|
|
635
680
|
promise: Promise<string>;
|
|
636
681
|
resolve: (value: string) => void;
|
|
@@ -656,8 +701,13 @@ export function createStep<
|
|
|
656
701
|
onFinish: result => {
|
|
657
702
|
streamPromise.resolve(result.text);
|
|
658
703
|
},
|
|
704
|
+
abortSignal,
|
|
659
705
|
});
|
|
660
706
|
|
|
707
|
+
if (abortSignal.aborted) {
|
|
708
|
+
return abort();
|
|
709
|
+
}
|
|
710
|
+
|
|
661
711
|
for await (const chunk of fullStream) {
|
|
662
712
|
switch (chunk.type) {
|
|
663
713
|
case 'text-delta':
|
|
@@ -815,6 +865,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
815
865
|
delay?: number;
|
|
816
866
|
};
|
|
817
867
|
runtimeContext: RuntimeContext;
|
|
868
|
+
abortController: AbortController;
|
|
818
869
|
}): Promise<TOutput> {
|
|
819
870
|
await params.emitter.emit('watch-v2', {
|
|
820
871
|
type: 'start',
|
|
@@ -914,6 +965,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
914
965
|
resume,
|
|
915
966
|
prevOutput,
|
|
916
967
|
emitter,
|
|
968
|
+
abortController,
|
|
917
969
|
runtimeContext,
|
|
918
970
|
}: {
|
|
919
971
|
workflowId: string;
|
|
@@ -927,6 +979,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
927
979
|
};
|
|
928
980
|
prevOutput: any;
|
|
929
981
|
emitter: Emitter;
|
|
982
|
+
abortController: AbortController;
|
|
930
983
|
runtimeContext: RuntimeContext;
|
|
931
984
|
}): Promise<StepResult<any, any, any, any>> {
|
|
932
985
|
return super.executeStep({
|
|
@@ -938,6 +991,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
938
991
|
resume,
|
|
939
992
|
prevOutput,
|
|
940
993
|
emitter,
|
|
994
|
+
abortController,
|
|
941
995
|
runtimeContext,
|
|
942
996
|
});
|
|
943
997
|
}
|
|
@@ -966,17 +1020,12 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
966
1020
|
resume,
|
|
967
1021
|
prevOutput,
|
|
968
1022
|
emitter,
|
|
1023
|
+
abortController,
|
|
969
1024
|
runtimeContext,
|
|
970
1025
|
}: {
|
|
971
1026
|
step: Step<string, any, any>;
|
|
972
1027
|
stepResults: Record<string, StepResult<any, any, any, any>>;
|
|
973
|
-
executionContext:
|
|
974
|
-
workflowId: string;
|
|
975
|
-
runId: string;
|
|
976
|
-
executionPath: number[];
|
|
977
|
-
suspendedPaths: Record<string, number[]>;
|
|
978
|
-
retryConfig: { attempts: number; delay: number };
|
|
979
|
-
};
|
|
1028
|
+
executionContext: ExecutionContext;
|
|
980
1029
|
resume?: {
|
|
981
1030
|
steps: string[];
|
|
982
1031
|
resumePayload: any;
|
|
@@ -984,6 +1033,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
984
1033
|
};
|
|
985
1034
|
prevOutput: any;
|
|
986
1035
|
emitter: Emitter;
|
|
1036
|
+
abortController: AbortController;
|
|
987
1037
|
runtimeContext: RuntimeContext;
|
|
988
1038
|
}): Promise<StepResult<any, any, any, any>> {
|
|
989
1039
|
const startedAt = await this.inngestStep.run(
|
|
@@ -1016,6 +1066,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
1016
1066
|
type: 'step-start',
|
|
1017
1067
|
payload: {
|
|
1018
1068
|
id: step.id,
|
|
1069
|
+
status: 'running',
|
|
1019
1070
|
},
|
|
1020
1071
|
});
|
|
1021
1072
|
|
|
@@ -1091,6 +1142,8 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
1091
1142
|
payload: {
|
|
1092
1143
|
id: step.id,
|
|
1093
1144
|
status: 'failed',
|
|
1145
|
+
error: result?.error,
|
|
1146
|
+
payload: prevOutput,
|
|
1094
1147
|
},
|
|
1095
1148
|
});
|
|
1096
1149
|
|
|
@@ -1128,6 +1181,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
1128
1181
|
type: 'step-suspended',
|
|
1129
1182
|
payload: {
|
|
1130
1183
|
id: step.id,
|
|
1184
|
+
status: 'suspended',
|
|
1131
1185
|
},
|
|
1132
1186
|
});
|
|
1133
1187
|
|
|
@@ -1187,6 +1241,15 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
1187
1241
|
eventTimestamp: Date.now(),
|
|
1188
1242
|
});
|
|
1189
1243
|
|
|
1244
|
+
await emitter.emit('watch-v2', {
|
|
1245
|
+
type: 'step-result',
|
|
1246
|
+
payload: {
|
|
1247
|
+
id: step.id,
|
|
1248
|
+
status: 'success',
|
|
1249
|
+
output: result?.result,
|
|
1250
|
+
},
|
|
1251
|
+
});
|
|
1252
|
+
|
|
1190
1253
|
await emitter.emit('watch-v2', {
|
|
1191
1254
|
type: 'step-finish',
|
|
1192
1255
|
payload: {
|
|
@@ -1241,6 +1304,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
1241
1304
|
engine: {
|
|
1242
1305
|
step: this.inngestStep,
|
|
1243
1306
|
},
|
|
1307
|
+
abortSignal: abortController.signal,
|
|
1244
1308
|
});
|
|
1245
1309
|
const endedAt = Date.now();
|
|
1246
1310
|
|
|
@@ -1307,8 +1371,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
1307
1371
|
type: 'step-suspended',
|
|
1308
1372
|
payload: {
|
|
1309
1373
|
id: step.id,
|
|
1310
|
-
|
|
1311
|
-
output: execResults.status === 'success' ? execResults?.output : undefined,
|
|
1374
|
+
...execResults,
|
|
1312
1375
|
},
|
|
1313
1376
|
});
|
|
1314
1377
|
} else {
|
|
@@ -1316,8 +1379,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
1316
1379
|
type: 'step-result',
|
|
1317
1380
|
payload: {
|
|
1318
1381
|
id: step.id,
|
|
1319
|
-
|
|
1320
|
-
output: execResults.status === 'success' ? execResults?.output : undefined,
|
|
1382
|
+
...execResults,
|
|
1321
1383
|
},
|
|
1322
1384
|
});
|
|
1323
1385
|
|
|
@@ -1396,6 +1458,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
1396
1458
|
resume,
|
|
1397
1459
|
executionContext,
|
|
1398
1460
|
emitter,
|
|
1461
|
+
abortController,
|
|
1399
1462
|
runtimeContext,
|
|
1400
1463
|
}: {
|
|
1401
1464
|
workflowId: string;
|
|
@@ -1417,6 +1480,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
1417
1480
|
};
|
|
1418
1481
|
executionContext: ExecutionContext;
|
|
1419
1482
|
emitter: Emitter;
|
|
1483
|
+
abortController: AbortController;
|
|
1420
1484
|
runtimeContext: RuntimeContext;
|
|
1421
1485
|
}): Promise<StepResult<any, any, any, any>> {
|
|
1422
1486
|
let execResults: any;
|
|
@@ -1429,6 +1493,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
1429
1493
|
runId,
|
|
1430
1494
|
mastra: this.mastra!,
|
|
1431
1495
|
runtimeContext,
|
|
1496
|
+
runCount: -1,
|
|
1432
1497
|
inputData: prevOutput,
|
|
1433
1498
|
getInitData: () => stepResults?.input as any,
|
|
1434
1499
|
getStepResult: (step: any) => {
|
|
@@ -1447,10 +1512,14 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
1447
1512
|
// TODO: this function shouldn't have suspend probably?
|
|
1448
1513
|
suspend: async (_suspendPayload: any) => {},
|
|
1449
1514
|
bail: () => {},
|
|
1515
|
+
abort: () => {
|
|
1516
|
+
abortController.abort();
|
|
1517
|
+
},
|
|
1450
1518
|
[EMITTER_SYMBOL]: emitter,
|
|
1451
1519
|
engine: {
|
|
1452
1520
|
step: this.inngestStep,
|
|
1453
1521
|
},
|
|
1522
|
+
abortSignal: abortController.signal,
|
|
1454
1523
|
});
|
|
1455
1524
|
return result ? index : null;
|
|
1456
1525
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
@@ -1482,6 +1551,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
1482
1551
|
executionSpan: executionContext.executionSpan,
|
|
1483
1552
|
},
|
|
1484
1553
|
emitter,
|
|
1554
|
+
abortController,
|
|
1485
1555
|
runtimeContext,
|
|
1486
1556
|
}),
|
|
1487
1557
|
),
|