diff --git a/packages/core/orchestration/src/transaction/transaction-orchestrator.ts b/packages/core/orchestration/src/transaction/transaction-orchestrator.ts index 2cf277c778..b5e1f3b333 100644 --- a/packages/core/orchestration/src/transaction/transaction-orchestrator.ts +++ b/packages/core/orchestration/src/transaction/transaction-orchestrator.ts @@ -549,6 +549,16 @@ export class TransactionOrchestrator extends EventEmitter { step.changeState(TransactionStepState.TIMEOUT) + if (error?.stack) { + const workflowId = transaction.modelId + const stepAction = step.definition.action + const sourcePath = transaction.getFlow().metadata?.sourcePath + const sourceStack = sourcePath + ? `\n⮑ \sat ${sourcePath}: [${workflowId} -> ${stepAction} (${TransactionHandlerType.INVOKE})]` + : `\n⮑ \sat [${workflowId} -> ${stepAction} (${TransactionHandlerType.INVOKE})]` + error.stack += sourceStack + } + transaction.addError( step.definition.action!, TransactionHandlerType.INVOKE, @@ -602,13 +612,21 @@ export class TransactionOrchestrator extends EventEmitter { step.changeStatus(TransactionStepStatus.PERMANENT_FAILURE) if (!isTimeout) { - transaction.addError( - step.definition.action!, - step.isCompensating() - ? TransactionHandlerType.COMPENSATE - : TransactionHandlerType.INVOKE, - error - ) + const handlerType = step.isCompensating() + ? TransactionHandlerType.COMPENSATE + : TransactionHandlerType.INVOKE + + if (error?.stack) { + const workflowId = transaction.modelId + const stepAction = step.definition.action + const sourcePath = transaction.getFlow().metadata?.sourcePath + const sourceStack = sourcePath + ? `\n⮑ \sat ${sourcePath}: [${workflowId} -> ${stepAction} (${TransactionHandlerType.INVOKE})]` + : `\n⮑ \sat [${workflowId} -> ${stepAction} (${TransactionHandlerType.INVOKE})]` + error.stack += sourceStack + } + + transaction.addError(step.definition.action!, handlerType, error) } if (!step.isCompensating()) { diff --git a/packages/core/orchestration/src/transaction/types.ts b/packages/core/orchestration/src/transaction/types.ts index ef48652858..b83ebab1bf 100644 --- a/packages/core/orchestration/src/transaction/types.ts +++ b/packages/core/orchestration/src/transaction/types.ts @@ -243,6 +243,7 @@ export type TransactionFlow = { metadata?: { eventGroupId?: string parentIdempotencyKey?: string + sourcePath?: string [key: string]: unknown } hasAsyncSteps: boolean diff --git a/packages/core/workflows-sdk/src/helper/workflow-export.ts b/packages/core/workflows-sdk/src/helper/workflow-export.ts index a2ff478560..502b4e13be 100644 --- a/packages/core/workflows-sdk/src/helper/workflow-export.ts +++ b/packages/core/workflows-sdk/src/helper/workflow-export.ts @@ -44,6 +44,7 @@ function createContextualWorkflowRunner< dataPreparation?: (data: TData) => Promise options?: { wrappedInput?: boolean + sourcePath?: string } container?: LoadedModule[] | MedusaContainer }): Omit< @@ -93,6 +94,7 @@ function createContextualWorkflowRunner< const flowMetadata = { eventGroupId, parentStepIdempotencyKey, + sourcePath: options?.sourcePath, } const args = [ @@ -334,6 +336,7 @@ export const exportWorkflow = ( dataPreparation?: (data: TData) => Promise, options?: { wrappedInput?: boolean + sourcePath?: string } ): MainExportedWorkflow => { function exportedWorkflow< diff --git a/packages/core/workflows-sdk/src/utils/composer/__tests__/compose.ts b/packages/core/workflows-sdk/src/utils/composer/__tests__/compose.ts index 45d01632f6..b0f12c6682 100644 --- a/packages/core/workflows-sdk/src/utils/composer/__tests__/compose.ts +++ b/packages/core/workflows-sdk/src/utils/composer/__tests__/compose.ts @@ -6,19 +6,19 @@ import { } from "@medusajs/orchestration" import { IEventBusModuleService } from "@medusajs/types" import { - Modules, composeMessage, createMedusaContainer, + Modules, promiseAll, } from "@medusajs/utils" import { asValue } from "awilix" import { - StepResponse, - WorkflowResponse, createStep, createWorkflow, parallelize, + StepResponse, transform, + WorkflowResponse, } from ".." import { MedusaWorkflow } from "../../../medusa-workflow" import { createHook } from "../create-hook" @@ -1903,7 +1903,7 @@ describe("Workflow composer", function () { action: "step1", handlerType: "invoke", error: expect.objectContaining({ - message: "invoke fail", + message: "invoke fail", }), }) diff --git a/packages/core/workflows-sdk/src/utils/composer/create-workflow.ts b/packages/core/workflows-sdk/src/utils/composer/create-workflow.ts index 970dc60464..0f8ea3068f 100644 --- a/packages/core/workflows-sdk/src/utils/composer/create-workflow.ts +++ b/packages/core/workflows-sdk/src/utils/composer/create-workflow.ts @@ -4,7 +4,11 @@ import { WorkflowManager, } from "@medusajs/orchestration" import { LoadedModule, MedusaContainer } from "@medusajs/types" -import { OrchestrationUtils, isString } from "@medusajs/utils" +import { + getCallerFilePath, + isString, + OrchestrationUtils, +} from "@medusajs/utils" import { ulid } from "ulid" import { exportWorkflow } from "../../helper" import { createStep } from "./create-step" @@ -34,7 +38,7 @@ global[OrchestrationUtils.SymbolMedusaWorkflowComposerContext] = null * @returns The created workflow. You can later execute the workflow by invoking it, then using its `run` method. * * @example - * import { + * import { * createWorkflow, * WorkflowResponse * } from "@medusajs/framework/workflows-sdk" @@ -50,7 +54,7 @@ global[OrchestrationUtils.SymbolMedusaWorkflowComposerContext] = null * } * * const myWorkflow = createWorkflow( - * "my-workflow", + * "my-workflow", * (input: WorkflowInput) => { * // Everything here will be executed and resolved later * // during the execution. Including the data access. @@ -92,6 +96,7 @@ export function createWorkflow( input: WorkflowData ) => void | WorkflowResponse ): ReturnWorkflow { + const fileSourcePath = getCallerFilePath() as string const name = isString(nameOrConfig) ? nameOrConfig : nameOrConfig.name const options = isString(nameOrConfig) ? {} : nameOrConfig @@ -153,6 +158,7 @@ export function createWorkflow( undefined, { wrappedInput: true, + sourcePath: fileSourcePath, } )