diff --git a/src/subscribe.test.ts b/src/subscribe.test.ts index 0105de5..79c634b 100644 --- a/src/subscribe.test.ts +++ b/src/subscribe.test.ts @@ -358,3 +358,35 @@ it('stops retrying persistent routine if teardown is called', async () => { expect(onChange.callCount).toBe(firstCallCount); }); + +it('does not begin the new routine until the interrupted routine has completed', async () => { + const trigger = { + ...defaultTrigger, + interruptible: true, + persistent: true, + retry: { + maxTimeout: 100, + retries: 1, + }, + }; + + const onChange = sinon.stub(trigger, 'onChange'); + + onChange.resolves(async () => { + await wait(100); + }); + + const subscription = await subscribe(trigger); + + void subscription.trigger([]); + + await wait(10); + + void subscription.trigger([]); + + await wait(10); + + subscription.activeTask?.abortController?.abort(); + + expect(onChange.callCount).toBe(1); +}); diff --git a/src/subscribe.ts b/src/subscribe.ts index 69e990a..0668b54 100644 --- a/src/subscribe.ts +++ b/src/subscribe.ts @@ -227,7 +227,13 @@ export const subscribe = (trigger: Trigger): Subscription => { outerActiveTask.abortController.abort(); + const abortedTaskPromise = outerActiveTask.promise; + outerActiveTask = null; + + // Do not start a new task until the previous task has been + // aborted and the shutdown routine has run to completion. + await abortedTaskPromise; } else { if (trigger.persistent) { log.warn(