3.7.13. Execute Nested Workflows

In this chapter, you'll learn how to execute a workflow in another workflow.

How to Execute a Workflow in Another?#

In many cases, you may have a workflow that you want to re-use in another workflow. This is most common when you build custom workflows and you want to utilize Medusa's existing workflows.

Executing a workflow within another is slightly different from how you usually execute a workflow. Instead of invoking the workflow, passing it the container, then running its run method, you use the runAsStep method of the workflow. This will pass the Medusa container and workflow context to the nested workflow.

For example, to execute the createProductsWorkflow in your custom workflow:

Code
6} from "@medusajs/medusa/core-flows"7
8const workflow = createWorkflow(9  "hello-world",10  async (input) => {11    const products = createProductsWorkflow.runAsStep({12      input: {13        products: [14          // ...15        ],16      },17    })18
19    // ...20  }21)

The runAsStep method accepts an input property to pass input to the workflow.

Returned Data#

Notice that you don't need to use await when executing the nested workflow, as it's not a promise in this scenario.

You also receive the workflow's output as a return value from the runAsStep method. This is different from the usual workflow response, where you receive the output in a result property.


Prepare Input Data#

Since Medusa creates an internal representation of your workflow's constructor function, you can't manipulate data directly in the workflow constructor. You can learn more about this in the Data Manipulation chapter.

If you need to perform some data manipulation to prepare the nested workflow's input data, use transform from the Workflows SDK.

For example:

Code
11}12
13const workflow = createWorkflow(14  "hello-product",15  async (input: WorkflowInput) => {16    const createProductsData = transform({17      input,18    }, (data) => [19      {20        title: `Hello ${data.input.title}`,21      },22    ])23
24    const products = createProductsWorkflow.runAsStep({25      input: {26        products: createProductsData,27      },28    })29
30    // ...31  }32)

In this example, you use the transform function to prepend Hello to the title of the product. Then, you pass the result as input to the createProductsWorkflow.

Note: Learn more about transform in the Data Manipulation chapter.

Run Workflow Conditionally#

Similar to the previous section, you can't use conditional statements directly in the workflow constructor. Instead, you can use the when-then function from the Workflows SDK to run a workflow conditionally.

For example:

Code
15}16
17const workflow = createWorkflow(18  "hello-product",19  async (input: WorkflowInput) => {20    const product = when(input, ({ should_create }) => should_create)21      .then(() => {22        return createProductsWorkflow.runAsStep({23          input: {24            products: [input.product],25          },26        })27      })28  }29)

In this example, you use when-then to run the createProductsWorkflow only if should_create (passed in the input) is enabled.

Note: Learn more about when-then in the When-Then Conditions chapter.

Errors in Nested Workflows#

A nested workflow behaves similarly to a step in a workflow. So, if the nested workflow fails, it will throw an error that stops the parent workflow's execution and compensates previous steps.

In addition, if another step fails after the nested workflow, the nested workflow's steps will be compensated as part of the compensation process.

Learn more about handling errors in workflows in the Error Handling chapter.


Nested Long-Running Workflows#

When you execute a long-running workflow within another workflow, the parent workflow becomes a long-running workflow as well.

So, the parent workflow will wait for the nested workflow to finish before continuing its execution.

Refer to the Long-Running Workflows chapter for more information on how to handle long-running workflows.

Was this chapter helpful?
Ask Anything
FAQ
What is Medusa?
How can I create a module?
How can I create a data model?
How do I create a workflow?
How can I extend a data model in the Product Module?
Recipes
How do I build a marketplace with Medusa?
How do I build digital products with Medusa?
How do I build subscription-based purchases with Medusa?
What other recipes are available in the Medusa documentation?
Chat is cleared on refresh
Line break