@mastra/inngest 0.12.3-alpha.0 → 0.12.3-alpha.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/src/index.test.ts CHANGED
@@ -7904,4 +7904,180 @@ describe('MastraInngestWorkflow', () => {
7904
7904
  });
7905
7905
  });
7906
7906
  });
7907
+
7908
+ describe.sequential('Flow Control Configuration', () => {
7909
+ it('should accept workflow configuration with flow control properties', async ctx => {
7910
+ const inngest = new Inngest({
7911
+ id: 'mastra-flow-control',
7912
+ baseUrl: `http://localhost:${(ctx as any).inngestPort}`,
7913
+ middleware: [realtimeMiddleware()],
7914
+ });
7915
+
7916
+ const { createWorkflow, createStep } = init(inngest);
7917
+
7918
+ const step1 = createStep({
7919
+ id: 'step1',
7920
+ execute: async ({ inputData }) => {
7921
+ return { result: 'step1: ' + inputData.value };
7922
+ },
7923
+ inputSchema: z.object({ value: z.string() }),
7924
+ outputSchema: z.object({ result: z.string() }),
7925
+ });
7926
+
7927
+ // Test workflow with flow control configuration
7928
+ const workflow = createWorkflow({
7929
+ id: 'flow-control-test',
7930
+ inputSchema: z.object({ value: z.string() }),
7931
+ outputSchema: z.object({ result: z.string() }),
7932
+ steps: [step1],
7933
+ // Flow control properties
7934
+ concurrency: {
7935
+ limit: 5,
7936
+ key: 'event.data.userId',
7937
+ },
7938
+ rateLimit: {
7939
+ period: '1h',
7940
+ limit: 100,
7941
+ },
7942
+ priority: {
7943
+ run: 'event.data.priority ?? 50',
7944
+ },
7945
+ });
7946
+
7947
+ expect(workflow).toBeDefined();
7948
+ expect(workflow.id).toBe('flow-control-test');
7949
+
7950
+ // Verify that function creation includes flow control config
7951
+ const inngestFunction = workflow.getFunction();
7952
+ expect(inngestFunction).toBeDefined();
7953
+ });
7954
+
7955
+ it('should handle workflow configuration with partial flow control properties', async ctx => {
7956
+ const inngest = new Inngest({
7957
+ id: 'mastra-partial-flow-control',
7958
+ baseUrl: `http://localhost:${(ctx as any).inngestPort}`,
7959
+ middleware: [realtimeMiddleware()],
7960
+ });
7961
+
7962
+ const { createWorkflow, createStep } = init(inngest);
7963
+
7964
+ const step1 = createStep({
7965
+ id: 'step1',
7966
+ execute: async ({ inputData }) => {
7967
+ return { result: 'step1: ' + inputData.value };
7968
+ },
7969
+ inputSchema: z.object({ value: z.string() }),
7970
+ outputSchema: z.object({ result: z.string() }),
7971
+ });
7972
+
7973
+ // Test workflow with only some flow control properties
7974
+ const workflow = createWorkflow({
7975
+ id: 'partial-flow-control-test',
7976
+ inputSchema: z.object({ value: z.string() }),
7977
+ outputSchema: z.object({ result: z.string() }),
7978
+ steps: [step1],
7979
+ // Only concurrency control
7980
+ concurrency: {
7981
+ limit: 10,
7982
+ },
7983
+ });
7984
+
7985
+ expect(workflow).toBeDefined();
7986
+ expect(workflow.id).toBe('partial-flow-control-test');
7987
+
7988
+ const inngestFunction = workflow.getFunction();
7989
+ expect(inngestFunction).toBeDefined();
7990
+ });
7991
+
7992
+ it('should handle workflow configuration without flow control properties (backward compatibility)', async ctx => {
7993
+ const inngest = new Inngest({
7994
+ id: 'mastra-backward-compat',
7995
+ baseUrl: `http://localhost:${(ctx as any).inngestPort}`,
7996
+ middleware: [realtimeMiddleware()],
7997
+ });
7998
+
7999
+ const { createWorkflow, createStep } = init(inngest);
8000
+
8001
+ const step1 = createStep({
8002
+ id: 'step1',
8003
+ execute: async ({ inputData }) => {
8004
+ return { result: 'step1: ' + inputData.value };
8005
+ },
8006
+ inputSchema: z.object({ value: z.string() }),
8007
+ outputSchema: z.object({ result: z.string() }),
8008
+ });
8009
+
8010
+ // Test workflow without any flow control properties (existing behavior)
8011
+ const workflow = createWorkflow({
8012
+ id: 'backward-compat-test',
8013
+ inputSchema: z.object({ value: z.string() }),
8014
+ outputSchema: z.object({ result: z.string() }),
8015
+ steps: [step1],
8016
+ retryConfig: {
8017
+ attempts: 3,
8018
+ delay: 1000,
8019
+ },
8020
+ });
8021
+
8022
+ expect(workflow).toBeDefined();
8023
+ expect(workflow.id).toBe('backward-compat-test');
8024
+
8025
+ const inngestFunction = workflow.getFunction();
8026
+ expect(inngestFunction).toBeDefined();
8027
+ });
8028
+
8029
+ it('should support all flow control configuration types', async ctx => {
8030
+ const inngest = new Inngest({
8031
+ id: 'mastra-all-flow-control',
8032
+ baseUrl: `http://localhost:${(ctx as any).inngestPort}`,
8033
+ middleware: [realtimeMiddleware()],
8034
+ });
8035
+
8036
+ const { createWorkflow, createStep } = init(inngest);
8037
+
8038
+ const step1 = createStep({
8039
+ id: 'step1',
8040
+ execute: async ({ inputData }) => {
8041
+ return { result: 'step1: ' + inputData.value };
8042
+ },
8043
+ inputSchema: z.object({ value: z.string() }),
8044
+ outputSchema: z.object({ result: z.string() }),
8045
+ });
8046
+
8047
+ // Test workflow with all flow control configuration types
8048
+ const workflow = createWorkflow({
8049
+ id: 'all-flow-control-test',
8050
+ inputSchema: z.object({ value: z.string() }),
8051
+ outputSchema: z.object({ result: z.string() }),
8052
+ steps: [step1],
8053
+ // All flow control properties
8054
+ concurrency: {
8055
+ limit: 5,
8056
+ key: 'event.data.userId',
8057
+ },
8058
+ rateLimit: {
8059
+ period: '1m',
8060
+ limit: 10,
8061
+ },
8062
+ throttle: {
8063
+ period: '10s',
8064
+ limit: 1,
8065
+ key: 'event.data.organizationId',
8066
+ },
8067
+ debounce: {
8068
+ period: '5s',
8069
+ key: 'event.data.messageId',
8070
+ },
8071
+ priority: {
8072
+ run: 'event.data.priority ?? 0',
8073
+ },
8074
+ });
8075
+
8076
+ expect(workflow).toBeDefined();
8077
+ expect(workflow.id).toBe('all-flow-control-test');
8078
+
8079
+ const inngestFunction = workflow.getFunction();
8080
+ expect(inngestFunction).toBeDefined();
8081
+ });
8082
+ });
7907
8083
  }, 40e3);
package/src/index.ts CHANGED
@@ -33,6 +33,30 @@ import type { Inngest, BaseContext } from 'inngest';
33
33
  import { serve as inngestServe } from 'inngest/hono';
34
34
  import { z } from 'zod';
35
35
 
36
+ // Extract Inngest's native flow control configuration types
37
+ type InngestCreateFunctionConfig = Parameters<Inngest['createFunction']>[0];
38
+
39
+ // Extract specific flow control properties (excluding batching)
40
+ export type InngestFlowControlConfig = Pick<
41
+ InngestCreateFunctionConfig,
42
+ 'concurrency' | 'rateLimit' | 'throttle' | 'debounce' | 'priority'
43
+ >;
44
+
45
+ // Union type for Inngest workflows with flow control
46
+ export type InngestWorkflowConfig<
47
+ TWorkflowId extends string = string,
48
+ TInput extends z.ZodType<any> = z.ZodType<any>,
49
+ TOutput extends z.ZodType<any> = z.ZodType<any>,
50
+ TSteps extends Step<string, any, any, any, any, any>[] = Step<string, any, any, any, any, any>[],
51
+ > = WorkflowConfig<TWorkflowId, TInput, TOutput, TSteps> & InngestFlowControlConfig;
52
+
53
+ // Compile-time compatibility assertion
54
+ type _AssertInngestCompatibility =
55
+ InngestFlowControlConfig extends Pick<Parameters<Inngest['createFunction']>[0], keyof InngestFlowControlConfig>
56
+ ? true
57
+ : never;
58
+ const _compatibilityCheck: _AssertInngestCompatibility = true;
59
+
36
60
  export type InngestEngineType = {
37
61
  step: any;
38
62
  };
@@ -342,9 +366,19 @@ export class InngestWorkflow<
342
366
  public inngest: Inngest;
343
367
 
344
368
  private function: ReturnType<Inngest['createFunction']> | undefined;
369
+ private readonly flowControlConfig?: InngestFlowControlConfig;
370
+
371
+ constructor(params: InngestWorkflowConfig<TWorkflowId, TInput, TOutput, TSteps>, inngest: Inngest) {
372
+ const { concurrency, rateLimit, throttle, debounce, priority, ...workflowParams } = params;
373
+
374
+ super(workflowParams as WorkflowConfig<TWorkflowId, TInput, TOutput, TSteps>);
375
+
376
+ const flowControlEntries = Object.entries({ concurrency, rateLimit, throttle, debounce, priority }).filter(
377
+ ([_, value]) => value !== undefined,
378
+ );
379
+
380
+ this.flowControlConfig = flowControlEntries.length > 0 ? Object.fromEntries(flowControlEntries) : undefined;
345
381
 
346
- constructor(params: WorkflowConfig<TWorkflowId, TInput, TOutput, TSteps>, inngest: Inngest) {
347
- super(params);
348
382
  this.#mastra = params.mastra!;
349
383
  this.inngest = inngest;
350
384
  }
@@ -513,6 +547,8 @@ export class InngestWorkflow<
513
547
  // @ts-ignore
514
548
  retries: this.retryConfig?.attempts ?? 0,
515
549
  cancelOn: [{ event: `cancel.workflow.${this.id}` }],
550
+ // Spread flow control configuration
551
+ ...this.flowControlConfig,
516
552
  },
517
553
  { event: `workflow.${this.id}` },
518
554
  async ({ event, step, attempt, publish }) => {
@@ -801,7 +837,7 @@ export function init(inngest: Inngest) {
801
837
  any,
802
838
  InngestEngineType
803
839
  >[],
804
- >(params: WorkflowConfig<TWorkflowId, TInput, TOutput, TSteps>) {
840
+ >(params: InngestWorkflowConfig<TWorkflowId, TInput, TOutput, TSteps>) {
805
841
  return new InngestWorkflow<InngestEngineType, TSteps, TWorkflowId, TInput, TOutput, TInput>(params, inngest);
806
842
  },
807
843
  createStep,