feat(workflows-sdk): log on error (#8666)

This commit is contained in:
Carlos R. L. Rodrigues
2024-08-20 06:23:24 -03:00
committed by GitHub
parent 1be9373290
commit eb0bfe9f33
6 changed files with 122 additions and 80 deletions
@@ -11,6 +11,7 @@ type FlowRunOptions<TData = unknown> = {
context?: Context context?: Context
resultFrom?: string | string[] | Symbol resultFrom?: string | string[] | Symbol
throwOnError?: boolean throwOnError?: boolean
logOnError?: boolean
events?: Record<string, Function> events?: Record<string, Function>
} }
+19 -27
View File
@@ -1,47 +1,39 @@
import { Context, LoadedModule, MedusaContainer } from "@medusajs/types"
import { import {
DistributedTransactionType,
DistributedTransactionEvents, DistributedTransactionEvents,
DistributedTransactionType,
LocalWorkflow, LocalWorkflow,
TransactionStepError, TransactionStepError,
} from "@medusajs/orchestration" } from "@medusajs/orchestration"
import { Context, LoadedModule, MedusaContainer } from "@medusajs/types"
export type FlowRunOptions<TData = unknown> = { type BaseFlowRunOptions = {
context?: Context
resultFrom?: string | string[] | Symbol
throwOnError?: boolean
logOnError?: boolean
events?: DistributedTransactionEvents
container?: LoadedModule[] | MedusaContainer
}
export type FlowRunOptions<TData = unknown> = BaseFlowRunOptions & {
input?: TData input?: TData
context?: Context
resultFrom?: string | string[] | Symbol
throwOnError?: boolean
events?: DistributedTransactionEvents
container?: LoadedModule[] | MedusaContainer
} }
export type FlowRegisterStepSuccessOptions<TData = unknown> = { export type FlowRegisterStepSuccessOptions<TData = unknown> =
BaseFlowRunOptions & {
idempotencyKey: string idempotencyKey: string
response?: TData response?: TData
context?: Context }
resultFrom?: string | string[] | Symbol
throwOnError?: boolean
events?: DistributedTransactionEvents
container?: LoadedModule[] | MedusaContainer
}
export type FlowRegisterStepFailureOptions<TData = unknown> = { export type FlowRegisterStepFailureOptions<TData = unknown> =
BaseFlowRunOptions & {
idempotencyKey: string idempotencyKey: string
response?: TData response?: TData
context?: Context }
resultFrom?: string | string[] | Symbol
throwOnError?: boolean
events?: DistributedTransactionEvents
container?: LoadedModule[] | MedusaContainer
}
export type FlowCancelOptions = { export type FlowCancelOptions = BaseFlowRunOptions & {
transaction?: DistributedTransactionType transaction?: DistributedTransactionType
transactionId?: string transactionId?: string
context?: Context
throwOnError?: boolean
events?: DistributedTransactionEvents
container?: LoadedModule[] | MedusaContainer
} }
/** /**
@@ -1,7 +1,7 @@
import { MedusaModule } from "@medusajs/modules-sdk" import { MedusaModule } from "@medusajs/modules-sdk"
import { import {
DistributedTransactionType,
DistributedTransactionEvents, DistributedTransactionEvents,
DistributedTransactionType,
LocalWorkflow, LocalWorkflow,
TransactionHandlerType, TransactionHandlerType,
TransactionState, TransactionState,
@@ -62,6 +62,7 @@ function createContextualWorkflowRunner<
method, method,
{ {
throwOnError, throwOnError,
logOnError = false,
resultFrom, resultFrom,
isCancel = false, isCancel = false,
container: executionContainer, container: executionContainer,
@@ -86,7 +87,7 @@ function createContextualWorkflowRunner<
const { eventGroupId } = context const { eventGroupId } = context
attachOnFinishReleaseEvents(events, eventGroupId!, flow) attachOnFinishReleaseEvents(events, eventGroupId!, flow, { logOnError })
const flowMetadata = { const flowMetadata = {
eventGroupId, eventGroupId,
@@ -143,21 +144,18 @@ function createContextualWorkflowRunner<
} }
} }
const newRun = async ( const newRun = async ({
{
input, input,
context: outerContext, context: outerContext,
throwOnError, throwOnError,
logOnError,
resultFrom, resultFrom,
events, events,
container, container,
}: FlowRunOptions = { }: FlowRunOptions = {}) => {
throwOnError: true,
resultFrom: defaultResult,
}
) => {
resultFrom ??= defaultResult resultFrom ??= defaultResult
throwOnError ??= true throwOnError ??= true
logOnError ??= false
const context = { const context = {
...outerContext, ...outerContext,
@@ -185,7 +183,12 @@ function createContextualWorkflowRunner<
return await originalExecution( return await originalExecution(
originalRun, originalRun,
{ throwOnError, resultFrom, container }, {
throwOnError,
resultFrom,
container,
logOnError,
},
context.transactionId, context.transactionId,
input, input,
context, context,
@@ -200,17 +203,18 @@ function createContextualWorkflowRunner<
idempotencyKey, idempotencyKey,
context: outerContext, context: outerContext,
throwOnError, throwOnError,
logOnError,
resultFrom, resultFrom,
events, events,
container, container,
}: FlowRegisterStepSuccessOptions = { }: FlowRegisterStepSuccessOptions = {
idempotencyKey: "", idempotencyKey: "",
throwOnError: true,
resultFrom: defaultResult,
} }
) => { ) => {
idempotencyKey ??= ""
resultFrom ??= defaultResult resultFrom ??= defaultResult
throwOnError ??= true throwOnError ??= true
logOnError ??= false
const [, transactionId] = idempotencyKey.split(":") const [, transactionId] = idempotencyKey.split(":")
const context = { const context = {
@@ -223,7 +227,12 @@ function createContextualWorkflowRunner<
return await originalExecution( return await originalExecution(
originalRegisterStepSuccess, originalRegisterStepSuccess,
{ throwOnError, resultFrom, container }, {
throwOnError,
resultFrom,
container,
logOnError,
},
idempotencyKey, idempotencyKey,
response, response,
context, context,
@@ -238,17 +247,18 @@ function createContextualWorkflowRunner<
idempotencyKey, idempotencyKey,
context: outerContext, context: outerContext,
throwOnError, throwOnError,
logOnError,
resultFrom, resultFrom,
events, events,
container, container,
}: FlowRegisterStepFailureOptions = { }: FlowRegisterStepFailureOptions = {
idempotencyKey: "", idempotencyKey: "",
throwOnError: true,
resultFrom: defaultResult,
} }
) => { ) => {
idempotencyKey ??= ""
resultFrom ??= defaultResult resultFrom ??= defaultResult
throwOnError ??= true throwOnError ??= true
logOnError ??= false
const [, transactionId] = idempotencyKey.split(":") const [, transactionId] = idempotencyKey.split(":")
const context = { const context = {
@@ -261,7 +271,12 @@ function createContextualWorkflowRunner<
return await originalExecution( return await originalExecution(
originalRegisterStepFailure, originalRegisterStepFailure,
{ throwOnError, resultFrom, container }, {
throwOnError,
resultFrom,
container,
logOnError,
},
idempotencyKey, idempotencyKey,
response, response,
context, context,
@@ -270,19 +285,17 @@ function createContextualWorkflowRunner<
} }
flow.registerStepFailure = newRegisterStepFailure as any flow.registerStepFailure = newRegisterStepFailure as any
const newCancel = async ( const newCancel = async ({
{
transaction, transaction,
transactionId, transactionId,
context: outerContext, context: outerContext,
throwOnError, throwOnError,
logOnError,
events, events,
container, container,
}: FlowCancelOptions = { }: FlowCancelOptions = {}) => {
throwOnError: true,
}
) => {
throwOnError ??= true throwOnError ??= true
logOnError ??= false
const context = { const context = {
...outerContext, ...outerContext,
@@ -299,6 +312,7 @@ function createContextualWorkflowRunner<
resultFrom: undefined, resultFrom: undefined,
isCancel: true, isCancel: true,
container, container,
logOnError,
}, },
transaction ?? transactionId!, transaction ?? transactionId!,
undefined, undefined,
@@ -478,7 +492,12 @@ export const exportWorkflow = <TData = unknown, TResult = unknown>(
function attachOnFinishReleaseEvents( function attachOnFinishReleaseEvents(
events: DistributedTransactionEvents = {}, events: DistributedTransactionEvents = {},
eventGroupId: string, eventGroupId: string,
flow: LocalWorkflow flow: LocalWorkflow,
{
logOnError,
}: {
logOnError?: boolean
} = {}
) { ) {
const onFinish = events.onFinish const onFinish = events.onFinish
@@ -487,6 +506,30 @@ function attachOnFinishReleaseEvents(
result?: unknown result?: unknown
errors?: unknown[] errors?: unknown[]
}) => { }) => {
const { transaction } = args
const logger =
(flow.container as MedusaContainer).resolve(
ContainerRegistrationKeys.LOGGER,
{ allowUnregistered: true }
) || console
if (logOnError) {
const TERMINAL_SIZE = process.stdout?.columns ?? 60
const separator = new Array(TERMINAL_SIZE).join("-")
const worflowName = transaction.getFlow().modelId
const allWorkflowErrors = transaction
.getErrors()
.map(
(err) =>
`${worflowName}:${err?.action}:${err?.handlerType} - ${err?.error?.message}${EOL}${err?.error?.stack}`
)
.join(EOL + separator + EOL)
logger.error(allWorkflowErrors)
}
await onFinish?.(args) await onFinish?.(args)
const eventBusService = (flow.container as MedusaContainer).resolve( const eventBusService = (flow.container as MedusaContainer).resolve(
@@ -498,13 +541,6 @@ function attachOnFinishReleaseEvents(
return return
} }
const logger =
(flow.container as MedusaContainer).resolve(
ContainerRegistrationKeys.LOGGER,
{ allowUnregistered: true }
) || console
const { transaction } = args
const failedStatus = [TransactionState.FAILED, TransactionState.REVERTED] const failedStatus = [TransactionState.FAILED, TransactionState.REVERTED]
if (failedStatus.includes(transaction.getState())) { if (failedStatus.includes(transaction.getState())) {
@@ -1,7 +1,7 @@
import { import {
DistributedTransaction, DistributedTransaction,
DistributedTransactionType,
DistributedTransactionEvents, DistributedTransactionEvents,
DistributedTransactionType,
TransactionHandlerType, TransactionHandlerType,
TransactionStep, TransactionStep,
WorkflowScheduler, WorkflowScheduler,
@@ -109,6 +109,7 @@ export class WorkflowOrchestratorService {
transactionId, transactionId,
resultFrom, resultFrom,
throwOnError, throwOnError,
logOnError,
events: eventHandlers, events: eventHandlers,
container, container,
} = options ?? {} } = options ?? {}
@@ -148,6 +149,7 @@ export class WorkflowOrchestratorService {
const ret = await flow.run({ const ret = await flow.run({
input, input,
throwOnError, throwOnError,
logOnError,
resultFrom, resultFrom,
context, context,
events, events,
@@ -223,6 +225,7 @@ export class WorkflowOrchestratorService {
const { const {
context, context,
throwOnError, throwOnError,
logOnError,
resultFrom, resultFrom,
container, container,
events: eventHandlers, events: eventHandlers,
@@ -251,6 +254,7 @@ export class WorkflowOrchestratorService {
context, context,
resultFrom, resultFrom,
throwOnError, throwOnError,
logOnError,
events, events,
response: stepResponse, response: stepResponse,
}) })
@@ -285,6 +289,7 @@ export class WorkflowOrchestratorService {
const { const {
context, context,
throwOnError, throwOnError,
logOnError,
resultFrom, resultFrom,
container, container,
events: eventHandlers, events: eventHandlers,
@@ -313,6 +318,7 @@ export class WorkflowOrchestratorService {
context, context,
resultFrom, resultFrom,
throwOnError, throwOnError,
logOnError,
events, events,
response: stepResponse, response: stepResponse,
}) })
@@ -11,20 +11,20 @@ import {
} from "@medusajs/types" } from "@medusajs/types"
import { import {
ContainerRegistrationKeys, ContainerRegistrationKeys,
createMedusaContainer,
Module, Module,
Modules, Modules,
TransactionHandlerType, TransactionHandlerType,
TransactionStepState, TransactionStepState,
createMedusaContainer,
} from "@medusajs/utils" } from "@medusajs/utils"
import { WorkflowsModuleService } from "@medusajs/workflow-engine-inmemory/dist/services"
import { asFunction, asValue } from "awilix" import { asFunction, asValue } from "awilix"
import Redis from "ioredis"
import { knex } from "knex" import { knex } from "knex"
import { setTimeout } from "timers/promises" import { setTimeout } from "timers/promises"
import "../__fixtures__" import "../__fixtures__"
import { createScheduled } from "../__fixtures__/workflow_scheduled" import { createScheduled } from "../__fixtures__/workflow_scheduled"
import { DB_URL, TestDatabase } from "../utils" import { DB_URL, TestDatabase } from "../utils"
import { WorkflowsModuleService } from "@medusajs/workflow-engine-inmemory/dist/services"
import Redis from "ioredis"
jest.setTimeout(100000) jest.setTimeout(100000)
@@ -216,6 +216,7 @@ describe("Workflow Orchestrator module", function () {
myInput: "123", myInput: "123",
}, },
throwOnError: false, throwOnError: false,
logOnError: true,
} }
) )
@@ -1,7 +1,7 @@
import { import {
DistributedTransaction, DistributedTransaction,
DistributedTransactionType,
DistributedTransactionEvents, DistributedTransactionEvents,
DistributedTransactionType,
TransactionHandlerType, TransactionHandlerType,
TransactionStep, TransactionStep,
WorkflowScheduler, WorkflowScheduler,
@@ -12,12 +12,12 @@ import {
Logger, Logger,
MedusaContainer, MedusaContainer,
} from "@medusajs/types" } from "@medusajs/types"
import { InjectSharedContext, isString, MedusaContext } from "@medusajs/utils" import { InjectSharedContext, MedusaContext, isString } from "@medusajs/utils"
import { import {
FlowRunOptions, FlowRunOptions,
MedusaWorkflow, MedusaWorkflow,
resolveValue,
ReturnWorkflow, ReturnWorkflow,
resolveValue,
} from "@medusajs/workflows-sdk" } from "@medusajs/workflows-sdk"
import Redis from "ioredis" import Redis from "ioredis"
import { ulid } from "ulid" import { ulid } from "ulid"
@@ -158,6 +158,7 @@ export class WorkflowOrchestratorService {
transactionId, transactionId,
resultFrom, resultFrom,
throwOnError, throwOnError,
logOnError,
events: eventHandlers, events: eventHandlers,
container, container,
} = options ?? {} } = options ?? {}
@@ -191,6 +192,7 @@ export class WorkflowOrchestratorService {
const ret = await flow.run({ const ret = await flow.run({
input, input,
throwOnError, throwOnError,
logOnError,
resultFrom, resultFrom,
context, context,
events, events,
@@ -266,6 +268,7 @@ export class WorkflowOrchestratorService {
const { const {
context, context,
throwOnError, throwOnError,
logOnError,
resultFrom, resultFrom,
container, container,
events: eventHandlers, events: eventHandlers,
@@ -294,6 +297,7 @@ export class WorkflowOrchestratorService {
context, context,
resultFrom, resultFrom,
throwOnError, throwOnError,
logOnError,
events, events,
response: stepResponse, response: stepResponse,
}) })
@@ -328,6 +332,7 @@ export class WorkflowOrchestratorService {
const { const {
context, context,
throwOnError, throwOnError,
logOnError,
resultFrom, resultFrom,
container, container,
events: eventHandlers, events: eventHandlers,
@@ -356,6 +361,7 @@ export class WorkflowOrchestratorService {
context, context,
resultFrom, resultFrom,
throwOnError, throwOnError,
logOnError,
events, events,
response: stepResponse, response: stepResponse,
}) })