nodejs / nodejs/undici

deduplicate: aborting the primary request rejects the other callers in the group

Open
#5,711 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
JavaScript
Stars
7.7k
Forks
879
Avg merge
2d 16h
Merged PRs (30d)
68

Description

Summary

With interceptors.deduplicate(), aborting the first request of a coalesced group also rejects every other caller waiting on it — including callers that passed no signal at all.

I have a fix and tests, but it changes the interceptor's semantics rather than patching a slip, so I would rather agree the intended behaviour with you before sending a PR.

Reproduction

Two concurrent requests to the same resource through the deduplicate interceptor. The first carries an AbortSignal (a timeout, a cancelled UI action); the second carries none.

waiter outcome -> rejected: AbortError / This operation was aborted

The waiter had no signal of its own.

Where it comes from

DeduplicationHandler hands the primary caller the real dispatch controller (lib/handler/deduplication-handler.js:147-149). When that caller aborts, api-request.js:92 calls controller.abort(reason) on the real controller, the network request is cancelled, and onResponseError (:290-305) settles every waiting handler with AbortError.

The existing tests cover the inverse case — aborting a deduplicated request, from #5673 — but not this direction.

The question

For a request coalescer, I would expect the group to survive as long as any member still wants the response: the primary's abort should detach that caller, and the underlying request should only be cancelled once nobody is left waiting. Otherwise coalescing is not transparent, and whether your request succeeds depends on who else happened to ask first and whether they had a timeout.

If that is the intended semantics, I have it working locally: the primary gets a proxied controller (same shape as the existing #createWaitingHandler), abort settles only the primary, and the real dispatch is aborted only when the primary is gone and no waiting handler remains. Roughly 95 lines in the handler.

Two details that fell out of writing the tests:

  • The pendingRequests entry was not being released when every member of a group aborted, so a later request could join a request with no consumers left. That needed fixing too.
  • Behaviour with no waiters is unchanged: the abort propagates exactly as it does today.

Tests: the new case fails on main with AbortError where a body was expected, and passes with the change. test/interceptors/deduplicate.js goes to 38/38; cache.js and retry.js stay at 103/103.

Happy to open the PR, or to take a different shape if you would rather the group be torn down with its primary — in which case the pendingRequests leak is still worth fixing on its own.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with lib/handler/deduplication-handler.js:147-149 and api-request.js:92,290-305 to trace how primary aborts settle the group. Read the existing abort tests in test/interceptors/deduplicate.js and reproduce the failing primary-abort case. Done means the intended semantics are confirmed, the all-aborted pendingRequests case is covered, and the relevant interceptor tests pass.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, nodejs
Domain
api, backend-api-design
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.