docs: improvements + additions to workflow docs (#9182)

Improve existing workflow docs + add missing docs
This commit is contained in:
Shahed Nasser
2024-09-20 15:38:32 +00:00
committed by GitHub
parent a4b5d66b3e
commit 6584e911e0
18 changed files with 678 additions and 406 deletions
@@ -4,16 +4,25 @@ export const metadata = {
# {metadata.title}
In this chapter, you'll learn how to add a compensation function to a step.
In this chapter, you'll learn what a compensation function is and how to add it to a step.
## Compensation Function
## What is a Compensation Function
To avoid data inconsistency when an error is thrown in a workflow, define a function (called a compensation function) and pass it as a second parameter to the `createStep` function.
A compensation function rolls back or undoes changes made by a step when an error occurs in the workflow.
For example:
For example, if a step creates a record, the compensation function deletes the record when an error occurs later in the workflow.
```ts title="src/workflows/hello-world.ts" highlights={[["16"], ["17"], ["18"]]} collapsibleLines="1-6" expandButtonLabel="Show Imports"
// other imports...
By using compensation functions, you provide a mechanism that guarantees data consistency in your application and across systems.
---
## How to add a Compensation Function?
A compensation function is passed as a second parameter to the `createStep` function.
For example, create the file `src/workflows/hello-world.ts` with the following content:
```ts title="src/workflows/hello-world.ts" highlights={[["15"], ["16"], ["17"]]} collapsibleLines="1-5" expandButtonLabel="Show Imports"
import {
createStep,
StepResponse,
@@ -34,16 +43,15 @@ const step1 = createStep(
)
```
Each step can have a compensation function. The compensation function only runs if an error occurs throughout the workflow. Its useful to undo or roll back actions youve performed in a step.
Each step can have a compensation function. The compensation function only runs if an error occurs throughout the workflow.
---
## Test the Compensation Function
1. Add another step that throws an error:
Create a step in the same `src/workflows/hello-world.ts` file that throws an error:
```ts title="src/workflows/hello-world.ts"
// ...
const step2 = createStep(
"step-2",
async () => {
@@ -52,16 +60,16 @@ const step2 = createStep(
)
```
2. Use the steps in a workflow. For example:
Then, create a workflow that uses the steps:
```ts title="src/workflows/hello-world.ts" collapsibleLines="1-8" expandButtonLabel="Show Imports"
import {
// other imports...
createWorkflow,
WorkflowResponse,
} from "@medusajs/workflows-sdk"
// other imports...
// ...
// steps...
const myWorkflow = createWorkflow(
"hello-world",
@@ -77,7 +85,7 @@ const myWorkflow = createWorkflow(
export default myWorkflow
```
3. Execute the workflow from a resource, such as an API route:
Finally, execute the workflow from an API route:
```ts title="src/api/workflow/route.ts" collapsibleLines="1-6" expandButtonLabel="Show Imports"
import type {
@@ -97,13 +105,7 @@ export async function GET(
}
```
4. Run the Medusa application:
```bash npm2yarn
npm run dev
```
5. Send a `GET` request to `/workflow`:
Run the Medusa application and send a `GET` request to `/workflow`:
```bash
curl http://localhost:9000/workflow
@@ -112,4 +114,85 @@ curl http://localhost:9000/workflow
In the console, you'll see:
- `Hello from step one!` logged in the terminal, indicating that the first step ran successfully.
- `Oops! Rolling back my changes...` logged in the terminal, indicating that the second step failed and the compensation function of the first step ran consequently.
- `Oops! Rolling back my changes...` logged in the terminal, indicating that the second step failed and the compensation function of the first step ran consequently.
---
## Pass Input to Compensation Function
If a step creates a record, the compensation function must receive the ID of the record to remove it.
To pass input to the compensation function, pass a second parameter in the `StepResponse` returned by the step.
For example:
export const inputHighlights = [
["11", "", "The data to pass as an input to the compensation function."],
["14", "{ message }", "The data received as an input from `StepResponse`'s second parameter."]
]
```ts highlights={inputHighlights}
import {
createStep,
StepResponse,
} from "@medusajs/workflows-sdk"
const step1 = createStep(
"step-1",
async () => {
return new StepResponse(
`Hello from step one!`,
{ message: "Oops! Rolling back my changes..."}
)
},
async ({ message }) => {
console.log(message)
}
)
```
In this example, the step passes an object as a second parameter to `StepResponse`.
The compensation function receives the object and uses its `message` property to log a message.
---
## Resolve Resources from the Medusa Container
The compensation function receives an object second parameter. The object has a `container` property that you use to resolve resources from the Medusa container.
For example:
export const containerHighlights = [
["15", "container", "Access the container in the second parameter object."],
["16", "resolve", "Use the container to resolve resources."]
]
```ts
import {
createStep,
StepResponse,
} from "@medusajs/workflows-sdk"
import { ContainerRegistrationKeys } from "@medusajs/utils"
const step1 = createStep(
"step-1",
async () => {
return new StepResponse(
`Hello from step one!`,
{ message: "Oops! Rolling back my changes..."}
)
},
async ({ message }, { container }) => {
const logger = container.resolve(
ContainerRegistrationKeys.LOGGER
)
logger.info(message)
}
)
```
In this example, you use the `container` property in the second object parameter of the compensation function to resolve the logger.
You then use the logger to log a message.