Skip to content

fix(client): cancel unused connection attempts - #74

Open
ronag wants to merge 1 commit into
nxtedition:masterfrom
ronag:codex/fix-connector-pending-abort-20260829
Open

fix(client): cancel unused connection attempts#74
ronag wants to merge 1 commit into
nxtedition:masterfrom
ronag:codex/fix-connector-pending-abort-20260829

Conversation

@ronag

@ronag ronag commented Aug 29, 2026

Copy link
Copy Markdown
Member

Summary

  • adapt Cancel connection attempts after queued requests abort nodejs/undici#5662 to this reduced HTTP/1.1, request-only fork
  • reject pre-aborted and queued requests immediately while a connector is pending
  • give each connection attempt an abort signal and cancel it only when no queued request still depends on it
  • ignore late connector callbacks, destroy stale sockets, and keep intentional preconnect attempts intact
  • expose the attempt signal in the connector type contract

The upstream stream, pipeline, connect, upgrade, retry-interceptor, and HTTP/2 paths are not present in this fork and are intentionally excluded.

Upstream reference: nodejs#5662

Validation

Exact head: d4d6dc5259caf743c05b5e135580926e13e6a3a6 on Node.js v26.7.0

  • focused connector-abort regression: 8 passed
  • full unit matrix: 583 passed, 6 skipped
  • full Node integration matrix: 151 passed
  • TypeScript declaration tests: passed
  • full npm run lint: passed
  • git diff --check: passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adapts upstream undici behavior to cancel unused in-flight connection attempts by propagating an abort signal into connector calls and ensuring queued/pre-aborted requests are rejected promptly while a connection is still pending.

Changes:

  • Adds request-driven connection-attempt cancellation via per-attempt AbortController, ignoring late connector callbacks and cleaning up stale sockets/contexts.
  • Introduces an internal request-to-client abort hook (kRequestSignal) to reject pre-aborted and queued-aborted requests promptly during connecting.
  • Updates connector typings/tests and adds targeted regression tests covering abort-while-connecting and shared-attempt cancellation behavior.

Reviewed changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated no comments.

Show a summary per file
File Description
test/types/index.test.ts Extends type assertions to cover signal on connector options.
test/client-abort-while-connecting.js Adds regression tests for aborting requests and cancelling unused connection attempts.
lib/dispatcher/client.js Implements attempt-level aborting/cancellation and ignores late connector completions.
lib/core/symbols.js Exports kRequestSignal for internal request abort wiring.
lib/core/request.js Adds early-abort listener management/cleanup for queued requests.
lib/core/connect.js Threads signal into the built-in connector and destroys sockets on attempt abort.
lib/api/api-request.js Bridges API-layer abort handling into dispatcher via kRequestSignal.
index.d.ts Exposes signal?: AbortSignal on buildConnector option contract.
Suppressed comments (1)

lib/core/connect.js:188

  • signal-driven cancellation can be missed when the signal is already aborted before the abort listener is attached (not all EventTarget/AbortSignal-like implementations guarantee a late-added 'abort' listener will fire). Other parts of the codebase defensively check signal?.aborted before wiring listeners (e.g., lib/api/readable.js:331-333). Consider eagerly destroying the socket when signal.aborted is already true to ensure connection attempts are cancelled promptly in this case.
    socket
      .setNoDelay(true)
      .once(protocol === 'https:' ? 'secureConnect' : 'connect', function () {
        cleanup()

        if (callback) {
          const cb = callback
          callback = null
          cb(null, this)
        }
      })
      .on('error', function (err) {
        cleanup()

        if (callback) {
          const cb = callback
          callback = null
          cb(maybeNormalizeConnectError(err, this, { timeout, hostname, port }), null)
        }
      })

    return socket

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@ronag
ronag marked this pull request as ready for review August 29, 2026 20:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants