chore(workflow-engine): export cancel method (#11844)
What: * Workflow engine exports the method `cancel` to revert a workflow.
This commit is contained in:
@@ -20,6 +20,7 @@ import {
|
||||
import {
|
||||
isDefined,
|
||||
isErrorLike,
|
||||
isObject,
|
||||
MedusaError,
|
||||
promiseAll,
|
||||
serializeError,
|
||||
@@ -188,6 +189,7 @@ export class TransactionOrchestrator extends EventEmitter {
|
||||
TransactionStepState.DORMANT,
|
||||
TransactionStepState.SKIPPED,
|
||||
]
|
||||
|
||||
const siblings = step.next.map((sib) => flow.steps[sib])
|
||||
return (
|
||||
siblings.length === 0 ||
|
||||
@@ -1208,70 +1210,72 @@ export class TransactionOrchestrator extends EventEmitter {
|
||||
while (queue.length > 0) {
|
||||
const { obj, level } = queue.shift()
|
||||
|
||||
for (const key of Object.keys(obj)) {
|
||||
if (typeof obj[key] === "object" && obj[key] !== null) {
|
||||
queue.push({ obj: obj[key], level: [...level] })
|
||||
} else if (key === "action") {
|
||||
if (actionNames.has(obj.action)) {
|
||||
throw new Error(
|
||||
`Step ${obj.action} is already defined in workflow.`
|
||||
)
|
||||
}
|
||||
|
||||
actionNames.add(obj.action)
|
||||
level.push(obj.action)
|
||||
const id = level.join(".")
|
||||
const parent = level.slice(0, level.length - 1).join(".")
|
||||
|
||||
if (!existingSteps || parent === TransactionOrchestrator.ROOT_STEP) {
|
||||
states[parent].next?.push(id)
|
||||
}
|
||||
|
||||
const definitionCopy = { ...obj }
|
||||
delete definitionCopy.next
|
||||
|
||||
if (definitionCopy.async) {
|
||||
features.hasAsyncSteps = true
|
||||
}
|
||||
|
||||
if (definitionCopy.timeout) {
|
||||
features.hasStepTimeouts = true
|
||||
}
|
||||
|
||||
if (
|
||||
definitionCopy.retryInterval ||
|
||||
definitionCopy.retryIntervalAwaiting
|
||||
) {
|
||||
features.hasRetriesTimeout = true
|
||||
}
|
||||
|
||||
if (definitionCopy.nested) {
|
||||
features.hasNestedTransactions = true
|
||||
}
|
||||
|
||||
states[id] = Object.assign(
|
||||
new TransactionStep(),
|
||||
existingSteps?.[id] || {
|
||||
id,
|
||||
uuid: definitionCopy.uuid,
|
||||
depth: level.length - 1,
|
||||
definition: definitionCopy,
|
||||
saveResponse: definitionCopy.saveResponse ?? true,
|
||||
invoke: {
|
||||
state: TransactionStepState.NOT_STARTED,
|
||||
status: TransactionStepStatus.IDLE,
|
||||
},
|
||||
compensate: {
|
||||
state: TransactionStepState.DORMANT,
|
||||
status: TransactionStepStatus.IDLE,
|
||||
},
|
||||
attempts: 0,
|
||||
failures: 0,
|
||||
lastAttempt: null,
|
||||
next: [],
|
||||
}
|
||||
)
|
||||
if (obj.action) {
|
||||
if (actionNames.has(obj.action)) {
|
||||
throw new Error(`Step ${obj.action} is already defined in workflow.`)
|
||||
}
|
||||
|
||||
actionNames.add(obj.action)
|
||||
level.push(obj.action)
|
||||
const id = level.join(".")
|
||||
const parent = level.slice(0, level.length - 1).join(".")
|
||||
|
||||
if (!existingSteps || parent === TransactionOrchestrator.ROOT_STEP) {
|
||||
states[parent].next?.push(id)
|
||||
}
|
||||
|
||||
const definitionCopy = { ...obj }
|
||||
delete definitionCopy.next
|
||||
|
||||
if (definitionCopy.async) {
|
||||
features.hasAsyncSteps = true
|
||||
}
|
||||
|
||||
if (definitionCopy.timeout) {
|
||||
features.hasStepTimeouts = true
|
||||
}
|
||||
|
||||
if (
|
||||
definitionCopy.retryInterval ||
|
||||
definitionCopy.retryIntervalAwaiting
|
||||
) {
|
||||
features.hasRetriesTimeout = true
|
||||
}
|
||||
|
||||
if (definitionCopy.nested) {
|
||||
features.hasNestedTransactions = true
|
||||
}
|
||||
|
||||
states[id] = Object.assign(
|
||||
new TransactionStep(),
|
||||
existingSteps?.[id] || {
|
||||
id,
|
||||
uuid: definitionCopy.uuid,
|
||||
depth: level.length - 1,
|
||||
definition: definitionCopy,
|
||||
saveResponse: definitionCopy.saveResponse ?? true,
|
||||
invoke: {
|
||||
state: TransactionStepState.NOT_STARTED,
|
||||
status: TransactionStepStatus.IDLE,
|
||||
},
|
||||
compensate: {
|
||||
state: TransactionStepState.DORMANT,
|
||||
status: TransactionStepStatus.IDLE,
|
||||
},
|
||||
attempts: 0,
|
||||
failures: 0,
|
||||
lastAttempt: null,
|
||||
next: [],
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
if (Array.isArray(obj.next)) {
|
||||
for (const next of obj.next) {
|
||||
queue.push({ obj: next, level: [...level] })
|
||||
}
|
||||
} else if (isObject(obj.next)) {
|
||||
queue.push({ obj: obj.next, level: [...level] })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { FindConfig } from "../common"
|
||||
import { IModuleService } from "../modules-sdk"
|
||||
import { ContainerLike, IModuleService } from "../modules-sdk"
|
||||
import { Context } from "../shared-context"
|
||||
import {
|
||||
FilterableWorkflowExecutionProps,
|
||||
@@ -28,6 +28,15 @@ export interface WorkflowOrchestratorRunDTO<T = unknown>
|
||||
transactionId?: string
|
||||
}
|
||||
|
||||
export interface WorkflowOrchestratorCancelOptionsDTO {
|
||||
transactionId: string
|
||||
context?: Context
|
||||
throwOnError?: boolean
|
||||
logOnError?: boolean
|
||||
events?: Record<string, Function>
|
||||
container?: ContainerLike
|
||||
}
|
||||
|
||||
export type IdempotencyKeyParts = {
|
||||
workflowId: string
|
||||
transactionId: string
|
||||
@@ -63,17 +72,11 @@ export interface IWorkflowEngineService extends IModuleService {
|
||||
workflowId: string,
|
||||
options?: WorkflowOrchestratorRunDTO,
|
||||
sharedContext?: Context
|
||||
): Promise<{
|
||||
errors: Error[]
|
||||
transaction: object
|
||||
result: any
|
||||
acknowledgement: Acknowledgement
|
||||
}>
|
||||
)
|
||||
|
||||
getRunningTransaction(
|
||||
workflowId: string,
|
||||
transactionId: string,
|
||||
options?: Record<string, any>,
|
||||
sharedContext?: Context
|
||||
): Promise<unknown>
|
||||
|
||||
@@ -121,4 +124,10 @@ export interface IWorkflowEngineService extends IModuleService {
|
||||
},
|
||||
sharedContext?: Context
|
||||
)
|
||||
|
||||
cancel(
|
||||
workflowId: string,
|
||||
options: WorkflowOrchestratorCancelOptionsDTO,
|
||||
sharedContext?: Context
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user