feat(workflows-sdk): Allow when then in parallelize (#11756)

**What**
Update typings to allow using when then inside parallelize
This commit is contained in:
Adrien de Peretti authored and GitHub committed 2025-03-06 13:23:37 +00:00
1 parent 3b470f4142
commit 84f991192e
5 files changed
+80 -4

No files matched your search

+6
View File
@@ -0,0 +1,6 @@
---
"@medusajs/core-flows": patch
"@medusajs/workflows-sdk": patch
---
feat(workflows-sdk): Allow when then in parallelize
@@ -19,7 +19,8 @@ import { updateProductsWorkflow } from "./update-products"
/** /**
* The products to manage. * The products to manage.
*/ */
export interface BatchProductWorkflowInput extends BatchWorkflowInput< export interface BatchProductWorkflowInput
extends BatchWorkflowInput<
CreateProductWorkflowInputDTO, CreateProductWorkflowInputDTO,
UpdateProductWorkflowInputDTO UpdateProductWorkflowInputDTO
> {} > {}
@@ -19,10 +19,12 @@ import {
StepFunction, StepFunction,
StepResponse, StepResponse,
transform, transform,
when,
WorkflowResponse, WorkflowResponse,
} from ".." } from ".."
import { MedusaWorkflow } from "../../../medusa-workflow" import { MedusaWorkflow } from "../../../medusa-workflow"
import { createHook } from "../create-hook" import { createHook } from "../create-hook"
import { setTimeout } from "timers/promises"
jest.setTimeout(30000) jest.setTimeout(30000)
@@ -742,6 +744,71 @@ describe("Workflow composer", function () {
}) })
}) })
it("should compose a new workflow with conditional parallelized steps", async () => {
const stepResults: string[] = []
const mockStep1Fn = jest.fn().mockImplementation(async () => {
await setTimeout(100)
stepResults.push("step1")
return new StepResponse(true)
}) as any
const mockStep2Fn = jest.fn().mockImplementation(() => {
stepResults.push("step2")
return new StepResponse(true)
}) as any
const mockStep3Fn = jest.fn().mockImplementation(() => {
stepResults.push("step3")
return new StepResponse(true)
}) as any
const mockStep4Fn = jest.fn().mockImplementation(() => {
stepResults.push("step4")
return new StepResponse(true)
}) as any
const step1 = createStep("step1", mockStep1Fn)
const step2 = createStep("step2", mockStep2Fn)
const step3 = createStep("step3", mockStep3Fn)
const step4 = createStep("step4", mockStep4Fn)
const callStep2IfNeeded = () => {
return when({}, () => false).then(() => {
return step2()
})
}
const callStep3IfNeeded = () => {
return when({}, () => false).then(() => {
return step4()
})
}
const workflow = createWorkflow("workflow1", function (input) {
const [ret1, ret2, ret3, ret4] = parallelize(
step1(),
callStep2IfNeeded(),
step3(),
callStep3IfNeeded()
)
return new WorkflowResponse({ ret1, ret2, ret3, ret4 })
})
const { result: workflowResult } = await workflow().run()
expect(mockStep1Fn).toHaveBeenCalledTimes(1)
expect(mockStep2Fn).toHaveBeenCalledTimes(0)
expect(mockStep3Fn).toHaveBeenCalledTimes(1)
expect(mockStep4Fn).toHaveBeenCalledTimes(0)
expect(workflowResult).toEqual({
ret1: true,
ret2: undefined,
ret3: true,
ret4: undefined,
})
expect(stepResults).toEqual(["step3", "step1"])
})
it("should compose a new workflow with parallelize steps and rollback them all in case of error", async () => { it("should compose a new workflow with parallelize steps and rollback them all in case of error", async () => {
const step1CompensationFn = jest.fn().mockImplementation(() => { const step1CompensationFn = jest.fn().mockImplementation(() => {
return "step1 compensation" return "step1 compensation"
@@ -41,7 +41,7 @@ import { OrchestrationUtils } from "@medusajs/utils"
* } * }
* ) * )
*/ */
export function parallelize<TResult extends WorkflowData[]>( export function parallelize<TResult extends (WorkflowData | undefined)[]>(
...steps: TResult ...steps: TResult
): TResult { ): TResult {
if (!global[OrchestrationUtils.SymbolMedusaWorkflowComposerContext]) { if (!global[OrchestrationUtils.SymbolMedusaWorkflowComposerContext]) {
@@ -64,7 +64,7 @@ export function parallelize<TResult extends WorkflowData[]>(
const stepOntoMerge = steps.shift()! const stepOntoMerge = steps.shift()!
this.flow.mergeActions( this.flow.mergeActions(
stepOntoMerge.__step__, stepOntoMerge.__step__,
...steps.map((step) => step.__step__) ...steps.map((step) => step!.__step__)
) )
return resultSteps as unknown as TResult return resultSteps as unknown as TResult
@@ -104,7 +104,9 @@ export type CreateWorkflowComposerContext = {
fn: StepFunctionResult fn: StepFunctionResult
) => WorkflowData<TOutput> ) => WorkflowData<TOutput>
hookBinder: (name: string, fn: () => HookHandler) => void hookBinder: (name: string, fn: () => HookHandler) => void
parallelizeBinder: <TOutput extends WorkflowData[] = WorkflowData[]>( parallelizeBinder: <
TOutput extends (WorkflowData | undefined)[] = WorkflowData[]
>(
fn: (this: CreateWorkflowComposerContext) => TOutput fn: (this: CreateWorkflowComposerContext) => TOutput
) => TOutput ) => TOutput
} }