From cdfde0dfacd52b8b74a5a2b88b5b95229df97b04 Mon Sep 17 00:00:00 2001 From: Shahed Nasser Date: Fri, 24 Jan 2025 14:34:24 +0200 Subject: [PATCH] docs: document workflow retention (#11138) --- .../workflows/long-running-workflow/page.mdx | 6 + .../workflows/store-executions/page.mdx | 173 ++++++++++++++++++ www/apps/book/generated/edit-dates.mjs | 3 +- www/apps/book/sidebar.mjs | 5 + 4 files changed, 186 insertions(+), 1 deletion(-) create mode 100644 www/apps/book/app/learn/fundamentals/workflows/store-executions/page.mdx diff --git a/www/apps/book/app/learn/fundamentals/workflows/long-running-workflow/page.mdx b/www/apps/book/app/learn/fundamentals/workflows/long-running-workflow/page.mdx index 32f003cdff..4f07d29e9b 100644 --- a/www/apps/book/app/learn/fundamentals/workflows/long-running-workflow/page.mdx +++ b/www/apps/book/app/learn/fundamentals/workflows/long-running-workflow/page.mdx @@ -282,6 +282,12 @@ You use this step in another workflow that changes the status of an async step i To access the status and result of a long-running workflow execution, use the `subscribe` and `unsubscribe` methods of the Workflow Engine Module's main service. + + +To retrieve the workflow execution's details at a later point, you must enable [storing the workflow's executions](../store-executions/page.mdx). + + + For example: export const highlights = [ diff --git a/www/apps/book/app/learn/fundamentals/workflows/store-executions/page.mdx b/www/apps/book/app/learn/fundamentals/workflows/store-executions/page.mdx new file mode 100644 index 0000000000..663bb65c01 --- /dev/null +++ b/www/apps/book/app/learn/fundamentals/workflows/store-executions/page.mdx @@ -0,0 +1,173 @@ +import { Prerequisites } from "docs-ui" + +export const metadata = { + title: `${pageNumber} Store Workflow Executions`, +} + +# {metadata.title} + +In this chapter, you'll learn how to store workflow executions in the database and access them later. + +## Workflow Execution Retention + +Medusa doesn't store your workflow's execution details by default. However, you can configure a workflow to keep its execution details stored in the database. + +This is useful for auditing and debugging purposes. When you store a workflow's execution, you can view details around its steps, their states and their output. You can also check whether the workflow or any of its steps failed. + + + +You can view stored workflow executions from the Medusa Admin dashboard by going to Settings -> Workflows. + + + +--- + +## How to Store Workflow's Executions? + + + +`createWorkflow` from the Workflows SDK can accept an object as a first parameter to set the workflow's configuration. To enable storing a workflow's executions: + +- Enable the `store` option. If your workflow is a [Long-Running Workflow](../long-running-workflow/page.mdx), this option is enabled by default. +- Set the `retentionTime` option to the number of milliseconds that the workflow execution should be stored in the database. + +For example: + +export const highlights = [ + ["15", "retentionTime", "The number of milliseconds that the workflow's executions should be stored in the database."], + ["16", "store", "Enable storing the workflow's executions in the database."], +] + +```ts highlights={highlights} +import { createStep, createWorkflow } from "@medusajs/framework/workflows-sdk" + +const step1 = createStep( + { + name: "step-1" + }, + async () => { + console.log("Hello from step 1") + } +) + +export const helloWorkflow = createWorkflow( + { + name: "hello-workflow", + retentionTime: 99999, + store: true + }, + () => { + step1() + } +) +``` + +Whenever you execute the `helloWorkflow` now, its execution details will be stored in the database. + +--- + +## Retrieve Workflow Executions + + + +You can view stored workflow executions from the Medusa Admin dashboard by going to Settings -> Workflows. + + + +When you execute a workflow, the returned object has a `transaction` property containing the workflow execution's transaction details: + +```ts +const { transaction } = await helloWorkflow(container).run() +``` + +To retrieve a workflow's execution details from the database, resolve the Workflow Engine Module from the container and use its `listWorkflowExecutions` method. + +For example, you can create a `GET` API Route at `src/workflows/[id]/route.ts` that retrieves a workflow execution for the specified transaction ID: + +export const retrieveHighlights = [ + ["8", "transaction_id", "Get the transaction ID from a path parameter."], + ["10", "workflowEngineService", "Resolve the Workflow Engine Module from the container."], + ["14", "workflowExecution", "Retrieve the workflow execution for the specified transaction ID."], +] + +```ts title="src/workflows/[id]/route.ts" highlights={retrieveHighlights} +import { MedusaRequest, MedusaResponse } from "@medusajs/framework"; +import { Modules } from "@medusajs/framework/utils"; + +export async function GET( + req: MedusaRequest, + res: MedusaResponse +) { + const { transaction_id } = req.params + + const workflowEngineService = req.scope.resolve( + Modules.WORKFLOW_ENGINE + ) + + const [workflowExecution] = await workflowEngineService.listWorkflowExecutions({ + transaction_id: transaction_id + }) + + res.json({ + workflowExecution + }) +} +``` + +In the above example, you resolve the Workflow Engine Module from the container and use its `listWorkflowExecutions` method, passing the `transaction_id` as a filter to retrieve its workflow execution details. + +A workflow execution object will be similar to the following: + +```json +{ + "workflow_id": "hello-workflow", + "transaction_id": "01JJC2T6AVJCQ3N4BRD1EB88SP", + "id": "wf_exec_01JJC2T6B3P76JD35F12QTTA78", + "execution": { + "state": "done", + "steps": {}, + "modelId": "hello-workflow", + "options": {}, + "metadata": {}, + "startedAt": 1737719880027, + "definition": {}, + "timedOutAt": null, + "hasAsyncSteps": false, + "transactionId": "01JJC2T6AVJCQ3N4BRD1EB88SP", + "hasFailedSteps": false, + "hasSkippedSteps": false, + "hasWaitingSteps": false, + "hasRevertedSteps": false, + "hasSkippedOnFailureSteps": false + }, + "context": { + "data": {}, + "errors": [] + }, + "state": "done", + "created_at": "2025-01-24T09:58:00.036Z", + "updated_at": "2025-01-24T09:58:00.046Z", + "deleted_at": null +} +``` + +### Example: Check if Stored Workflow Execution Failed + +To check if a stored workflow execution failed, you can check its `state` property: + +```ts +if (workflowExecution.state === "failed") { + return res.status(500).json({ + error: "Workflow failed" + }) +} +``` + +Other state values include `done`, `invoking`, and `compensating`. \ No newline at end of file diff --git a/www/apps/book/generated/edit-dates.mjs b/www/apps/book/generated/edit-dates.mjs index 4a0f7dba60..c7a90f86e6 100644 --- a/www/apps/book/generated/edit-dates.mjs +++ b/www/apps/book/generated/edit-dates.mjs @@ -108,5 +108,6 @@ export const generatedEditDates = { "app/learn/fundamentals/workflows/multiple-step-usage/page.mdx": "2024-11-25T16:19:32.169Z", "app/learn/installation/page.mdx": "2025-01-06T09:12:48.690Z", "app/learn/fundamentals/data-models/check-constraints/page.mdx": "2024-12-06T14:34:50.384Z", - "app/learn/fundamentals/module-links/link/page.mdx": "2025-01-06T09:27:25.604Z" + "app/learn/fundamentals/module-links/link/page.mdx": "2025-01-06T09:27:25.604Z", + "app/learn/fundamentals/workflows/store-executions/page.mdx": "2025-01-24T12:09:24.087Z" } \ No newline at end of file diff --git a/www/apps/book/sidebar.mjs b/www/apps/book/sidebar.mjs index b4f31c19df..82c99b9a03 100644 --- a/www/apps/book/sidebar.mjs +++ b/www/apps/book/sidebar.mjs @@ -382,6 +382,11 @@ export const sidebar = numberSidebarItems( path: "/learn/fundamentals/workflows/workflow-timeout", title: "Workflow Timeout", }, + { + type: "link", + path: "/learn/fundamentals/workflows/store-executions", + title: "Store Workflow Executions", + }, { type: "link", path: "/learn/fundamentals/workflows/long-running-workflow",