Repository navigation
Conversation
undici@8 eagerly calls setGlobalDispatcher(new Agent()) at module load
when Symbol.for("undici.globalDispatcher.2") is unset, overwriting the
legacy Symbol.for("undici.globalDispatcher.1") slot that Node's built-in
fetch reads. With NODE_USE_ENV_PROXY=1, that slot holds Node's
EnvHttpProxyAgent, so importing the TCVDB client silently disabled
HTTP(S)_PROXY for every fetch in the process (L1/Skill extraction then
fail with "Cannot connect to API").
Load undici lazily on first request instead of at module scope, and
snapshot/restore the legacy dispatcher slot across the import so a
pre-configured dispatcher survives. The HTTPS custom-CA Agent creation
moves to the same lazy path, keeping construction side-effect free.
Add regression tests covering both the import side effect and a full
request round-trip against a local HTTP server.
Fixes TencentCloud#1157
Signed-off-by: dvd233 <111864431+dvd233@users.noreply.github.com>
Signed-off-by: dvd233 <111864431+dvd233@users.noreply.github.com>
|
Thanks @dvd233 — lazy-loading "undici" looks like a good way to remove the SQLite-mode side effect. I noticed one concurrency edge in the snapshot/restore guard: const previousLegacy = g[LEGACY_GLOBAL_DISPATCHER]; undiciModulePromise = import("undici").then((mod) => { This assumes every change to the legacy slot while "import("undici")" is pending came from undici. A possible interleaving is:
So the fix can itself overwrite a newer process-wide networking decision. Could restoration be conditional on proving that the current value is the compatibility dispatcher installed by this undici initialization, rather than restoring whenever the value merely changed? I’d also add a regression where the legacy slot changes during the lazy import and assert that the newer value survives. This is separate from #1157’s original bug: preserving the dispatcher present before undici initialization is correct; the question is ownership of a later concurrent change. AI-assisted source review; I have not reproduced this with a real concurrent "setGlobalDispatcher()" + delayed module loader yet, so I’d treat it as a lifecycle/concurrency contract question rather than a confirmed production failure. |
Signed-off-by: dvd233 <111864431+dvd233@users.noreply.github.com>
2325203 to
0ad1b09
Compare

Description | 描述
Fixes #1157. Importing the TCVDB client must not overwrite the legacy global dispatcher used by Node's built-in
fetch, including a configured proxy dispatcher.Load undici lazily on the first TCVDB request, using synchronous CommonJS loading to keep the dispatcher snapshot and restoration in one turn. This also avoids restoring a stale snapshot over a concurrent dispatcher replacement. Construction remains free of undici's global initialization side effects; the TCVDB request/HTTPS-agent behavior remains with the existing client.
Verification | 验证
npm run buildis not passing:build:seed-v2reports TS5058 becausescripts/seed-v2/tsconfig.jsonis missing. Running the complete build at the original PR head reproduced the same failure; the package scripts and missing path are unchanged by this PR.DCO | 签署
The author confirmed the DCO submission rights and authorized correcting the two existing commits. Their code trees, author/committer metadata, and upstream parent are unchanged; only their own DCO trailers and the necessarily regenerated merge signature changed. The follow-up commit also carries the author's sign-off. Recovery refs retain the original commits.
Prepared and verified with Codex assistance. Automated verification does not replace maintainer review or establish official CI success.