feat(workflows-sdk): log on error (#8666)
This commit is contained in:
@@ -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>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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> =
|
||||||
idempotencyKey: string
|
BaseFlowRunOptions & {
|
||||||
response?: TData
|
idempotencyKey: string
|
||||||
context?: Context
|
response?: TData
|
||||||
resultFrom?: string | string[] | Symbol
|
}
|
||||||
throwOnError?: boolean
|
|
||||||
events?: DistributedTransactionEvents
|
|
||||||
container?: LoadedModule[] | MedusaContainer
|
|
||||||
}
|
|
||||||
|
|
||||||
export type FlowRegisterStepFailureOptions<TData = unknown> = {
|
export type FlowRegisterStepFailureOptions<TData = unknown> =
|
||||||
idempotencyKey: string
|
BaseFlowRunOptions & {
|
||||||
response?: TData
|
idempotencyKey: string
|
||||||
context?: Context
|
response?: TData
|
||||||
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,
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user