From af17d25e74765a40154c7b685b9268cded3a024e Mon Sep 17 00:00:00 2001 From: Copilot <223556219+Copilot@users.noreply.github.com> Date: Tue, 3 Mar 2026 20:52:37 +0000 Subject: [PATCH] fix: clear orchestrationQueueSet in InMemoryOrchestrationBackend.reset() The reset() method clears the orchestrationQueue array but does not clear the orchestrationQueueSet. When an orchestration is created and reset() is called before the orchestration is dequeued, the Set retains the stale instance ID. Any subsequent createInstance() call with the same ID after reset is silently skipped by enqueueOrchestration() because the Set still reports the ID as present. This causes the orchestration to never be processed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../src/testing/in-memory-backend.ts | 1 + .../test/in-memory-backend.spec.ts | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/packages/durabletask-js/src/testing/in-memory-backend.ts b/packages/durabletask-js/src/testing/in-memory-backend.ts index 3f65e98..4d88923 100644 --- a/packages/durabletask-js/src/testing/in-memory-backend.ts +++ b/packages/durabletask-js/src/testing/in-memory-backend.ts @@ -382,6 +382,7 @@ export class InMemoryOrchestrationBackend { reset(): void { this.instances.clear(); this.orchestrationQueue.length = 0; + this.orchestrationQueueSet.clear(); this.activityQueue.length = 0; for (const waiters of this.stateWaiters.values()) { for (const waiter of waiters) { diff --git a/packages/durabletask-js/test/in-memory-backend.spec.ts b/packages/durabletask-js/test/in-memory-backend.spec.ts index 56e5f15..4923ab9 100644 --- a/packages/durabletask-js/test/in-memory-backend.spec.ts +++ b/packages/durabletask-js/test/in-memory-backend.spec.ts @@ -286,4 +286,26 @@ describe("In-Memory Backend", () => { const state = await client.getOrchestrationState(id); expect(state).toBeUndefined(); }); + + it("should allow reusing instance IDs after reset", async () => { + const orchestrator: TOrchestrator = async (_: OrchestrationContext, input: number) => { + return input * 2; + }; + + // Create an orchestration without starting the worker, so it stays in the queue + const instanceId = "reuse-test-id"; + backend.createInstance(instanceId, getName(orchestrator), JSON.stringify(10)); + + // Reset while the orchestration is still queued (not yet processed) + backend.reset(); + + // Now create a new orchestration with the same instance ID and process it + worker.addOrchestrator(orchestrator); + await worker.start(); + + await client.scheduleNewOrchestration(orchestrator, 21, instanceId); + const state = await client.waitForOrchestrationCompletion(instanceId, true, 10); + expect(state?.runtimeStatus).toEqual(OrchestrationStatus.COMPLETED); + expect(state?.serializedOutput).toEqual(JSON.stringify(42)); + }); });