p-queue icon indicating copy to clipboard operation
p-queue copied to clipboard

Aborting pending and waiting tasks at the same time hangs the queue

Open klimashkin opened this issue 3 years ago • 4 comments

If we have one pending and one waiting task and abort them both, then the queue gets stuck with one pending task forever and gets blocked

import PQueue, {AbortError} from 'p-queue';

const queue = new PQueue({concurrency: 1});

const controller1 = new AbortController();
const controller2 = new AbortController();

try {
	const task1 = queue.add(({signal}) => fetch('https://sindresorhus.com', {signal}), {signal: controller1.signal});
	const task2 = queue.add(({signal}) => fetch('https://example.com', {signal}), {signal: controller2.signal});


          setTimeout(() => {
                  controller1.abort();
                  controller2.abort();
          
                  queue; // Size: 1  Pending: 1
          }, 0)

        await task1;
        await task2;
} catch (error) {
	if (!(error instanceof AbortError)) {
		throw error;
	}
}

klimashkin avatar Sep 19 '22 08:09 klimashkin

// @Richienb

sindresorhus avatar Sep 19 '22 09:09 sindresorhus

I believe a robust solution will be to properly implement a way to dequeue items which will be a breaking change. Similar to https://github.com/sindresorhus/p-queue/issues/140

Richienb avatar Sep 19 '22 09:09 Richienb

That is a blocker for everyone using a signal in .add

The workaround is to manually check for the aborted signal at the beginning of the task, something like

.add(() => {
    if (controller.signal.aborted) {
      throw new AbortError('The task was aborted.');
    }

    ...
})

klimashkin avatar Sep 19 '22 15:09 klimashkin

I think that the main reason is that aborted tasks that are not currently executing, will move and stuck on pending state.

Rotemy avatar Sep 20 '22 11:09 Rotemy

Any plan for release?

rajsync avatar Feb 03 '23 00:02 rajsync