@mastra/inngest 0.11.2 → 0.11.3-alpha.0

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.
@@ -1,23 +1,23 @@
1
1
 
2
- > @mastra/inngest@0.11.2-alpha.0 build /home/runner/work/mastra/mastra/workflows/inngest
2
+ > @mastra/inngest@0.11.3-alpha.0 build /home/runner/work/mastra/mastra/workflows/inngest
3
3
  > tsup src/index.ts --format esm,cjs --experimental-dts --clean --treeshake=smallest --splitting
4
4
 
5
5
  CLI Building entry: src/index.ts
6
6
  CLI Using tsconfig: tsconfig.json
7
7
  CLI tsup v8.5.0
8
8
  TSC Build start
9
- TSC ⚡️ Build success in 9062ms
9
+ TSC ⚡️ Build success in 8949ms
10
10
  DTS Build start
11
11
  CLI Target: es2022
12
12
  Analysis will use the bundled TypeScript version 5.8.3
13
13
  Writing package typings: /home/runner/work/mastra/mastra/workflows/inngest/dist/_tsup-dts-rollup.d.ts
14
14
  Analysis will use the bundled TypeScript version 5.8.3
15
15
  Writing package typings: /home/runner/work/mastra/mastra/workflows/inngest/dist/_tsup-dts-rollup.d.cts
16
- DTS ⚡️ Build success in 5920ms
16
+ DTS ⚡️ Build success in 6476ms
17
17
  CLI Cleaning output folder
18
18
  ESM Build start
19
19
  CJS Build start
20
- CJS dist/index.cjs 34.63 KB
21
- CJS ⚡️ Build success in 316ms
22
- ESM dist/index.js 34.43 KB
23
- ESM ⚡️ Build success in 316ms
20
+ CJS dist/index.cjs 37.25 KB
21
+ CJS ⚡️ Build success in 268ms
22
+ ESM dist/index.js 37.03 KB
23
+ ESM ⚡️ Build success in 268ms
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @mastra/inngest
2
2
 
3
+ ## 0.11.3-alpha.0
4
+
5
+ ### Patch Changes
6
+
7
+ - b790fd1: Ability to pass a function to .sleep()/.sleepUntil()
8
+ - Updated dependencies [f8ce2cc]
9
+ - Updated dependencies [8c846b6]
10
+ - Updated dependencies [b790fd1]
11
+ - Updated dependencies [d7ed04d]
12
+ - Updated dependencies [f36e4f1]
13
+ - @mastra/core@0.10.11-alpha.0
14
+
3
15
  ## 0.11.2
4
16
 
5
17
  ### Patch Changes
@@ -109,9 +109,53 @@ export declare class InngestExecutionEngine extends DefaultExecutionEngine {
109
109
  abortController: AbortController;
110
110
  runtimeContext: RuntimeContext;
111
111
  }): Promise<StepResult<any, any, any, any>>;
112
- executeSleep({ id, duration }: {
113
- id: string;
114
- duration: number;
112
+ executeSleep({ workflowId, runId, entry, prevOutput, stepResults, emitter, abortController, runtimeContext, }: {
113
+ workflowId: string;
114
+ runId: string;
115
+ serializedStepGraph: SerializedStepFlowEntry[];
116
+ entry: {
117
+ type: 'sleep';
118
+ id: string;
119
+ duration?: number;
120
+ fn?: ExecuteFunction<any, any, any, any, InngestEngineType>;
121
+ };
122
+ prevStep: StepFlowEntry;
123
+ prevOutput: any;
124
+ stepResults: Record<string, StepResult<any, any, any, any>>;
125
+ resume?: {
126
+ steps: string[];
127
+ stepResults: Record<string, StepResult<any, any, any, any>>;
128
+ resumePayload: any;
129
+ resumePath: number[];
130
+ };
131
+ executionContext: ExecutionContext;
132
+ emitter: Emitter;
133
+ abortController: AbortController;
134
+ runtimeContext: RuntimeContext;
135
+ }): Promise<void>;
136
+ executeSleepUntil({ workflowId, runId, entry, prevOutput, stepResults, emitter, abortController, runtimeContext, }: {
137
+ workflowId: string;
138
+ runId: string;
139
+ serializedStepGraph: SerializedStepFlowEntry[];
140
+ entry: {
141
+ type: 'sleepUntil';
142
+ id: string;
143
+ date?: Date;
144
+ fn?: ExecuteFunction<any, any, any, any, InngestEngineType>;
145
+ };
146
+ prevStep: StepFlowEntry;
147
+ prevOutput: any;
148
+ stepResults: Record<string, StepResult<any, any, any, any>>;
149
+ resume?: {
150
+ steps: string[];
151
+ stepResults: Record<string, StepResult<any, any, any, any>>;
152
+ resumePayload: any;
153
+ resumePath: number[];
154
+ };
155
+ executionContext: ExecutionContext;
156
+ emitter: Emitter;
157
+ abortController: AbortController;
158
+ runtimeContext: RuntimeContext;
115
159
  }): Promise<void>;
116
160
  executeWaitForEvent({ event, timeout }: {
117
161
  event: string;
@@ -109,9 +109,53 @@ export declare class InngestExecutionEngine extends DefaultExecutionEngine {
109
109
  abortController: AbortController;
110
110
  runtimeContext: RuntimeContext;
111
111
  }): Promise<StepResult<any, any, any, any>>;
112
- executeSleep({ id, duration }: {
113
- id: string;
114
- duration: number;
112
+ executeSleep({ workflowId, runId, entry, prevOutput, stepResults, emitter, abortController, runtimeContext, }: {
113
+ workflowId: string;
114
+ runId: string;
115
+ serializedStepGraph: SerializedStepFlowEntry[];
116
+ entry: {
117
+ type: 'sleep';
118
+ id: string;
119
+ duration?: number;
120
+ fn?: ExecuteFunction<any, any, any, any, InngestEngineType>;
121
+ };
122
+ prevStep: StepFlowEntry;
123
+ prevOutput: any;
124
+ stepResults: Record<string, StepResult<any, any, any, any>>;
125
+ resume?: {
126
+ steps: string[];
127
+ stepResults: Record<string, StepResult<any, any, any, any>>;
128
+ resumePayload: any;
129
+ resumePath: number[];
130
+ };
131
+ executionContext: ExecutionContext;
132
+ emitter: Emitter;
133
+ abortController: AbortController;
134
+ runtimeContext: RuntimeContext;
135
+ }): Promise<void>;
136
+ executeSleepUntil({ workflowId, runId, entry, prevOutput, stepResults, emitter, abortController, runtimeContext, }: {
137
+ workflowId: string;
138
+ runId: string;
139
+ serializedStepGraph: SerializedStepFlowEntry[];
140
+ entry: {
141
+ type: 'sleepUntil';
142
+ id: string;
143
+ date?: Date;
144
+ fn?: ExecuteFunction<any, any, any, any, InngestEngineType>;
145
+ };
146
+ prevStep: StepFlowEntry;
147
+ prevOutput: any;
148
+ stepResults: Record<string, StepResult<any, any, any, any>>;
149
+ resume?: {
150
+ steps: string[];
151
+ stepResults: Record<string, StepResult<any, any, any, any>>;
152
+ resumePayload: any;
153
+ resumePath: number[];
154
+ };
155
+ executionContext: ExecutionContext;
156
+ emitter: Emitter;
157
+ abortController: AbortController;
158
+ runtimeContext: RuntimeContext;
115
159
  }): Promise<void>;
116
160
  executeWaitForEvent({ event, timeout }: {
117
161
  event: string;
package/dist/index.cjs CHANGED
@@ -665,8 +665,103 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
665
665
  runtimeContext
666
666
  });
667
667
  }
668
- async executeSleep({ id, duration }) {
669
- await this.inngestStep.sleep(id, duration);
668
+ // async executeSleep({ id, duration }: { id: string; duration: number }): Promise<void> {
669
+ // await this.inngestStep.sleep(id, duration);
670
+ // }
671
+ async executeSleep({
672
+ workflowId,
673
+ runId,
674
+ entry,
675
+ prevOutput,
676
+ stepResults,
677
+ emitter,
678
+ abortController,
679
+ runtimeContext
680
+ }) {
681
+ let { duration, fn } = entry;
682
+ if (fn) {
683
+ duration = await this.inngestStep.run(`workflow.${workflowId}.sleep.${entry.id}`, async () => {
684
+ return await fn({
685
+ runId,
686
+ mastra: this.mastra,
687
+ runtimeContext,
688
+ inputData: prevOutput,
689
+ runCount: -1,
690
+ getInitData: () => stepResults?.input,
691
+ getStepResult: (step) => {
692
+ if (!step?.id) {
693
+ return null;
694
+ }
695
+ const result = stepResults[step.id];
696
+ if (result?.status === "success") {
697
+ return result.output;
698
+ }
699
+ return null;
700
+ },
701
+ // TODO: this function shouldn't have suspend probably?
702
+ suspend: async (_suspendPayload) => {
703
+ },
704
+ bail: () => {
705
+ },
706
+ abort: () => {
707
+ abortController?.abort();
708
+ },
709
+ [_constants.EMITTER_SYMBOL]: emitter,
710
+ engine: { step: this.inngestStep },
711
+ abortSignal: abortController?.signal
712
+ });
713
+ });
714
+ }
715
+ await this.inngestStep.sleep(entry.id, !duration || duration < 0 ? 0 : duration);
716
+ }
717
+ async executeSleepUntil({
718
+ workflowId,
719
+ runId,
720
+ entry,
721
+ prevOutput,
722
+ stepResults,
723
+ emitter,
724
+ abortController,
725
+ runtimeContext
726
+ }) {
727
+ let { date, fn } = entry;
728
+ if (fn) {
729
+ date = await this.inngestStep.run(`workflow.${workflowId}.sleepUntil.${entry.id}`, async () => {
730
+ return await fn({
731
+ runId,
732
+ mastra: this.mastra,
733
+ runtimeContext,
734
+ inputData: prevOutput,
735
+ runCount: -1,
736
+ getInitData: () => stepResults?.input,
737
+ getStepResult: (step) => {
738
+ if (!step?.id) {
739
+ return null;
740
+ }
741
+ const result = stepResults[step.id];
742
+ if (result?.status === "success") {
743
+ return result.output;
744
+ }
745
+ return null;
746
+ },
747
+ // TODO: this function shouldn't have suspend probably?
748
+ suspend: async (_suspendPayload) => {
749
+ },
750
+ bail: () => {
751
+ },
752
+ abort: () => {
753
+ abortController?.abort();
754
+ },
755
+ [_constants.EMITTER_SYMBOL]: emitter,
756
+ engine: { step: this.inngestStep },
757
+ abortSignal: abortController?.signal
758
+ });
759
+ });
760
+ }
761
+ if (!(date instanceof Date)) {
762
+ return;
763
+ }
764
+ await this.inngestStep.sleepUntil(entry.id, date);
670
765
  }
671
766
  async executeWaitForEvent({ event, timeout }) {
672
767
  const eventData = await this.inngestStep.waitForEvent(`user-event-${event}`, {
package/dist/index.js CHANGED
@@ -663,8 +663,103 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
663
663
  runtimeContext
664
664
  });
665
665
  }
666
- async executeSleep({ id, duration }) {
667
- await this.inngestStep.sleep(id, duration);
666
+ // async executeSleep({ id, duration }: { id: string; duration: number }): Promise<void> {
667
+ // await this.inngestStep.sleep(id, duration);
668
+ // }
669
+ async executeSleep({
670
+ workflowId,
671
+ runId,
672
+ entry,
673
+ prevOutput,
674
+ stepResults,
675
+ emitter,
676
+ abortController,
677
+ runtimeContext
678
+ }) {
679
+ let { duration, fn } = entry;
680
+ if (fn) {
681
+ duration = await this.inngestStep.run(`workflow.${workflowId}.sleep.${entry.id}`, async () => {
682
+ return await fn({
683
+ runId,
684
+ mastra: this.mastra,
685
+ runtimeContext,
686
+ inputData: prevOutput,
687
+ runCount: -1,
688
+ getInitData: () => stepResults?.input,
689
+ getStepResult: (step) => {
690
+ if (!step?.id) {
691
+ return null;
692
+ }
693
+ const result = stepResults[step.id];
694
+ if (result?.status === "success") {
695
+ return result.output;
696
+ }
697
+ return null;
698
+ },
699
+ // TODO: this function shouldn't have suspend probably?
700
+ suspend: async (_suspendPayload) => {
701
+ },
702
+ bail: () => {
703
+ },
704
+ abort: () => {
705
+ abortController?.abort();
706
+ },
707
+ [EMITTER_SYMBOL]: emitter,
708
+ engine: { step: this.inngestStep },
709
+ abortSignal: abortController?.signal
710
+ });
711
+ });
712
+ }
713
+ await this.inngestStep.sleep(entry.id, !duration || duration < 0 ? 0 : duration);
714
+ }
715
+ async executeSleepUntil({
716
+ workflowId,
717
+ runId,
718
+ entry,
719
+ prevOutput,
720
+ stepResults,
721
+ emitter,
722
+ abortController,
723
+ runtimeContext
724
+ }) {
725
+ let { date, fn } = entry;
726
+ if (fn) {
727
+ date = await this.inngestStep.run(`workflow.${workflowId}.sleepUntil.${entry.id}`, async () => {
728
+ return await fn({
729
+ runId,
730
+ mastra: this.mastra,
731
+ runtimeContext,
732
+ inputData: prevOutput,
733
+ runCount: -1,
734
+ getInitData: () => stepResults?.input,
735
+ getStepResult: (step) => {
736
+ if (!step?.id) {
737
+ return null;
738
+ }
739
+ const result = stepResults[step.id];
740
+ if (result?.status === "success") {
741
+ return result.output;
742
+ }
743
+ return null;
744
+ },
745
+ // TODO: this function shouldn't have suspend probably?
746
+ suspend: async (_suspendPayload) => {
747
+ },
748
+ bail: () => {
749
+ },
750
+ abort: () => {
751
+ abortController?.abort();
752
+ },
753
+ [EMITTER_SYMBOL]: emitter,
754
+ engine: { step: this.inngestStep },
755
+ abortSignal: abortController?.signal
756
+ });
757
+ });
758
+ }
759
+ if (!(date instanceof Date)) {
760
+ return;
761
+ }
762
+ await this.inngestStep.sleepUntil(entry.id, date);
668
763
  }
669
764
  async executeWaitForEvent({ event, timeout }) {
670
765
  const eventData = await this.inngestStep.waitForEvent(`user-event-${event}`, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mastra/inngest",
3
- "version": "0.11.2",
3
+ "version": "0.11.3-alpha.0",
4
4
  "description": "Mastra Inngest integration",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -39,9 +39,9 @@
39
39
  "typescript": "^5.8.3",
40
40
  "vitest": "^3.2.4",
41
41
  "@internal/lint": "0.0.17",
42
+ "@mastra/core": "0.10.11-alpha.0",
42
43
  "@mastra/libsql": "0.11.0",
43
- "@mastra/deployer": "0.10.10",
44
- "@mastra/core": "0.10.10"
44
+ "@mastra/deployer": "0.10.11-alpha.0"
45
45
  },
46
46
  "peerDependencies": {
47
47
  "@mastra/core": ">=0.10.9-0 <0.11.0-0"
package/src/index.test.ts CHANGED
@@ -367,7 +367,7 @@ describe('MastraInngestWorkflow', () => {
367
367
  srv.close();
368
368
  });
369
369
 
370
- it('should execute a a sleep step', async ctx => {
370
+ it('should execute a sleep step', async ctx => {
371
371
  const inngest = new Inngest({
372
372
  id: 'mastra',
373
373
  baseUrl: `http://localhost:${(ctx as any).inngestPort}`,
@@ -455,6 +455,100 @@ describe('MastraInngestWorkflow', () => {
455
455
  srv.close();
456
456
  });
457
457
 
458
+ it('should execute a sleep step with fn parameter', async ctx => {
459
+ const inngest = new Inngest({
460
+ id: 'mastra',
461
+ baseUrl: `http://localhost:${(ctx as any).inngestPort}`,
462
+ });
463
+
464
+ const { createWorkflow, createStep } = init(inngest);
465
+
466
+ const execute = vi.fn<any>().mockResolvedValue({ value: 1000 });
467
+ const step1 = createStep({
468
+ id: 'step1',
469
+ execute,
470
+ inputSchema: z.object({}),
471
+ outputSchema: z.object({ value: z.number() }),
472
+ });
473
+ const step2 = createStep({
474
+ id: 'step2',
475
+ execute: async ({ inputData }) => {
476
+ return { value: inputData.value + 1000 };
477
+ },
478
+ inputSchema: z.object({ value: z.number() }),
479
+ outputSchema: z.object({ value: z.number() }),
480
+ });
481
+
482
+ const workflow = createWorkflow({
483
+ id: 'test-workflow',
484
+ inputSchema: z.object({}),
485
+ outputSchema: z.object({
486
+ value: z.number(),
487
+ }),
488
+ steps: [step1],
489
+ });
490
+
491
+ workflow
492
+ .then(step1)
493
+ .sleep(async ({ inputData }) => {
494
+ return inputData.value;
495
+ })
496
+ .then(step2)
497
+ .commit();
498
+
499
+ const mastra = new Mastra({
500
+ storage: new DefaultStorage({
501
+ url: ':memory:',
502
+ }),
503
+ workflows: {
504
+ 'test-workflow': workflow,
505
+ },
506
+ server: {
507
+ apiRoutes: [
508
+ {
509
+ path: '/inngest/api',
510
+ method: 'ALL',
511
+ createHandler: async ({ mastra }) => inngestServe({ mastra, inngest }),
512
+ },
513
+ ],
514
+ },
515
+ });
516
+
517
+ const app = await createHonoServer(mastra);
518
+
519
+ const srv = (globServer = serve({
520
+ fetch: app.fetch,
521
+ port: (ctx as any).handlerPort,
522
+ }));
523
+ await resetInngest();
524
+
525
+ const run = await workflow.createRunAsync();
526
+ const startTime = Date.now();
527
+ const result = await run.start({ inputData: {} });
528
+ const endTime = Date.now();
529
+
530
+ expect(execute).toHaveBeenCalled();
531
+ expect(result.steps['step1']).toMatchObject({
532
+ status: 'success',
533
+ output: { value: 1000 },
534
+ // payload: {},
535
+ // startedAt: expect.any(Number),
536
+ // endedAt: expect.any(Number),
537
+ });
538
+
539
+ expect(result.steps['step2']).toMatchObject({
540
+ status: 'success',
541
+ output: { value: 2000 },
542
+ // payload: { result: 'success' },
543
+ // startedAt: expect.any(Number),
544
+ // endedAt: expect.any(Number),
545
+ });
546
+
547
+ expect(endTime - startTime).toBeGreaterThan(1000);
548
+
549
+ srv.close();
550
+ });
551
+
458
552
  it('should execute a a sleep until step', async ctx => {
459
553
  const inngest = new Inngest({
460
554
  id: 'mastra',
@@ -547,6 +641,100 @@ describe('MastraInngestWorkflow', () => {
547
641
  srv.close();
548
642
  });
549
643
 
644
+ it('should execute a sleep until step with fn parameter', async ctx => {
645
+ const inngest = new Inngest({
646
+ id: 'mastra',
647
+ baseUrl: `http://localhost:${(ctx as any).inngestPort}`,
648
+ });
649
+
650
+ const { createWorkflow, createStep } = init(inngest);
651
+
652
+ const execute = vi.fn<any>().mockResolvedValue({ value: 1000 });
653
+ const step1 = createStep({
654
+ id: 'step1',
655
+ execute,
656
+ inputSchema: z.object({}),
657
+ outputSchema: z.object({ value: z.number() }),
658
+ });
659
+ const step2 = createStep({
660
+ id: 'step2',
661
+ execute: async ({ inputData }) => {
662
+ return { value: inputData.value + 1000 };
663
+ },
664
+ inputSchema: z.object({ value: z.number() }),
665
+ outputSchema: z.object({ value: z.number() }),
666
+ });
667
+
668
+ const workflow = createWorkflow({
669
+ id: 'test-workflow',
670
+ inputSchema: z.object({}),
671
+ outputSchema: z.object({
672
+ value: z.number(),
673
+ }),
674
+ steps: [step1],
675
+ });
676
+
677
+ workflow
678
+ .then(step1)
679
+ .sleepUntil(async ({ inputData }) => {
680
+ return new Date(Date.now() + inputData.value);
681
+ })
682
+ .then(step2)
683
+ .commit();
684
+
685
+ const mastra = new Mastra({
686
+ storage: new DefaultStorage({
687
+ url: ':memory:',
688
+ }),
689
+ workflows: {
690
+ 'test-workflow': workflow,
691
+ },
692
+ server: {
693
+ apiRoutes: [
694
+ {
695
+ path: '/inngest/api',
696
+ method: 'ALL',
697
+ createHandler: async ({ mastra }) => inngestServe({ mastra, inngest }),
698
+ },
699
+ ],
700
+ },
701
+ });
702
+
703
+ const app = await createHonoServer(mastra);
704
+
705
+ const srv = (globServer = serve({
706
+ fetch: app.fetch,
707
+ port: (ctx as any).handlerPort,
708
+ }));
709
+ await resetInngest();
710
+
711
+ const run = await workflow.createRunAsync();
712
+ const startTime = Date.now();
713
+ const result = await run.start({ inputData: {} });
714
+ const endTime = Date.now();
715
+
716
+ expect(execute).toHaveBeenCalled();
717
+ expect(result.steps['step1']).toMatchObject({
718
+ status: 'success',
719
+ output: { value: 1000 },
720
+ // payload: {},
721
+ // startedAt: expect.any(Number),
722
+ // endedAt: expect.any(Number),
723
+ });
724
+
725
+ expect(result.steps['step2']).toMatchObject({
726
+ status: 'success',
727
+ output: { value: 2000 },
728
+ // payload: { result: 'success' },
729
+ // startedAt: expect.any(Number),
730
+ // endedAt: expect.any(Number),
731
+ });
732
+
733
+ expect(endTime - startTime).toBeGreaterThan(1000);
734
+
735
+ srv.close();
736
+ });
737
+
550
738
  it('should execute a a waitForEvent step', async ctx => {
551
739
  const inngest = new Inngest({
552
740
  id: 'mastra',
@@ -6473,6 +6661,215 @@ describe('MastraInngestWorkflow', () => {
6473
6661
  });
6474
6662
  });
6475
6663
 
6664
+ it('should handle basic sleep waiting flow with fn parameter', async ctx => {
6665
+ const inngest = new Inngest({
6666
+ id: 'mastra',
6667
+ baseUrl: `http://localhost:${(ctx as any).inngestPort}`,
6668
+ middleware: [realtimeMiddleware()],
6669
+ });
6670
+
6671
+ const { createWorkflow, createStep } = init(inngest);
6672
+
6673
+ const step1Action = vi.fn<any>().mockResolvedValue({ value: 1000 });
6674
+ const step2Action = vi.fn<any>().mockResolvedValue({ value: 2000 });
6675
+
6676
+ const step1 = createStep({
6677
+ id: 'step1',
6678
+ execute: step1Action,
6679
+ inputSchema: z.object({}),
6680
+ outputSchema: z.object({ value: z.number() }),
6681
+ });
6682
+ const step2 = createStep({
6683
+ id: 'step2',
6684
+ execute: step2Action,
6685
+ inputSchema: z.object({ value: z.number() }),
6686
+ outputSchema: z.object({}),
6687
+ });
6688
+
6689
+ const workflow = createWorkflow({
6690
+ id: 'test-workflow',
6691
+ inputSchema: z.object({}),
6692
+ outputSchema: z.object({}),
6693
+ steps: [step1, step2],
6694
+ });
6695
+ workflow
6696
+ .then(step1)
6697
+ .sleep(async ({ inputData }) => {
6698
+ return inputData.value;
6699
+ })
6700
+ .then(step2)
6701
+ .commit();
6702
+
6703
+ const mastra = new Mastra({
6704
+ storage: new DefaultStorage({
6705
+ url: ':memory:',
6706
+ }),
6707
+ workflows: {
6708
+ 'test-workflow': workflow,
6709
+ },
6710
+ server: {
6711
+ apiRoutes: [
6712
+ {
6713
+ path: '/inngest/api',
6714
+ method: 'ALL',
6715
+ createHandler: async ({ mastra }) => inngestServe({ mastra, inngest }),
6716
+ },
6717
+ ],
6718
+ },
6719
+ });
6720
+
6721
+ const app = await createHonoServer(mastra);
6722
+
6723
+ const srv = (globServer = serve({
6724
+ fetch: app.fetch,
6725
+ port: (ctx as any).handlerPort,
6726
+ }));
6727
+ await resetInngest();
6728
+
6729
+ const runId = 'test-run-id';
6730
+ let watchData: StreamEvent[] = [];
6731
+ const run = await workflow.createRunAsync({
6732
+ runId,
6733
+ });
6734
+
6735
+ await resetInngest();
6736
+
6737
+ const { stream, getWorkflowState } = run.stream({ inputData: {} });
6738
+
6739
+ // Start watching the workflow
6740
+ const collectedStreamData: StreamEvent[] = [];
6741
+ for await (const data of stream) {
6742
+ collectedStreamData.push(JSON.parse(JSON.stringify(data)));
6743
+ }
6744
+ watchData = collectedStreamData;
6745
+
6746
+ const executionResult = await getWorkflowState();
6747
+
6748
+ await resetInngest();
6749
+
6750
+ srv.close();
6751
+
6752
+ expect(watchData.length).toBe(11);
6753
+ expect(watchData).toMatchObject([
6754
+ {
6755
+ payload: {
6756
+ runId: 'test-run-id',
6757
+ },
6758
+ type: 'start',
6759
+ },
6760
+ {
6761
+ payload: {
6762
+ id: 'step1',
6763
+ startedAt: expect.any(Number),
6764
+ status: 'running',
6765
+ payload: {},
6766
+ },
6767
+ type: 'step-start',
6768
+ },
6769
+ {
6770
+ payload: {
6771
+ id: 'step1',
6772
+ output: {
6773
+ value: 1000,
6774
+ },
6775
+ endedAt: expect.any(Number),
6776
+ status: 'success',
6777
+ },
6778
+ type: 'step-result',
6779
+ },
6780
+ {
6781
+ payload: {
6782
+ id: 'step1',
6783
+ metadata: {},
6784
+ },
6785
+ type: 'step-finish',
6786
+ },
6787
+ {
6788
+ payload: {
6789
+ id: expect.any(String),
6790
+ startedAt: expect.any(Number),
6791
+ status: 'waiting',
6792
+ payload: {
6793
+ value: 1000,
6794
+ },
6795
+ },
6796
+ type: 'step-waiting',
6797
+ },
6798
+ {
6799
+ payload: {
6800
+ id: expect.any(String),
6801
+ endedAt: expect.any(Number),
6802
+ startedAt: expect.any(Number),
6803
+ status: 'success',
6804
+ output: {
6805
+ value: 1000,
6806
+ },
6807
+ },
6808
+ type: 'step-result',
6809
+ },
6810
+ {
6811
+ type: 'step-finish',
6812
+ payload: {
6813
+ id: expect.any(String),
6814
+ metadata: {},
6815
+ },
6816
+ },
6817
+ {
6818
+ payload: {
6819
+ id: 'step2',
6820
+ payload: {
6821
+ value: 1000,
6822
+ },
6823
+ startedAt: expect.any(Number),
6824
+ status: 'running',
6825
+ },
6826
+ type: 'step-start',
6827
+ },
6828
+ {
6829
+ payload: {
6830
+ id: 'step2',
6831
+ output: {
6832
+ value: 2000,
6833
+ },
6834
+ endedAt: expect.any(Number),
6835
+ status: 'success',
6836
+ },
6837
+ type: 'step-result',
6838
+ },
6839
+ {
6840
+ payload: {
6841
+ id: 'step2',
6842
+ metadata: {},
6843
+ },
6844
+ type: 'step-finish',
6845
+ },
6846
+ {
6847
+ payload: {
6848
+ runId: 'test-run-id',
6849
+ },
6850
+ type: 'finish',
6851
+ },
6852
+ ]);
6853
+
6854
+ // Verify execution completed successfully
6855
+ expect(executionResult.steps.step1).toMatchObject({
6856
+ status: 'success',
6857
+ output: { value: 1000 },
6858
+ payload: {},
6859
+ startedAt: expect.any(Number),
6860
+ endedAt: expect.any(Number),
6861
+ });
6862
+ expect(executionResult.steps.step2).toMatchObject({
6863
+ status: 'success',
6864
+ output: { value: 2000 },
6865
+ payload: {
6866
+ value: 1000,
6867
+ },
6868
+ startedAt: expect.any(Number),
6869
+ endedAt: expect.any(Number),
6870
+ });
6871
+ });
6872
+
6476
6873
  it('should handle waitForEvent waiting flow', async ctx => {
6477
6874
  const inngest = new Inngest({
6478
6875
  id: 'mastra',
package/src/index.ts CHANGED
@@ -997,8 +997,158 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
997
997
  });
998
998
  }
999
999
 
1000
- async executeSleep({ id, duration }: { id: string; duration: number }): Promise<void> {
1001
- await this.inngestStep.sleep(id, duration);
1000
+ // async executeSleep({ id, duration }: { id: string; duration: number }): Promise<void> {
1001
+ // await this.inngestStep.sleep(id, duration);
1002
+ // }
1003
+
1004
+ async executeSleep({
1005
+ workflowId,
1006
+ runId,
1007
+ entry,
1008
+ prevOutput,
1009
+ stepResults,
1010
+ emitter,
1011
+ abortController,
1012
+ runtimeContext,
1013
+ }: {
1014
+ workflowId: string;
1015
+ runId: string;
1016
+ serializedStepGraph: SerializedStepFlowEntry[];
1017
+ entry: {
1018
+ type: 'sleep';
1019
+ id: string;
1020
+ duration?: number;
1021
+ fn?: ExecuteFunction<any, any, any, any, InngestEngineType>;
1022
+ };
1023
+ prevStep: StepFlowEntry;
1024
+ prevOutput: any;
1025
+ stepResults: Record<string, StepResult<any, any, any, any>>;
1026
+ resume?: {
1027
+ steps: string[];
1028
+ stepResults: Record<string, StepResult<any, any, any, any>>;
1029
+ resumePayload: any;
1030
+ resumePath: number[];
1031
+ };
1032
+ executionContext: ExecutionContext;
1033
+ emitter: Emitter;
1034
+ abortController: AbortController;
1035
+ runtimeContext: RuntimeContext;
1036
+ }): Promise<void> {
1037
+ let { duration, fn } = entry;
1038
+
1039
+ if (fn) {
1040
+ duration = await this.inngestStep.run(`workflow.${workflowId}.sleep.${entry.id}`, async () => {
1041
+ return await fn({
1042
+ runId,
1043
+ mastra: this.mastra!,
1044
+ runtimeContext,
1045
+ inputData: prevOutput,
1046
+ runCount: -1,
1047
+ getInitData: () => stepResults?.input as any,
1048
+ getStepResult: (step: any) => {
1049
+ if (!step?.id) {
1050
+ return null;
1051
+ }
1052
+
1053
+ const result = stepResults[step.id];
1054
+ if (result?.status === 'success') {
1055
+ return result.output;
1056
+ }
1057
+
1058
+ return null;
1059
+ },
1060
+
1061
+ // TODO: this function shouldn't have suspend probably?
1062
+ suspend: async (_suspendPayload: any): Promise<any> => {},
1063
+ bail: () => {},
1064
+ abort: () => {
1065
+ abortController?.abort();
1066
+ },
1067
+ [EMITTER_SYMBOL]: emitter,
1068
+ engine: { step: this.inngestStep },
1069
+ abortSignal: abortController?.signal,
1070
+ });
1071
+ });
1072
+ }
1073
+
1074
+ await this.inngestStep.sleep(entry.id, !duration || duration < 0 ? 0 : duration);
1075
+ }
1076
+
1077
+ async executeSleepUntil({
1078
+ workflowId,
1079
+ runId,
1080
+ entry,
1081
+ prevOutput,
1082
+ stepResults,
1083
+ emitter,
1084
+ abortController,
1085
+ runtimeContext,
1086
+ }: {
1087
+ workflowId: string;
1088
+ runId: string;
1089
+ serializedStepGraph: SerializedStepFlowEntry[];
1090
+ entry: {
1091
+ type: 'sleepUntil';
1092
+ id: string;
1093
+ date?: Date;
1094
+ fn?: ExecuteFunction<any, any, any, any, InngestEngineType>;
1095
+ };
1096
+ prevStep: StepFlowEntry;
1097
+ prevOutput: any;
1098
+ stepResults: Record<string, StepResult<any, any, any, any>>;
1099
+ resume?: {
1100
+ steps: string[];
1101
+ stepResults: Record<string, StepResult<any, any, any, any>>;
1102
+ resumePayload: any;
1103
+ resumePath: number[];
1104
+ };
1105
+ executionContext: ExecutionContext;
1106
+ emitter: Emitter;
1107
+ abortController: AbortController;
1108
+ runtimeContext: RuntimeContext;
1109
+ }): Promise<void> {
1110
+ let { date, fn } = entry;
1111
+
1112
+ if (fn) {
1113
+ date = await this.inngestStep.run(`workflow.${workflowId}.sleepUntil.${entry.id}`, async () => {
1114
+ return await fn({
1115
+ runId,
1116
+ mastra: this.mastra!,
1117
+ runtimeContext,
1118
+ inputData: prevOutput,
1119
+ runCount: -1,
1120
+ getInitData: () => stepResults?.input as any,
1121
+ getStepResult: (step: any) => {
1122
+ if (!step?.id) {
1123
+ return null;
1124
+ }
1125
+
1126
+ const result = stepResults[step.id];
1127
+ if (result?.status === 'success') {
1128
+ return result.output;
1129
+ }
1130
+
1131
+ return null;
1132
+ },
1133
+
1134
+ // TODO: this function shouldn't have suspend probably?
1135
+ suspend: async (_suspendPayload: any): Promise<any> => {},
1136
+ bail: () => {},
1137
+ abort: () => {
1138
+ abortController?.abort();
1139
+ },
1140
+ [EMITTER_SYMBOL]: emitter,
1141
+ engine: { step: this.inngestStep },
1142
+ abortSignal: abortController?.signal,
1143
+ });
1144
+ });
1145
+ }
1146
+
1147
+ if (!(date instanceof Date)) {
1148
+ return;
1149
+ }
1150
+
1151
+ await this.inngestStep.sleepUntil(entry.id, date);
1002
1152
  }
1003
1153
 
1004
1154
  async executeWaitForEvent({ event, timeout }: { event: string; timeout?: number }): Promise<any> {