@mastra/inngest 0.0.0-fix-fetching-workflow-snapshots-20250625000954 → 0.0.0-http-transporter-20250702160118

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/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 = Object.values(wfs).flatMap(wf => {
37
- if (wf instanceof InngestWorkflow) {
38
- wf.__registerMastra(mastra);
39
- return wf.getFunctions();
40
- }
41
- return [];
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,15 @@ 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' || runs?.[0]?.status === 'Cancelled') {
101
+ if (runs?.[0]?.status === 'Failed') {
102
+ console.log('run', runs?.[0]);
98
103
  throw new Error(`Function run ${runs?.[0]?.status}`);
104
+ } else if (runs?.[0]?.status === 'Cancelled') {
105
+ const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
106
+ workflowName: this.workflowId,
107
+ runId: this.runId,
108
+ });
109
+ return { output: { result: { steps: snapshot?.context, status: 'canceled' } } };
99
110
  }
100
111
  }
101
112
  return runs?.[0];
@@ -108,6 +119,30 @@ export class InngestRun<
108
119
  });
109
120
  }
110
121
 
122
+ async cancel() {
123
+ await this.inngest.send({
124
+ name: `cancel.workflow.${this.workflowId}`,
125
+ data: {
126
+ runId: this.runId,
127
+ },
128
+ });
129
+
130
+ const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
131
+ workflowName: this.workflowId,
132
+ runId: this.runId,
133
+ });
134
+ if (snapshot) {
135
+ await this.#mastra?.storage?.persistWorkflowSnapshot({
136
+ workflowName: this.workflowId,
137
+ runId: this.runId,
138
+ snapshot: {
139
+ ...snapshot,
140
+ status: 'canceled' as any,
141
+ },
142
+ });
143
+ }
144
+ }
145
+
111
146
  async start({
112
147
  inputData,
113
148
  }: {
@@ -147,7 +182,9 @@ export class InngestRun<
147
182
  result.error = new Error(result.error);
148
183
  }
149
184
 
150
- this.cleanup?.();
185
+ if (result.status !== 'suspended') {
186
+ this.cleanup?.();
187
+ }
151
188
  return result;
152
189
  }
153
190
 
@@ -432,23 +469,27 @@ export class InngestWorkflow<
432
469
 
433
470
  this.runs.set(runIdToUse, run);
434
471
 
435
- await this.mastra?.getStorage()?.persistWorkflowSnapshot({
436
- workflowName: this.id,
437
- runId: runIdToUse,
438
- snapshot: {
472
+ const workflowSnapshotInStorage = await this.getWorkflowRunExecutionResult(runIdToUse);
473
+
474
+ if (!workflowSnapshotInStorage) {
475
+ await this.mastra?.getStorage()?.persistWorkflowSnapshot({
476
+ workflowName: this.id,
439
477
  runId: runIdToUse,
440
- status: 'pending',
441
- value: {},
442
- context: {},
443
- activePaths: [],
444
- serializedStepGraph: this.serializedStepGraph,
445
- suspendedPaths: {},
446
- result: undefined,
447
- error: undefined,
448
- // @ts-ignore
449
- timestamp: Date.now(),
450
- },
451
- });
478
+ snapshot: {
479
+ runId: runIdToUse,
480
+ status: 'pending',
481
+ value: {},
482
+ context: {},
483
+ activePaths: [],
484
+ serializedStepGraph: this.serializedStepGraph,
485
+ suspendedPaths: {},
486
+ result: undefined,
487
+ error: undefined,
488
+ // @ts-ignore
489
+ timestamp: Date.now(),
490
+ },
491
+ });
492
+ }
452
493
 
453
494
  return run;
454
495
  }
@@ -458,8 +499,12 @@ export class InngestWorkflow<
458
499
  return this.function;
459
500
  }
460
501
  this.function = this.inngest.createFunction(
461
- // @ts-ignore
462
- { id: `workflow.${this.id}`, retries: this.retryConfig?.attempts ?? 0 },
502
+ {
503
+ id: `workflow.${this.id}`,
504
+ // @ts-ignore
505
+ retries: this.retryConfig?.attempts ?? 0,
506
+ cancelOn: [{ event: `cancel.workflow.${this.id}` }],
507
+ },
463
508
  { event: `workflow.${this.id}` },
464
509
  async ({ event, step, attempt, publish }) => {
465
510
  let { inputData, runId, resume } = event.data;
@@ -508,6 +553,7 @@ export class InngestWorkflow<
508
553
  retryConfig: this.retryConfig,
509
554
  runtimeContext: new RuntimeContext(), // TODO
510
555
  resume,
556
+ abortController: new AbortController(),
511
557
  });
512
558
 
513
559
  return { result, runId };
@@ -630,7 +676,7 @@ export function createStep<
630
676
  outputSchema: z.object({
631
677
  text: z.string(),
632
678
  }),
633
- execute: async ({ inputData, [EMITTER_SYMBOL]: emitter, runtimeContext }) => {
679
+ execute: async ({ inputData, [EMITTER_SYMBOL]: emitter, runtimeContext, abortSignal, abort }) => {
634
680
  let streamPromise = {} as {
635
681
  promise: Promise<string>;
636
682
  resolve: (value: string) => void;
@@ -656,8 +702,13 @@ export function createStep<
656
702
  onFinish: result => {
657
703
  streamPromise.resolve(result.text);
658
704
  },
705
+ abortSignal,
659
706
  });
660
707
 
708
+ if (abortSignal.aborted) {
709
+ return abort();
710
+ }
711
+
661
712
  for await (const chunk of fullStream) {
662
713
  switch (chunk.type) {
663
714
  case 'text-delta':
@@ -815,6 +866,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
815
866
  delay?: number;
816
867
  };
817
868
  runtimeContext: RuntimeContext;
869
+ abortController: AbortController;
818
870
  }): Promise<TOutput> {
819
871
  await params.emitter.emit('watch-v2', {
820
872
  type: 'start',
@@ -914,6 +966,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
914
966
  resume,
915
967
  prevOutput,
916
968
  emitter,
969
+ abortController,
917
970
  runtimeContext,
918
971
  }: {
919
972
  workflowId: string;
@@ -927,6 +980,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
927
980
  };
928
981
  prevOutput: any;
929
982
  emitter: Emitter;
983
+ abortController: AbortController;
930
984
  runtimeContext: RuntimeContext;
931
985
  }): Promise<StepResult<any, any, any, any>> {
932
986
  return super.executeStep({
@@ -938,6 +992,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
938
992
  resume,
939
993
  prevOutput,
940
994
  emitter,
995
+ abortController,
941
996
  runtimeContext,
942
997
  });
943
998
  }
@@ -966,17 +1021,12 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
966
1021
  resume,
967
1022
  prevOutput,
968
1023
  emitter,
1024
+ abortController,
969
1025
  runtimeContext,
970
1026
  }: {
971
1027
  step: Step<string, any, any>;
972
1028
  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
- };
1029
+ executionContext: ExecutionContext;
980
1030
  resume?: {
981
1031
  steps: string[];
982
1032
  resumePayload: any;
@@ -984,6 +1034,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
984
1034
  };
985
1035
  prevOutput: any;
986
1036
  emitter: Emitter;
1037
+ abortController: AbortController;
987
1038
  runtimeContext: RuntimeContext;
988
1039
  }): Promise<StepResult<any, any, any, any>> {
989
1040
  const startedAt = await this.inngestStep.run(
@@ -1016,6 +1067,9 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
1016
1067
  type: 'step-start',
1017
1068
  payload: {
1018
1069
  id: step.id,
1070
+ status: 'running',
1071
+ payload: prevOutput,
1072
+ startedAt,
1019
1073
  },
1020
1074
  });
1021
1075
 
@@ -1091,6 +1145,8 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
1091
1145
  payload: {
1092
1146
  id: step.id,
1093
1147
  status: 'failed',
1148
+ error: result?.error,
1149
+ payload: prevOutput,
1094
1150
  },
1095
1151
  });
1096
1152
 
@@ -1128,6 +1184,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
1128
1184
  type: 'step-suspended',
1129
1185
  payload: {
1130
1186
  id: step.id,
1187
+ status: 'suspended',
1131
1188
  },
1132
1189
  });
1133
1190
 
@@ -1187,6 +1244,15 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
1187
1244
  eventTimestamp: Date.now(),
1188
1245
  });
1189
1246
 
1247
+ await emitter.emit('watch-v2', {
1248
+ type: 'step-result',
1249
+ payload: {
1250
+ id: step.id,
1251
+ status: 'success',
1252
+ output: result?.result,
1253
+ },
1254
+ });
1255
+
1190
1256
  await emitter.emit('watch-v2', {
1191
1257
  type: 'step-finish',
1192
1258
  payload: {
@@ -1241,6 +1307,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
1241
1307
  engine: {
1242
1308
  step: this.inngestStep,
1243
1309
  },
1310
+ abortSignal: abortController.signal,
1244
1311
  });
1245
1312
  const endedAt = Date.now();
1246
1313
 
@@ -1307,8 +1374,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
1307
1374
  type: 'step-suspended',
1308
1375
  payload: {
1309
1376
  id: step.id,
1310
- status: execResults.status,
1311
- output: execResults.status === 'success' ? execResults?.output : undefined,
1377
+ ...execResults,
1312
1378
  },
1313
1379
  });
1314
1380
  } else {
@@ -1316,8 +1382,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
1316
1382
  type: 'step-result',
1317
1383
  payload: {
1318
1384
  id: step.id,
1319
- status: execResults.status,
1320
- output: execResults.status === 'success' ? execResults?.output : undefined,
1385
+ ...execResults,
1321
1386
  },
1322
1387
  });
1323
1388
 
@@ -1396,6 +1461,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
1396
1461
  resume,
1397
1462
  executionContext,
1398
1463
  emitter,
1464
+ abortController,
1399
1465
  runtimeContext,
1400
1466
  }: {
1401
1467
  workflowId: string;
@@ -1417,6 +1483,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
1417
1483
  };
1418
1484
  executionContext: ExecutionContext;
1419
1485
  emitter: Emitter;
1486
+ abortController: AbortController;
1420
1487
  runtimeContext: RuntimeContext;
1421
1488
  }): Promise<StepResult<any, any, any, any>> {
1422
1489
  let execResults: any;
@@ -1429,6 +1496,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
1429
1496
  runId,
1430
1497
  mastra: this.mastra!,
1431
1498
  runtimeContext,
1499
+ runCount: -1,
1432
1500
  inputData: prevOutput,
1433
1501
  getInitData: () => stepResults?.input as any,
1434
1502
  getStepResult: (step: any) => {
@@ -1447,10 +1515,14 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
1447
1515
  // TODO: this function shouldn't have suspend probably?
1448
1516
  suspend: async (_suspendPayload: any) => {},
1449
1517
  bail: () => {},
1518
+ abort: () => {
1519
+ abortController.abort();
1520
+ },
1450
1521
  [EMITTER_SYMBOL]: emitter,
1451
1522
  engine: {
1452
1523
  step: this.inngestStep,
1453
1524
  },
1525
+ abortSignal: abortController.signal,
1454
1526
  });
1455
1527
  return result ? index : null;
1456
1528
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -1482,6 +1554,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
1482
1554
  executionSpan: executionContext.executionSpan,
1483
1555
  },
1484
1556
  emitter,
1557
+ abortController,
1485
1558
  runtimeContext,
1486
1559
  }),
1487
1560
  ),
package/vitest.config.ts CHANGED
@@ -4,5 +4,11 @@ export default defineConfig({
4
4
  test: {
5
5
  globals: true,
6
6
  include: ['src/**/*.test.ts'],
7
+ pool: 'threads',
8
+ poolOptions: {
9
+ threads: {
10
+ singleThread: true,
11
+ },
12
+ },
7
13
  },
8
14
  });