fix: Remove scheduled workflows if they no longer exist when executed (#7673)

This commit is contained in:
Stevche Radevski
2024-06-11 12:57:25 +02:00
committed by GitHub
parent 8e2a42b786
commit 3d72002c28
7 changed files with 103 additions and 20 deletions

View File

@@ -2,6 +2,7 @@ import { MedusaApp } from "@medusajs/modules-sdk"
import {
TransactionStepTimeoutError,
TransactionTimeoutError,
WorkflowManager,
} from "@medusajs/orchestration"
import { RemoteQueryFunction } from "@medusajs/types"
import { TransactionHandlerType, TransactionStepState } from "@medusajs/utils"
@@ -316,5 +317,23 @@ describe("Workflow Orchestrator module", function () {
await setTimeout(3100)
expect(spy).toHaveBeenCalledTimes(2)
})
it("should remove scheduled workflow if workflow no longer exists", async () => {
const spy = await createScheduled("remove-scheduled", {
cron: "* * * * * *",
})
const logSpy = jest.spyOn(console, "warn")
await setTimeout(1100)
expect(spy).toHaveBeenCalledTimes(1)
WorkflowManager["workflows"].delete("remove-scheduled")
await setTimeout(1100)
expect(spy).toHaveBeenCalledTimes(1)
expect(logSpy).toHaveBeenCalledWith(
"Tried to execute a scheduled workflow with ID remove-scheduled that does not exist, removing it from the scheduler."
)
})
})
})

View File

@@ -7,7 +7,7 @@ import {
TransactionStep,
} from "@medusajs/orchestration"
import { ModulesSdkTypes } from "@medusajs/types"
import { TransactionState, promiseAll } from "@medusajs/utils"
import { MedusaError, TransactionState, promiseAll } from "@medusajs/utils"
import { WorkflowOrchestratorService } from "@services"
import { Queue, Worker } from "bullmq"
import Redis from "ioredis"
@@ -123,11 +123,24 @@ export class RedisDistributedTransactionStorage
jobId: string,
schedulerOptions: SchedulerOptions
) {
// TODO: In the case of concurrency being forbidden, we want to generate a predictable transaction ID and rely on the idempotency
// of the transaction to ensure that the transaction is only executed once.
return await this.workflowOrchestratorService_.run(jobId, {
throwOnError: false,
})
try {
// TODO: In the case of concurrency being forbidden, we want to generate a predictable transaction ID and rely on the idempotency
// of the transaction to ensure that the transaction is only executed once.
return await this.workflowOrchestratorService_.run(jobId, {
throwOnError: false,
})
} catch (e) {
if (e instanceof MedusaError && e.type === MedusaError.Types.NOT_FOUND) {
console.warn(
`Tried to execute a scheduled workflow with ID ${jobId} that does not exist, removing it from the scheduler.`
)
await this.remove(jobId)
return
}
throw e
}
}
async get(key: string): Promise<TransactionCheckpoint | undefined> {