From 95d282e8ef8f2185737d493dea8b6f1677684543 Mon Sep 17 00:00:00 2001 From: Adrien de Peretti Date: Mon, 30 Jun 2025 13:34:08 +0200 Subject: [PATCH] fix: test utils events + workflow storage (#12834) * feat(test-utils): Make event subscriber waiter robust and concurrent * feat(test-utils): Make event subscriber waiter robust and concurrent * fix workflows storage * remove timeout * Create gentle-teachers-doubt.md * revert timestamp * update changeset * fix execution loop * exit if no steps to await * typo * check next * check next * changeset * skip when async steps * wait workflow executions utils * wait workflow executions utils * wait workflow executions utils * increase timeout * break loop --------- Co-authored-by: Carlos R. L. Rodrigues Co-authored-by: Carlos R. L. Rodrigues <37986729+carlos-r-l-rodrigues@users.noreply.github.com> --- .changeset/gentle-teachers-doubt.md | 9 + .../auth/admin/auth-asymetric.spec.ts | 2 +- .../http/__tests__/auth/admin/auth.spec.ts | 2 +- .../transaction/transaction-orchestrator.ts | 14 +- .../src/dml/__tests__/entity-builder.spec.ts | 364 +++++++++++------- .../helpers/entity-builder/define-property.ts | 3 + .../src/__tests__/events.spec.ts | 8 +- packages/medusa-test-utils/src/events.ts | 165 ++++++-- .../wait-workflow-executions.ts | 35 ++ .../src/medusa-test-runner.ts | 9 + .../utils/workflow-orchestrator-storage.ts | 5 +- .../integration-tests/__tests__/index.spec.ts | 2 +- .../utils/workflow-orchestrator-storage.ts | 13 +- 13 files changed, 441 insertions(+), 190 deletions(-) create mode 100644 .changeset/gentle-teachers-doubt.md create mode 100644 packages/medusa-test-utils/src/medusa-test-runner-utils/wait-workflow-executions.ts diff --git a/.changeset/gentle-teachers-doubt.md b/.changeset/gentle-teachers-doubt.md new file mode 100644 index 0000000000..8f4542f23e --- /dev/null +++ b/.changeset/gentle-teachers-doubt.md @@ -0,0 +1,9 @@ +--- +"@medusajs/utils": patch +"@medusajs/orchestration": patch +"@medusajs/test-utils": patch +"@medusajs/workflow-engine-inmemory": patch +"@medusajs/workflow-engine-redis": patch +--- + +Fix/test utils events diff --git a/integration-tests/http/__tests__/auth/admin/auth-asymetric.spec.ts b/integration-tests/http/__tests__/auth/admin/auth-asymetric.spec.ts index 5686d328fd..8e8fb0c7f0 100644 --- a/integration-tests/http/__tests__/auth/admin/auth-asymetric.spec.ts +++ b/integration-tests/http/__tests__/auth/admin/auth-asymetric.spec.ts @@ -8,7 +8,7 @@ import { import path from "path" import { ContainerRegistrationKeys } from "@medusajs/utils" -jest.setTimeout(300000) +jest.setTimeout(100000) medusaIntegrationTestRunner({ medusaConfigFile: path.join(__dirname, "../../../__fixtures__/auth"), diff --git a/integration-tests/http/__tests__/auth/admin/auth.spec.ts b/integration-tests/http/__tests__/auth/admin/auth.spec.ts index 890f09fbd8..4281a1a4cb 100644 --- a/integration-tests/http/__tests__/auth/admin/auth.spec.ts +++ b/integration-tests/http/__tests__/auth/admin/auth.spec.ts @@ -6,7 +6,7 @@ import { createAdminUser, } from "../../../../helpers/create-admin-user" -jest.setTimeout(30000) +jest.setTimeout(100000) medusaIntegrationTestRunner({ testSuite: ({ dbConnection, getContainer, api }) => { diff --git a/packages/core/orchestration/src/transaction/transaction-orchestrator.ts b/packages/core/orchestration/src/transaction/transaction-orchestrator.ts index 1a9330faf3..e19f1972fa 100644 --- a/packages/core/orchestration/src/transaction/transaction-orchestrator.ts +++ b/packages/core/orchestration/src/transaction/transaction-orchestrator.ts @@ -841,6 +841,7 @@ export class TransactionOrchestrator extends EventEmitter { const execution: Promise[] = [] let i = 0 + let hasAsyncSteps = false for (const step of nextSteps.next) { const stepIndex = i++ if (!stepsShouldContinueExecution[stepIndex]) { @@ -876,12 +877,13 @@ export class TransactionOrchestrator extends EventEmitter { } else { // Execute async step in background and continue the execution of the transaction this.executeAsyncStep(promise, transaction, step, nextSteps) + hasAsyncSteps = true } } await promiseAll(execution) - if (nextSteps.next.length === 0) { + if (nextSteps.next.length === 0 || (hasAsyncSteps && !execution.length)) { continueExecution = false } } @@ -1290,6 +1292,16 @@ export class TransactionOrchestrator extends EventEmitter { ) } + if ( + flow.state === TransactionState.COMPENSATING || + flow.state === TransactionState.WAITING_TO_COMPENSATE + ) { + throw new MedusaError( + MedusaError.Types.NOT_ALLOWED, + `Cannot revert a transaction that is already compensating.` + ) + } + flow.state = TransactionState.WAITING_TO_COMPENSATE flow.cancelledAt = Date.now() diff --git a/packages/core/utils/src/dml/__tests__/entity-builder.spec.ts b/packages/core/utils/src/dml/__tests__/entity-builder.spec.ts index b2bc86b83f..305e2cecbf 100644 --- a/packages/core/utils/src/dml/__tests__/entity-builder.spec.ts +++ b/packages/core/utils/src/dml/__tests__/entity-builder.spec.ts @@ -23,7 +23,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", nullable: false, - + onCreate: expect.any(Function), kind: "scalar", setter: false, type: "date", @@ -45,6 +45,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", nullable: false, + onCreate: expect.any(Function), + onUpdate: expect.any(Function), kind: "scalar", setter: false, type: "date", @@ -146,7 +148,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -189,7 +191,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -289,7 +292,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -323,7 +326,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -423,7 +427,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -457,7 +461,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -570,7 +575,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -582,7 +587,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -715,7 +721,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -727,7 +733,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -861,7 +868,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -873,7 +880,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -973,7 +981,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -985,7 +993,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -1094,7 +1103,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -1106,7 +1115,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -1217,7 +1227,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -1229,7 +1239,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -1352,7 +1363,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -1364,7 +1375,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -1447,7 +1459,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -1470,7 +1482,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -1550,7 +1563,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -1562,7 +1575,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -1656,7 +1670,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -1668,7 +1682,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -1768,7 +1783,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -1780,7 +1795,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -1880,7 +1896,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -1892,7 +1908,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -1994,7 +2011,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -2006,7 +2023,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -2150,7 +2168,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -2162,7 +2180,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -2269,7 +2288,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -2281,7 +2300,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -2387,7 +2407,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -2399,7 +2419,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -2485,7 +2506,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -2497,7 +2518,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -2578,7 +2600,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -2590,7 +2612,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -2664,7 +2687,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -2676,7 +2699,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -2750,7 +2774,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -2762,7 +2786,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -2842,7 +2867,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -2854,7 +2879,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -2903,7 +2929,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -2915,7 +2941,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -3002,7 +3029,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -3014,7 +3041,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -3086,7 +3114,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -3098,7 +3126,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -3200,7 +3229,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -3212,7 +3241,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -3312,7 +3342,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -3324,7 +3354,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -3415,7 +3446,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -3427,7 +3458,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -3522,7 +3554,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -3534,7 +3566,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -3583,7 +3616,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -3595,7 +3628,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -3698,7 +3732,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -3710,7 +3744,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -3782,7 +3817,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -3794,7 +3829,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -4166,7 +4202,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -4178,7 +4214,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -4256,7 +4293,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -4268,7 +4305,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -4348,7 +4386,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -4360,7 +4398,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -4442,7 +4481,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -4454,7 +4493,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -4520,7 +4560,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -4532,7 +4572,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -4642,7 +4683,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -4654,7 +4695,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -4724,7 +4766,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -4736,7 +4778,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -4855,7 +4898,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -4867,7 +4910,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -4937,7 +4981,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -4949,7 +4993,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -5047,7 +5092,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -5059,7 +5104,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -5124,7 +5170,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -5136,7 +5182,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -5234,7 +5281,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -5246,7 +5293,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -5311,7 +5359,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -5323,7 +5371,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -5468,7 +5517,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -5480,7 +5529,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -5551,7 +5601,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -5563,7 +5613,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -5667,7 +5718,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -5679,7 +5730,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -5750,7 +5802,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -5762,7 +5814,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -5863,7 +5916,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -5875,7 +5928,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -5979,7 +6033,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -5991,7 +6045,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -6094,7 +6149,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -6106,7 +6161,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -6162,7 +6218,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -6174,7 +6230,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -6273,7 +6330,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -6285,7 +6342,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -6341,7 +6399,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -6353,7 +6411,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -6566,7 +6625,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -6578,7 +6637,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -6634,7 +6694,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -6646,7 +6706,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -6745,7 +6806,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -6757,7 +6818,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -6813,7 +6875,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -6825,7 +6887,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -6950,7 +7013,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -6962,7 +7025,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -7026,7 +7090,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -7038,7 +7102,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -7140,7 +7205,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -7152,7 +7217,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -7209,7 +7275,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -7221,7 +7287,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -7296,7 +7363,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -7308,7 +7375,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -7364,7 +7432,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -7376,7 +7444,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -7478,7 +7547,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -7490,7 +7559,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -7546,7 +7616,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -7558,7 +7628,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -7683,7 +7754,7 @@ describe("Entity builder", () => { columnType: "timestamptz", type: "date", nullable: false, - + onCreate: expect.any(Function), defaultRaw: "now()", name: "created_at", fieldName: "created_at", @@ -7695,7 +7766,8 @@ describe("Entity builder", () => { columnType: "timestamptz", type: "date", nullable: false, - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), defaultRaw: "now()", name: "updated_at", fieldName: "updated_at", @@ -7753,7 +7825,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -7765,7 +7837,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -7821,7 +7894,7 @@ describe("Entity builder", () => { name: "created_at", fieldName: "created_at", defaultRaw: "now()", - + onCreate: expect.any(Function), nullable: false, getter: false, setter: false, @@ -7833,7 +7906,8 @@ describe("Entity builder", () => { name: "updated_at", fieldName: "updated_at", defaultRaw: "now()", - + onCreate: expect.any(Function), + onUpdate: expect.any(Function), nullable: false, getter: false, setter: false, diff --git a/packages/core/utils/src/dml/helpers/entity-builder/define-property.ts b/packages/core/utils/src/dml/helpers/entity-builder/define-property.ts index cc0d1b3dae..dcd68a6567 100644 --- a/packages/core/utils/src/dml/helpers/entity-builder/define-property.ts +++ b/packages/core/utils/src/dml/helpers/entity-builder/define-property.ts @@ -80,6 +80,7 @@ const SPECIAL_PROPERTIES: { nullable: false, fieldName: field.fieldName, defaultRaw: "now()", + onCreate: () => new Date(), })(MikroORMEntity.prototype, field.fieldName) }, updated_at: (MikroORMEntity, field) => { @@ -89,6 +90,8 @@ const SPECIAL_PROPERTIES: { nullable: false, fieldName: field.fieldName, defaultRaw: "now()", + onCreate: () => new Date(), + onUpdate: () => new Date(), })(MikroORMEntity.prototype, field.fieldName) }, deleted_at: (MikroORMEntity, field, tableName) => { diff --git a/packages/medusa-test-utils/src/__tests__/events.spec.ts b/packages/medusa-test-utils/src/__tests__/events.spec.ts index f2d65b2a82..ea8a5a0580 100644 --- a/packages/medusa-test-utils/src/__tests__/events.spec.ts +++ b/packages/medusa-test-utils/src/__tests__/events.spec.ts @@ -39,7 +39,13 @@ describe("waitSubscribersExecution", () => { }) it("should reject when timeout is reached before event is fired", async () => { - const waitPromise = waitSubscribersExecution(TEST_EVENT, eventBus as any) + const waitPromise = waitSubscribersExecution( + TEST_EVENT, + eventBus as any, + { + timeout: 5000, + } + ) jest.advanceTimersByTime(5100) diff --git a/packages/medusa-test-utils/src/events.ts b/packages/medusa-test-utils/src/events.ts index e19cc48955..1e7be09956 100644 --- a/packages/medusa-test-utils/src/events.ts +++ b/packages/medusa-test-utils/src/events.ts @@ -1,82 +1,175 @@ -import { IEventBusModuleService } from "@medusajs/framework/types" import { EventEmitter } from "events" -// Allows you to wait for all subscribers to execute for a given event. Only works with the local event bus. -export const waitSubscribersExecution = ( - eventName: string, - eventBus: IEventBusModuleService, - { - timeout = 5000, - }: { - timeout?: number - } = {} -) => { - const eventEmitter: EventEmitter = (eventBus as any).eventEmitter_ - const subscriberPromises: Promise[] = [] - const originalListeners = eventEmitter.listeners(eventName) - let timeoutId: NodeJS.Timeout | null = null +type EventBus = { + eventEmitter_: EventEmitter +} - // Create a promise that rejects after the timeout - const timeoutPromise = new Promise((_, reject) => { +type WaitSubscribersExecutionOptions = { + timeout?: number +} + +// Map to hold pending promises for each event. +const waits = new Map>() + +/** + * Creates a promise that rejects after a specified timeout. + * @param timeout - The timeout in milliseconds. + * @param eventName - The name of the event being waited on. + * @returns A tuple containing the timeout promise and a function to clear the timeout. + */ +const createTimeoutPromise = ( + timeout: number, + eventName: string | symbol +): [Promise, () => void] => { + let timeoutId: NodeJS.Timeout | null = null + const promise = new Promise((_, reject) => { timeoutId = setTimeout(() => { reject( new Error( - `Timeout of ${timeout}ms exceeded while waiting for event "${eventName}"` + `Timeout of ${timeout}ms exceeded while waiting for event "${String( + eventName + )}"` ) ) }, timeout) timeoutId.unref() }) + return [promise, () => timeoutId && clearTimeout(timeoutId)] +} + +// Core logic to wait for subscribers. +const doWaitSubscribersExecution = ( + eventName: string | symbol, + eventBus: EventBus, + { timeout = 15000 }: WaitSubscribersExecutionOptions = {} +): Promise => { + const eventEmitter = eventBus.eventEmitter_ + const subscriberPromises: Promise[] = [] + const [timeoutPromise, clearTimeout] = createTimeoutPromise( + timeout, + eventName + ) - // If there are no existing listeners, resolve once the event happens. Otherwise, wrap the existing subscribers in a promise and resolve once they are done. if (!eventEmitter.listeners(eventName).length) { - let ok + let ok: (value?: any) => void const promise = new Promise((resolve) => { ok = resolve }) - subscriberPromises.push(promise) - eventEmitter.on(eventName, ok) + + const newListener = async (...args: any[]) => { + eventEmitter.removeListener(eventName, newListener) + ok(...args) + } + + Object.defineProperty(newListener, "__isSubscribersExecutionWrapper", { + value: true, + configurable: true, + enumerable: false, + }) + + eventEmitter.on(eventName, newListener) } else { eventEmitter.listeners(eventName).forEach((listener: any) => { + if (listener.__isSubscribersExecutionWrapper) { + return + } + eventEmitter.removeListener(eventName, listener) - let ok, nok + let ok: (value?: any) => void, nok: (reason?: any) => void const promise = new Promise((resolve, reject) => { ok = resolve nok = reject }) subscriberPromises.push(promise) - const newListener = async (...args2) => { + const newListener = async (...args2: any[]) => { + // As soon as the subscriber is executed, we restore the original listener + eventEmitter.removeListener(eventName, newListener) + let listenerToAdd = listener + while (listenerToAdd.originalListener) { + listenerToAdd = listenerToAdd.originalListener + } + eventEmitter.on(eventName, listenerToAdd) + try { const res = await listener.apply(eventBus, args2) - ok(res) - - return res } catch (error) { nok(error) } } + Object.defineProperty(newListener, "__isSubscribersExecutionWrapper", { + value: true, + configurable: true, + enumerable: false, + }) + Object.defineProperty(newListener, "originalListener", { + value: listener, + configurable: true, + enumerable: false, + }) eventEmitter.on(eventName, newListener) }) } const subscribersPromise = Promise.all(subscriberPromises).finally(() => { // Clear the timeout since events have been fired and handled - if (timeoutId !== null) { - clearTimeout(timeoutId) - } - - // Restore original event listeners - eventEmitter.removeAllListeners(eventName) - originalListeners.forEach((listener) => { - eventEmitter.on(eventName, listener as (...args: any) => void) - }) + clearTimeout() }) // Race between the subscribers and the timeout return Promise.race([subscribersPromise, timeoutPromise]) } + +/** + * Allows you to wait for all subscribers to execute for a given event. + * It ensures that concurrent waits for the same event are queued and executed sequentially. + * + * @param eventName - The name of the event to wait for. + * @param eventBus - The event bus instance. + * @param options - Options including timeout. + */ +export const waitSubscribersExecution = ( + eventName: string | symbol, + eventBus: any, + options?: WaitSubscribersExecutionOptions +): Promise => { + const chain = waits.get(eventName) + + if (!chain) { + const newPromise = doWaitSubscribersExecution( + eventName, + eventBus, + options + ).finally(() => { + // Once this chain is done, remove it from the map + // if it's still the same promise. This prevents race conditions + // where a new wait is queued before this one is removed. + if (waits.get(eventName) === newPromise) { + waits.delete(eventName) + } + }) + waits.set(eventName, newPromise) + return newPromise + } + + const runner = () => { + return doWaitSubscribersExecution(eventName, eventBus, options) + } + + const newPromise = chain.then(runner, runner).finally(() => { + // Once this chain is done, remove it from the map + // if it's still the same promise. This prevents race conditions + // where a new wait is queued before this one is removed. + if (waits.get(eventName) === newPromise) { + waits.delete(eventName) + } + }) + + waits.set(eventName, newPromise) + + return newPromise +} diff --git a/packages/medusa-test-utils/src/medusa-test-runner-utils/wait-workflow-executions.ts b/packages/medusa-test-utils/src/medusa-test-runner-utils/wait-workflow-executions.ts new file mode 100644 index 0000000000..8d425f87af --- /dev/null +++ b/packages/medusa-test-utils/src/medusa-test-runner-utils/wait-workflow-executions.ts @@ -0,0 +1,35 @@ +import { Modules } from "@medusajs/framework/utils" +import { MedusaContainer } from "@medusajs/types" + +/** + * Waits for all workflow executions to finish. When relying on workflows but not necessarily + * waiting for them to finish, this can be used to ensure that a test is not considered done while background executions are still running and can interfere with the other tests. + * @param container - The container instance. + * @returns A promise that resolves when all workflow executions have finished. + */ +export async function waitWorkflowExecutions(container: MedusaContainer) { + const wfe = container.resolve(Modules.WORKFLOW_ENGINE, { + allowUnregistered: true, + }) + if (!wfe) { + return + } + + const timeout = setTimeout(() => { + throw new Error("Timeout waiting for workflow executions to finish") + }, 10000).unref() + + let waitWorkflowsToFinish = true + while (waitWorkflowsToFinish) { + const executions = await wfe.listWorkflowExecutions({ + state: { $nin: ["not_started", "done", "reverted", "failed"] }, + }) + + if (executions.length === 0) { + waitWorkflowsToFinish = false + clearTimeout(timeout) + break + } + await new Promise((resolve) => setTimeout(resolve, 50)) + } +} diff --git a/packages/medusa-test-utils/src/medusa-test-runner.ts b/packages/medusa-test-utils/src/medusa-test-runner.ts index d15bdb200a..abfd6cbc04 100644 --- a/packages/medusa-test-utils/src/medusa-test-runner.ts +++ b/packages/medusa-test-utils/src/medusa-test-runner.ts @@ -18,6 +18,7 @@ import { startApp, syncLinks, } from "./medusa-test-runner-utils" +import { waitWorkflowExecutions } from "./medusa-test-runner-utils/wait-workflow-executions" export interface MedusaSuiteOptions { dbConnection: any // knex instance @@ -34,6 +35,9 @@ export interface MedusaSuiteOptions { clientUrl: string } getMedusaApp: () => MedusaAppOutput + utils: { + waitWorkflowExecutions: (container: MedusaContainer) => Promise + } } interface TestRunnerConfig { @@ -268,6 +272,7 @@ class MedusaTestRunner { public async afterEach(): Promise { try { + await waitWorkflowExecutions(this.globalContainer as MedusaContainer) await this.dbUtils.teardown({ schema: this.schema }) } catch (error) { logger.error("Error tearing down database:", error?.message) @@ -287,6 +292,10 @@ class MedusaTestRunner { clientUrl: this.dbConfig.clientUrl, }, dbUtils: this.dbUtils, + utils: { + waitWorkflowExecutions: () => + waitWorkflowExecutions(this.globalContainer as MedusaContainer), + }, } } } diff --git a/packages/modules/workflow-engine-inmemory/src/utils/workflow-orchestrator-storage.ts b/packages/modules/workflow-engine-inmemory/src/utils/workflow-orchestrator-storage.ts index 22d32c589b..bad9a32d1f 100644 --- a/packages/modules/workflow-engine-inmemory/src/utils/workflow-orchestrator-storage.ts +++ b/packages/modules/workflow-engine-inmemory/src/utils/workflow-orchestrator-storage.ts @@ -157,6 +157,7 @@ export class InMemoryDistributedTransactionStorage .catch(() => undefined) if (trx) { + const { flow, errors } = this.storage.get(key) ?? {} const { idempotent } = options ?? {} const execution = trx.execution as TransactionFlow @@ -183,9 +184,9 @@ export class InMemoryDistributedTransactionStorage } return { - flow: trx.execution as TransactionFlow, + flow: flow ?? (trx.execution as TransactionFlow), context: trx.context?.data as TransactionContext, - errors: trx.context?.errors as TransactionStepError[], + errors: errors ?? (trx.context?.errors as TransactionStepError[]), } } diff --git a/packages/modules/workflow-engine-redis/integration-tests/__tests__/index.spec.ts b/packages/modules/workflow-engine-redis/integration-tests/__tests__/index.spec.ts index 47280fc4af..f8c264c13f 100644 --- a/packages/modules/workflow-engine-redis/integration-tests/__tests__/index.spec.ts +++ b/packages/modules/workflow-engine-redis/integration-tests/__tests__/index.spec.ts @@ -1153,7 +1153,7 @@ moduleIntegrationTestRunner({ const notExpiredWorkflowId = "not-expired-workflow-" + ulid() createWorkflow( - { name: notExpiredWorkflowId, retentionTime: 1000 }, + { name: notExpiredWorkflowId, retentionTime: 10000 }, () => { return new WorkflowResponse("not expired") } diff --git a/packages/modules/workflow-engine-redis/src/utils/workflow-orchestrator-storage.ts b/packages/modules/workflow-engine-redis/src/utils/workflow-orchestrator-storage.ts index 99e2210646..6c93e74b88 100644 --- a/packages/modules/workflow-engine-redis/src/utils/workflow-orchestrator-storage.ts +++ b/packages/modules/workflow-engine-redis/src/utils/workflow-orchestrator-storage.ts @@ -291,6 +291,15 @@ export class RedisDistributedTransactionStorage .catch(() => undefined) if (trx) { + const rawData = await this.redisClient.get(key) + + let flow!: TransactionFlow, errors!: TransactionStepError[] + if (rawData) { + const data = JSON.parse(rawData) + flow = data.flow + errors = data.errors + } + const { idempotent } = options ?? {} const execution = trx.execution as TransactionFlow @@ -317,9 +326,9 @@ export class RedisDistributedTransactionStorage } return { - flow: trx.execution as TransactionFlow, + flow: flow ?? (trx.execution as TransactionFlow), context: trx.context?.data as TransactionContext, - errors: trx.context?.errors as TransactionStepError[], + errors: errors ?? (trx.context?.errors as TransactionStepError[]), } }