chore(): only execute race execution checks and publish message only for async workflows (#13396)
* chore(): only execute race execution checks for async workflows * chore(): workflow redis publish only for async flows * Create cyan-gorillas-poke.md * chore(): workflow redis publish only for async flows * fix negative check --------- Co-authored-by: Carlos R. L. Rodrigues <37986729+carlos-r-l-rodrigues@users.noreply.github.com>
This commit is contained in:
1 parent
28830567e7
commit
2b89510df3
7 files changed
+144
-52
No files matched your search
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
"@medusajs/workflow-engine-inmemory": patch
|
||||||
|
"@medusajs/workflow-engine-redis": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
chore(): only execute race execution checks for async workflows
|
||||||
+26
-8
@@ -47,11 +47,11 @@ import { createScheduled } from "../__fixtures__/workflow_scheduled"
|
|||||||
|
|
||||||
jest.setTimeout(60000)
|
jest.setTimeout(60000)
|
||||||
|
|
||||||
const failTrap = (done) => {
|
const failTrap = (done, name) => {
|
||||||
setTimeoutSync(() => {
|
setTimeoutSync(() => {
|
||||||
// REF:https://stackoverflow.com/questions/78028715/jest-async-test-with-event-emitter-isnt-ending
|
// REF:https://stackoverflow.com/questions/78028715/jest-async-test-with-event-emitter-isnt-ending
|
||||||
console.warn(
|
console.warn(
|
||||||
`Jest is breaking the event emit with its debouncer. This allows to continue the test by managing the timeout of the test manually.`
|
`Jest is breaking the event emit with its debouncer. This allows to continue the test by managing the timeout of the test manually. ${name}`
|
||||||
)
|
)
|
||||||
done()
|
done()
|
||||||
}, 5000)
|
}, 5000)
|
||||||
@@ -200,7 +200,10 @@ moduleIntegrationTestRunner<IWorkflowEngineService>({
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
failTrap(done)
|
failTrap(
|
||||||
|
done,
|
||||||
|
"should cancel an ongoing execution with async unfinished yet step"
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should cancel a complete execution with a sync workflow running as async", async () => {
|
it("should cancel a complete execution with a sync workflow running as async", async () => {
|
||||||
@@ -537,7 +540,10 @@ moduleIntegrationTestRunner<IWorkflowEngineService>({
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
failTrap(done)
|
failTrap(
|
||||||
|
done,
|
||||||
|
"should subscribe to a async workflow and receive the response when it finishes"
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("Testing basic workflow", function () {
|
describe("Testing basic workflow", function () {
|
||||||
@@ -744,7 +750,10 @@ moduleIntegrationTestRunner<IWorkflowEngineService>({
|
|||||||
})
|
})
|
||||||
|
|
||||||
expect(onFinish).toHaveBeenCalledTimes(0)
|
expect(onFinish).toHaveBeenCalledTimes(0)
|
||||||
failTrap(done)
|
failTrap(
|
||||||
|
done,
|
||||||
|
"should subscribe to a async workflow and receive the response when it finishes"
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should cancel and revert a completed workflow", async () => {
|
it("should cancel and revert a completed workflow", async () => {
|
||||||
@@ -817,7 +826,10 @@ moduleIntegrationTestRunner<IWorkflowEngineService>({
|
|||||||
throwOnError: true,
|
throwOnError: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
failTrap(done)
|
failTrap(
|
||||||
|
done,
|
||||||
|
"should not run conditional steps if condition is false"
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should not run conditional steps if condition is false", (done) => {
|
it("should not run conditional steps if condition is false", (done) => {
|
||||||
@@ -839,7 +851,10 @@ moduleIntegrationTestRunner<IWorkflowEngineService>({
|
|||||||
throwOnError: true,
|
throwOnError: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
failTrap(done)
|
failTrap(
|
||||||
|
done,
|
||||||
|
"should not run conditional steps if condition is false"
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -988,7 +1003,10 @@ moduleIntegrationTestRunner<IWorkflowEngineService>({
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
failTrap(done)
|
failTrap(
|
||||||
|
done,
|
||||||
|
"should display error when multple async steps are running in parallel"
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -14,11 +14,11 @@ import "../__fixtures__"
|
|||||||
|
|
||||||
jest.setTimeout(300000)
|
jest.setTimeout(300000)
|
||||||
|
|
||||||
const failTrap = (done) => {
|
const failTrap = (done, name) => {
|
||||||
setTimeoutSync(() => {
|
setTimeoutSync(() => {
|
||||||
// REF:https://stackoverflow.com/questions/78028715/jest-async-test-with-event-emitter-isnt-ending
|
// REF:https://stackoverflow.com/questions/78028715/jest-async-test-with-event-emitter-isnt-ending
|
||||||
console.warn(
|
console.warn(
|
||||||
"Jest is breaking the event emit with its debouncer. This allows to continue the test by managing the timeout of the test manually."
|
`Jest is breaking the event emit with its debouncer. This allows to continue the test by managing the timeout of the test manually. ${name}`
|
||||||
)
|
)
|
||||||
done()
|
done()
|
||||||
}, 5000)
|
}, 5000)
|
||||||
@@ -99,7 +99,10 @@ moduleIntegrationTestRunner<IWorkflowEngineService>({
|
|||||||
})
|
})
|
||||||
.catch((e) => e)
|
.catch((e) => e)
|
||||||
|
|
||||||
failTrap(done)
|
failTrap(
|
||||||
|
done,
|
||||||
|
"should prevent race continuation of the workflow during retryIntervalAwaiting in background execution"
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should prevent race continuation of the workflow compensation during retryIntervalAwaiting in background execution", (done) => {
|
it("should prevent race continuation of the workflow compensation during retryIntervalAwaiting in background execution", (done) => {
|
||||||
@@ -190,7 +193,10 @@ moduleIntegrationTestRunner<IWorkflowEngineService>({
|
|||||||
})
|
})
|
||||||
.catch((e) => e)
|
.catch((e) => e)
|
||||||
|
|
||||||
failTrap(done)
|
failTrap(
|
||||||
|
done,
|
||||||
|
"should prevent race continuation of the workflow compensation during retryIntervalAwaiting in background execution"
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|||||||
+7
-5
@@ -285,11 +285,13 @@ export class InMemoryDistributedTransactionStorage
|
|||||||
|
|
||||||
const { retentionTime } = options ?? {}
|
const { retentionTime } = options ?? {}
|
||||||
|
|
||||||
await this.#preventRaceConditionExecutionIfNecessary({
|
if (data.flow.hasAsyncSteps) {
|
||||||
data,
|
await this.#preventRaceConditionExecutionIfNecessary({
|
||||||
key,
|
data,
|
||||||
options,
|
key,
|
||||||
})
|
options,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Only store retention time if it's provided
|
// Only store retention time if it's provided
|
||||||
if (retentionTime) {
|
if (retentionTime) {
|
||||||
|
|||||||
@@ -15,11 +15,11 @@ import "../__fixtures__"
|
|||||||
|
|
||||||
jest.setTimeout(300000)
|
jest.setTimeout(300000)
|
||||||
|
|
||||||
const failTrap = (done) => {
|
const failTrap = (done, name) => {
|
||||||
setTimeoutSync(() => {
|
setTimeoutSync(() => {
|
||||||
// REF:https://stackoverflow.com/questions/78028715/jest-async-test-with-event-emitter-isnt-ending
|
// REF:https://stackoverflow.com/questions/78028715/jest-async-test-with-event-emitter-isnt-ending
|
||||||
console.warn(
|
console.warn(
|
||||||
"Jest is breaking the event emit with its debouncer. This allows to continue the test by managing the timeout of the test manually."
|
`Jest is breaking the event emit with its debouncer. This allows to continue the test by managing the timeout of the test manually. ${name}`
|
||||||
)
|
)
|
||||||
done()
|
done()
|
||||||
}, 5000)
|
}, 5000)
|
||||||
@@ -118,7 +118,10 @@ moduleIntegrationTestRunner<IWorkflowEngineService>({
|
|||||||
expect(result).toBe("result from step 0")
|
expect(result).toBe("result from step 0")
|
||||||
})
|
})
|
||||||
|
|
||||||
failTrap(done)
|
failTrap(
|
||||||
|
done,
|
||||||
|
"should prevent race continuation of the workflow during retryIntervalAwaiting in background execution"
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should prevent race continuation of the workflow compensation during retryIntervalAwaiting in background execution", (done) => {
|
it("should prevent race continuation of the workflow compensation during retryIntervalAwaiting in background execution", (done) => {
|
||||||
@@ -214,7 +217,10 @@ moduleIntegrationTestRunner<IWorkflowEngineService>({
|
|||||||
expect(result).toBe("result from step 0")
|
expect(result).toBe("result from step 0")
|
||||||
})
|
})
|
||||||
|
|
||||||
failTrap(done)
|
failTrap(
|
||||||
|
done,
|
||||||
|
"should prevent race continuation of the workflow compensation during retryIntervalAwaiting in background execution"
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ type IdempotencyKeyParts = {
|
|||||||
|
|
||||||
type NotifyOptions = {
|
type NotifyOptions = {
|
||||||
eventType: keyof DistributedTransactionEvents
|
eventType: keyof DistributedTransactionEvents
|
||||||
|
isFlowAsync: boolean
|
||||||
workflowId: string
|
workflowId: string
|
||||||
transactionId?: string
|
transactionId?: string
|
||||||
step?: TransactionStep
|
step?: TransactionStep
|
||||||
@@ -315,12 +316,6 @@ export class WorkflowOrchestratorService {
|
|||||||
throw new Error("Transaction ID is required")
|
throw new Error("Transaction ID is required")
|
||||||
}
|
}
|
||||||
|
|
||||||
const events: FlowRunOptions["events"] = this.buildWorkflowEvents({
|
|
||||||
customEventHandlers: eventHandlers,
|
|
||||||
workflowId,
|
|
||||||
transactionId: transactionId,
|
|
||||||
})
|
|
||||||
|
|
||||||
const exportedWorkflow = MedusaWorkflow.getWorkflow(workflowId)
|
const exportedWorkflow = MedusaWorkflow.getWorkflow(workflowId)
|
||||||
if (!exportedWorkflow) {
|
if (!exportedWorkflow) {
|
||||||
throw new Error(`Workflow with id "${workflowId}" not found.`)
|
throw new Error(`Workflow with id "${workflowId}" not found.`)
|
||||||
@@ -344,6 +339,12 @@ export class WorkflowOrchestratorService {
|
|||||||
throw new Error("Transaction not found")
|
throw new Error("Transaction not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const events: FlowRunOptions["events"] = this.buildWorkflowEvents({
|
||||||
|
customEventHandlers: eventHandlers,
|
||||||
|
workflowId,
|
||||||
|
transactionId: transactionId,
|
||||||
|
})
|
||||||
|
|
||||||
const ret = await exportedWorkflow.cancel({
|
const ret = await exportedWorkflow.cancel({
|
||||||
transaction,
|
transaction,
|
||||||
throwOnError: false,
|
throwOnError: false,
|
||||||
@@ -373,6 +374,7 @@ export class WorkflowOrchestratorService {
|
|||||||
const { result, errors } = ret
|
const { result, errors } = ret
|
||||||
|
|
||||||
this.notify({
|
this.notify({
|
||||||
|
isFlowAsync: ret.transaction.getFlow().hasAsyncSteps,
|
||||||
eventType: "onFinish",
|
eventType: "onFinish",
|
||||||
workflowId,
|
workflowId,
|
||||||
transactionId: transaction.transactionId,
|
transactionId: transaction.transactionId,
|
||||||
@@ -471,6 +473,7 @@ export class WorkflowOrchestratorService {
|
|||||||
const { result, errors } = ret
|
const { result, errors } = ret
|
||||||
|
|
||||||
this.notify({
|
this.notify({
|
||||||
|
isFlowAsync: ret.transaction.getFlow().hasAsyncSteps,
|
||||||
eventType: "onFinish",
|
eventType: "onFinish",
|
||||||
workflowId,
|
workflowId,
|
||||||
transactionId,
|
transactionId,
|
||||||
@@ -544,6 +547,7 @@ export class WorkflowOrchestratorService {
|
|||||||
const { result, errors } = ret
|
const { result, errors } = ret
|
||||||
|
|
||||||
this.notify({
|
this.notify({
|
||||||
|
isFlowAsync: ret.transaction.getFlow().hasAsyncSteps,
|
||||||
eventType: "onFinish",
|
eventType: "onFinish",
|
||||||
workflowId,
|
workflowId,
|
||||||
transactionId,
|
transactionId,
|
||||||
@@ -669,16 +673,8 @@ export class WorkflowOrchestratorService {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (publish) {
|
|
||||||
const channel = this.getChannelName(options.workflowId)
|
|
||||||
const message = JSON.stringify({
|
|
||||||
instanceId: this.instanceId,
|
|
||||||
data: options,
|
|
||||||
})
|
|
||||||
await this.redisPublisher.publish(channel, message)
|
|
||||||
}
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
isFlowAsync,
|
||||||
eventType,
|
eventType,
|
||||||
workflowId,
|
workflowId,
|
||||||
transactionId,
|
transactionId,
|
||||||
@@ -689,6 +685,15 @@ export class WorkflowOrchestratorService {
|
|||||||
state,
|
state,
|
||||||
} = options
|
} = options
|
||||||
|
|
||||||
|
if (publish && isFlowAsync) {
|
||||||
|
const channel = this.getChannelName(options.workflowId)
|
||||||
|
const message = JSON.stringify({
|
||||||
|
instanceId: this.instanceId,
|
||||||
|
data: options,
|
||||||
|
})
|
||||||
|
await this.redisPublisher.publish(channel, message)
|
||||||
|
}
|
||||||
|
|
||||||
const subscribers: TransactionSubscribers =
|
const subscribers: TransactionSubscribers =
|
||||||
this.subscribers.get(workflowId) ?? new Map()
|
this.subscribers.get(workflowId) ?? new Map()
|
||||||
|
|
||||||
@@ -698,6 +703,7 @@ export class WorkflowOrchestratorService {
|
|||||||
eventType,
|
eventType,
|
||||||
workflowId,
|
workflowId,
|
||||||
transactionId,
|
transactionId,
|
||||||
|
isFlowAsync,
|
||||||
step,
|
step,
|
||||||
response,
|
response,
|
||||||
result,
|
result,
|
||||||
@@ -743,6 +749,7 @@ export class WorkflowOrchestratorService {
|
|||||||
transactionId,
|
transactionId,
|
||||||
}): DistributedTransactionEvents {
|
}): DistributedTransactionEvents {
|
||||||
const notify = async ({
|
const notify = async ({
|
||||||
|
isFlowAsync,
|
||||||
eventType,
|
eventType,
|
||||||
step,
|
step,
|
||||||
result,
|
result,
|
||||||
@@ -750,6 +757,7 @@ export class WorkflowOrchestratorService {
|
|||||||
errors,
|
errors,
|
||||||
state,
|
state,
|
||||||
}: {
|
}: {
|
||||||
|
isFlowAsync: boolean
|
||||||
eventType: keyof DistributedTransactionEvents
|
eventType: keyof DistributedTransactionEvents
|
||||||
step?: TransactionStep
|
step?: TransactionStep
|
||||||
response?: unknown
|
response?: unknown
|
||||||
@@ -758,6 +766,7 @@ export class WorkflowOrchestratorService {
|
|||||||
state?: TransactionState
|
state?: TransactionState
|
||||||
}) => {
|
}) => {
|
||||||
await this.notify({
|
await this.notify({
|
||||||
|
isFlowAsync,
|
||||||
workflowId,
|
workflowId,
|
||||||
transactionId,
|
transactionId,
|
||||||
eventType,
|
eventType,
|
||||||
@@ -772,31 +781,50 @@ export class WorkflowOrchestratorService {
|
|||||||
return {
|
return {
|
||||||
onTimeout: async ({ transaction }) => {
|
onTimeout: async ({ transaction }) => {
|
||||||
customEventHandlers?.onTimeout?.({ transaction })
|
customEventHandlers?.onTimeout?.({ transaction })
|
||||||
await notify({ eventType: "onTimeout" })
|
await notify({
|
||||||
|
eventType: "onTimeout",
|
||||||
|
isFlowAsync: transaction.getFlow().hasAsyncSteps,
|
||||||
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
onBegin: async ({ transaction }) => {
|
onBegin: async ({ transaction }) => {
|
||||||
customEventHandlers?.onBegin?.({ transaction })
|
customEventHandlers?.onBegin?.({ transaction })
|
||||||
await notify({ eventType: "onBegin" })
|
await notify({
|
||||||
|
eventType: "onBegin",
|
||||||
|
isFlowAsync: transaction.getFlow().hasAsyncSteps,
|
||||||
|
})
|
||||||
},
|
},
|
||||||
onResume: async ({ transaction }) => {
|
onResume: async ({ transaction }) => {
|
||||||
customEventHandlers?.onResume?.({ transaction })
|
customEventHandlers?.onResume?.({ transaction })
|
||||||
await notify({ eventType: "onResume" })
|
await notify({
|
||||||
|
eventType: "onResume",
|
||||||
|
isFlowAsync: transaction.getFlow().hasAsyncSteps,
|
||||||
|
})
|
||||||
},
|
},
|
||||||
onCompensateBegin: async ({ transaction }) => {
|
onCompensateBegin: async ({ transaction }) => {
|
||||||
customEventHandlers?.onCompensateBegin?.({ transaction })
|
customEventHandlers?.onCompensateBegin?.({ transaction })
|
||||||
await notify({ eventType: "onCompensateBegin" })
|
await notify({
|
||||||
|
eventType: "onCompensateBegin",
|
||||||
|
isFlowAsync: transaction.getFlow().hasAsyncSteps,
|
||||||
|
})
|
||||||
},
|
},
|
||||||
onFinish: async ({ transaction, result, errors }) => {
|
onFinish: async ({ transaction, result, errors }) => {
|
||||||
customEventHandlers?.onFinish?.({ transaction, result, errors })
|
customEventHandlers?.onFinish?.({ transaction, result, errors })
|
||||||
await notify({ eventType: "onFinish" })
|
await notify({
|
||||||
|
eventType: "onFinish",
|
||||||
|
isFlowAsync: transaction.getFlow().hasAsyncSteps,
|
||||||
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
onStepBegin: async ({ step, transaction }) => {
|
onStepBegin: async ({ step, transaction }) => {
|
||||||
customEventHandlers?.onStepBegin?.({ step, transaction })
|
customEventHandlers?.onStepBegin?.({ step, transaction })
|
||||||
this.activeStepsCount++
|
this.activeStepsCount++
|
||||||
|
|
||||||
await notify({ eventType: "onStepBegin", step })
|
await notify({
|
||||||
|
eventType: "onStepBegin",
|
||||||
|
step,
|
||||||
|
isFlowAsync: transaction.getFlow().hasAsyncSteps,
|
||||||
|
})
|
||||||
},
|
},
|
||||||
onStepSuccess: async ({ step, transaction }) => {
|
onStepSuccess: async ({ step, transaction }) => {
|
||||||
const stepName = step.definition.action!
|
const stepName = step.definition.action!
|
||||||
@@ -805,7 +833,12 @@ export class WorkflowOrchestratorService {
|
|||||||
transaction
|
transaction
|
||||||
)
|
)
|
||||||
customEventHandlers?.onStepSuccess?.({ step, transaction, response })
|
customEventHandlers?.onStepSuccess?.({ step, transaction, response })
|
||||||
await notify({ eventType: "onStepSuccess", step, response })
|
await notify({
|
||||||
|
eventType: "onStepSuccess",
|
||||||
|
step,
|
||||||
|
response,
|
||||||
|
isFlowAsync: transaction.getFlow().hasAsyncSteps,
|
||||||
|
})
|
||||||
|
|
||||||
this.activeStepsCount--
|
this.activeStepsCount--
|
||||||
},
|
},
|
||||||
@@ -816,14 +849,23 @@ export class WorkflowOrchestratorService {
|
|||||||
.filter((err) => err.action === stepName)
|
.filter((err) => err.action === stepName)
|
||||||
|
|
||||||
customEventHandlers?.onStepFailure?.({ step, transaction, errors })
|
customEventHandlers?.onStepFailure?.({ step, transaction, errors })
|
||||||
await notify({ eventType: "onStepFailure", step, errors })
|
await notify({
|
||||||
|
eventType: "onStepFailure",
|
||||||
|
step,
|
||||||
|
errors,
|
||||||
|
isFlowAsync: transaction.getFlow().hasAsyncSteps,
|
||||||
|
})
|
||||||
|
|
||||||
this.activeStepsCount--
|
this.activeStepsCount--
|
||||||
},
|
},
|
||||||
onStepAwaiting: async ({ step, transaction }) => {
|
onStepAwaiting: async ({ step, transaction }) => {
|
||||||
customEventHandlers?.onStepAwaiting?.({ step, transaction })
|
customEventHandlers?.onStepAwaiting?.({ step, transaction })
|
||||||
|
|
||||||
await notify({ eventType: "onStepAwaiting", step })
|
await notify({
|
||||||
|
eventType: "onStepAwaiting",
|
||||||
|
step,
|
||||||
|
isFlowAsync: transaction.getFlow().hasAsyncSteps,
|
||||||
|
})
|
||||||
|
|
||||||
this.activeStepsCount--
|
this.activeStepsCount--
|
||||||
},
|
},
|
||||||
@@ -837,7 +879,12 @@ export class WorkflowOrchestratorService {
|
|||||||
response,
|
response,
|
||||||
})
|
})
|
||||||
|
|
||||||
await notify({ eventType: "onCompensateStepSuccess", step, response })
|
await notify({
|
||||||
|
eventType: "onCompensateStepSuccess",
|
||||||
|
step,
|
||||||
|
response,
|
||||||
|
isFlowAsync: transaction.getFlow().hasAsyncSteps,
|
||||||
|
})
|
||||||
},
|
},
|
||||||
onCompensateStepFailure: async ({ step, transaction }) => {
|
onCompensateStepFailure: async ({ step, transaction }) => {
|
||||||
const stepName = step.definition.action!
|
const stepName = step.definition.action!
|
||||||
@@ -847,7 +894,12 @@ export class WorkflowOrchestratorService {
|
|||||||
|
|
||||||
customEventHandlers?.onStepFailure?.({ step, transaction, errors })
|
customEventHandlers?.onStepFailure?.({ step, transaction, errors })
|
||||||
|
|
||||||
await notify({ eventType: "onCompensateStepFailure", step, errors })
|
await notify({
|
||||||
|
eventType: "onCompensateStepFailure",
|
||||||
|
step,
|
||||||
|
errors,
|
||||||
|
isFlowAsync: transaction.getFlow().hasAsyncSteps,
|
||||||
|
})
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -413,11 +413,13 @@ export class RedisDistributedTransactionStorage
|
|||||||
|
|
||||||
const { retentionTime } = options ?? {}
|
const { retentionTime } = options ?? {}
|
||||||
|
|
||||||
await this.#preventRaceConditionExecutionIfNecessary({
|
if (data.flow.hasAsyncSteps) {
|
||||||
data,
|
await this.#preventRaceConditionExecutionIfNecessary({
|
||||||
key,
|
data,
|
||||||
options,
|
key,
|
||||||
})
|
options,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
if (hasFinished && retentionTime) {
|
if (hasFinished && retentionTime) {
|
||||||
Object.assign(data, {
|
Object.assign(data, {
|
||||||
|
|||||||
Reference in new issue
Block a user