fix: workflow async concurrency (#13769)
* executeAsync * || 1 * wip * stepId * stepId * wip * wip * continue versioning management changes * fix and improve concurrency * update in memory engine * remove duplicated test * fix script * Create weak-drinks-confess.md * fixes * fix * fix * continuation * centralize merge checkepoint * centralize merge checkpoint * fix locking * rm only * Continue improvements and fixes * fixes * fixes * hasAwaiting will be recomputed * fix orchestrator engine * bump version on async parallel steps only * mark as delivered fix * changeset * check partitions * avoid saving when having parent step * cart test --------- Co-authored-by: Carlos R. L. Rodrigues <rodrigolr@gmail.com> Co-authored-by: Carlos R. L. Rodrigues <37986729+carlos-r-l-rodrigues@users.noreply.github.com> Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
d97a60d3c1
commit
516f5a3896
@@ -11,16 +11,20 @@ import {
|
||||
adminHeaders,
|
||||
createAdminUser,
|
||||
} from "../../../../helpers/create-admin-user"
|
||||
import { setTimeout } from "timers/promises"
|
||||
import { IWorkflowEngineService } from "@medusajs/framework/types"
|
||||
|
||||
jest.setTimeout(300000)
|
||||
|
||||
medusaIntegrationTestRunner({
|
||||
testSuite: ({ dbConnection, getContainer, api }) => {
|
||||
let container
|
||||
let workflowOrcModule: IWorkflowEngineService
|
||||
|
||||
beforeEach(async () => {
|
||||
container = getContainer()
|
||||
await createAdminUser(dbConnection, adminHeaders, container)
|
||||
workflowOrcModule = container.resolve(Modules.WORKFLOW_ENGINE)
|
||||
})
|
||||
|
||||
describe("GET /admin/workflow-executions", () => {
|
||||
@@ -90,5 +94,181 @@ medusaIntegrationTestRunner({
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("Workflow Orchestrator module subscribe", function () {
|
||||
it("should subscribe to a workflow and receive the response when it finishes", async () => {
|
||||
const step1 = createStep({ name: "step1" }, async () => {
|
||||
return new StepResponse("step1")
|
||||
})
|
||||
const step2 = createStep({ name: "step2" }, async () => {
|
||||
await setTimeout(1000)
|
||||
return new StepResponse("step2")
|
||||
})
|
||||
|
||||
const workflowId =
|
||||
"workflow" + Math.random().toString(36).substring(2, 15)
|
||||
createWorkflow(workflowId, function (input) {
|
||||
step1()
|
||||
step2().config({
|
||||
async: true,
|
||||
})
|
||||
return new WorkflowResponse("workflow")
|
||||
})
|
||||
|
||||
const step1_1 = createStep({ name: "step1_1" }, async () => {
|
||||
return new StepResponse("step1_1")
|
||||
})
|
||||
const step2_1 = createStep({ name: "step2_1" }, async () => {
|
||||
await setTimeout(1000)
|
||||
return new StepResponse("step2_1")
|
||||
})
|
||||
|
||||
const workflow2Id =
|
||||
"workflow_2" + Math.random().toString(36).substring(2, 15)
|
||||
createWorkflow(workflow2Id, function (input) {
|
||||
step1_1()
|
||||
step2_1().config({
|
||||
async: true,
|
||||
})
|
||||
return new WorkflowResponse("workflow_2")
|
||||
})
|
||||
|
||||
const transactionId =
|
||||
"trx_123" + Math.random().toString(36).substring(2, 15)
|
||||
const transactionId2 =
|
||||
"trx_124" + Math.random().toString(36).substring(2, 15)
|
||||
|
||||
const onWorkflowFinishSpy = jest.fn()
|
||||
|
||||
const onWorkflowFinishPromise = new Promise<void>((resolve) => {
|
||||
void workflowOrcModule.subscribe({
|
||||
workflowId: workflowId,
|
||||
transactionId,
|
||||
subscriber: (event) => {
|
||||
console.log("event", event)
|
||||
if (event.eventType === "onFinish") {
|
||||
onWorkflowFinishSpy()
|
||||
workflowOrcModule.run(workflow2Id, {
|
||||
transactionId: transactionId2,
|
||||
})
|
||||
resolve()
|
||||
}
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
const onWorkflow2FinishSpy = jest.fn()
|
||||
|
||||
const workflow2FinishPromise = new Promise<void>((resolve) => {
|
||||
void workflowOrcModule.subscribe({
|
||||
workflowId: workflow2Id,
|
||||
subscriber: (event) => {
|
||||
console.log("event", event)
|
||||
if (event.eventType === "onFinish") {
|
||||
onWorkflow2FinishSpy()
|
||||
resolve()
|
||||
}
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
workflowOrcModule.run(workflowId, {
|
||||
transactionId,
|
||||
})
|
||||
|
||||
await onWorkflowFinishPromise
|
||||
await workflow2FinishPromise
|
||||
|
||||
expect(onWorkflowFinishSpy).toHaveBeenCalledTimes(1)
|
||||
expect(onWorkflow2FinishSpy).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
it("should subscribe to a workflow and receive the response when it finishes (2)", async () => {
|
||||
const step1 = createStep({ name: "step1" }, async () => {
|
||||
return new StepResponse("step1")
|
||||
})
|
||||
const step2 = createStep({ name: "step2" }, async () => {
|
||||
await setTimeout(1000)
|
||||
return new StepResponse("step2")
|
||||
})
|
||||
|
||||
const workflowId =
|
||||
"workflow" + Math.random().toString(36).substring(2, 15)
|
||||
createWorkflow(workflowId, function (input) {
|
||||
step1()
|
||||
step2().config({
|
||||
async: true,
|
||||
})
|
||||
return new WorkflowResponse("workflow")
|
||||
})
|
||||
|
||||
const step1_1 = createStep({ name: "step1_1" }, async () => {
|
||||
return new StepResponse("step1_1")
|
||||
})
|
||||
const step2_1 = createStep({ name: "step2_1" }, async () => {
|
||||
await setTimeout(1000)
|
||||
return new StepResponse("step2_1")
|
||||
})
|
||||
|
||||
const workflow2Id =
|
||||
"workflow_2" + Math.random().toString(36).substring(2, 15)
|
||||
createWorkflow(workflow2Id, function (input) {
|
||||
step1_1()
|
||||
step2_1().config({
|
||||
async: true,
|
||||
})
|
||||
return new WorkflowResponse("workflow_2")
|
||||
})
|
||||
|
||||
const transactionId =
|
||||
"trx_123" + Math.random().toString(36).substring(2, 15)
|
||||
const transactionId2 =
|
||||
"trx_124" + Math.random().toString(36).substring(2, 15)
|
||||
|
||||
const onWorkflowFinishSpy = jest.fn()
|
||||
|
||||
const onWorkflowFinishPromise = new Promise<void>((resolve) => {
|
||||
void workflowOrcModule.subscribe({
|
||||
workflowId: workflowId,
|
||||
transactionId,
|
||||
subscriber: (event) => {
|
||||
console.log("event", event)
|
||||
if (event.eventType === "onFinish") {
|
||||
onWorkflowFinishSpy()
|
||||
workflowOrcModule.run(workflow2Id, {
|
||||
transactionId: transactionId2,
|
||||
})
|
||||
resolve()
|
||||
}
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
const onWorkflow2FinishSpy = jest.fn()
|
||||
|
||||
const workflow2FinishPromise = new Promise<void>((resolve) => {
|
||||
void workflowOrcModule.subscribe({
|
||||
workflowId: workflow2Id,
|
||||
subscriber: (event) => {
|
||||
console.log("event", event)
|
||||
if (event.eventType === "onFinish") {
|
||||
onWorkflow2FinishSpy()
|
||||
resolve()
|
||||
}
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
workflowOrcModule.run(workflowId, {
|
||||
transactionId,
|
||||
})
|
||||
|
||||
await onWorkflowFinishPromise
|
||||
await workflow2FinishPromise
|
||||
|
||||
expect(onWorkflowFinishSpy).toHaveBeenCalledTimes(1)
|
||||
expect(onWorkflow2FinishSpy).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user