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, which are in the Go packages under packages/core/core-flows/src in the MedusaGo repository.
Executing a workflow within another is slightly different from how you usually execute a workflow. Instead of calling the workflow's Run method with the container, you call its RunAsStep method with the execution of the workflow you're in. This runs the nested workflow within the parent workflow's execution, with the same container and context.
For example, to execute the CreateProductsWorkflow in your custom workflow:
// Workflow executes createProductsWorkflow as a step.
var Workflow = composer.CreateWorkflow("hello-world",
func(e *composer.Execution, _ any) ([]*dal.Record, error) {
product := dal.NewRecord()
product.Set("title", "Shirt")
// ...
// the workflow's output is returned, not a result property
products, err := workflows.CreateProductsWorkflow.RunAsStep(e, workflows.CreateProductsInput{
Products: []*dal.Record{product},
})
if err != nil {
return nil, err
}
// ...
return products, nil
})
RunAsStep accepts the workflow's execution, and the nested workflow's input. It returns the nested workflow's output, and an error.
The nested workflow runs as one step of the parent workflow, named after the nested workflow's ID with the suffix -as-step. To use another name, call RunAsStepNamed with the name as its second parameter.
Prepare Input Data#
Since the body of a workflow is Go code, you can prepare the input data of the nested workflow with regular code:
// WorkflowInput is the input of the workflow.
type WorkflowInput struct {
Title string `json:"title"`
}
// HelloProductWorkflow prepares the input of the nested workflow with
// regular Go code.
var HelloProductWorkflow = composer.CreateWorkflow("hello-product",
func(e *composer.Execution, input WorkflowInput) ([]*dal.Record, error) {
product := dal.NewRecord()
product.Set("title", "Hello "+input.Title)
return workflows.CreateProductsWorkflow.RunAsStep(e, workflows.CreateProductsInput{
Products: []*dal.Record{product},
})
})
In this example, you prepend Hello to the title of the product. Then, you pass the product as input to the CreateProductsWorkflow.
Run Workflow Conditionally#
Similarly, you run a workflow conditionally with an if statement:
// ConditionalInput is the input of the workflow.
type ConditionalInput struct {
Product *dal.Record
ShouldCreate bool
}
// ConditionalWorkflow only runs createProductsWorkflow if ShouldCreate is
// enabled.
var ConditionalWorkflow = composer.CreateWorkflow("conditional-product",
func(e *composer.Execution, input ConditionalInput) ([]*dal.Record, error) {
if !input.ShouldCreate {
return nil, nil
}
return workflows.CreateProductsWorkflow.RunAsStep(e, workflows.CreateProductsInput{
Products: []*dal.Record{input.Product},
})
})
In this example, the workflow only runs the CreateProductsWorkflow if ShouldCreate (passed in the input) is enabled.
Errors in Nested Workflows#
A nested workflow behaves similarly to a step in a workflow. So, if the nested workflow fails, it returns an error that you return from the parent workflow to stop its execution and compensate the previous steps.
In addition, if another step fails after the nested workflow, the nested workflow's steps are compensated as part of the compensation process, in the reverse order of the steps.
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 waits 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.
Nested Workflows and Hooks#
The hooks of the nested workflow still run when you execute it as a step. If you consumed a hook of the nested workflow, as explained in the Workflow Hooks chapter, its handler runs as part of the parent workflow's execution.