@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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +9 -0
- package/dist/index.cjs +10 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +7 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -2
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
- package/src/index.test.ts +176 -0
- package/src/index.ts +39 -3
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:
|
|
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,
|