|
6 | 6 | // undici is a hard dependency, but we still import it lazily inside the guard |
7 | 7 | // so browser bundlers don't pull undici (and its node:* deps) into the bundle |
8 | 8 | // when the SDK is loaded in a non-Node environment. |
| 9 | +// |
| 10 | +// The promise is cached so concurrent first calls share a single Agent — |
| 11 | +// without this, two parallel calls could each create and race to assign an |
| 12 | +// Agent, leaving the loser orphaned (never closed). |
9 | 13 | type UndiciAgent = InstanceType<typeof import("undici").Agent> |
10 | 14 |
|
11 | | -let nodeDispatcher: UndiciAgent | undefined | null |
12 | | - |
13 | | -async function ensureDispatcher() { |
14 | | - if (nodeDispatcher !== undefined) return nodeDispatcher |
15 | | - if (typeof process === "undefined" || !process.versions || process.versions.bun) { |
16 | | - nodeDispatcher = null |
17 | | - return null |
18 | | - } |
19 | | - const { Agent } = await import("undici") |
20 | | - nodeDispatcher = new Agent({ headersTimeout: 0, bodyTimeout: 0 }) |
21 | | - return nodeDispatcher |
22 | | -} |
| 15 | +const nodeDispatcher: Promise<UndiciAgent | null> = |
| 16 | + typeof process === "undefined" || !process.versions || process.versions.bun |
| 17 | + ? Promise.resolve(null) |
| 18 | + : import("undici").then(({ Agent }) => new Agent({ headersTimeout: 0, bodyTimeout: 0 })) |
23 | 19 |
|
24 | 20 | export async function nodeFetchWithDispatcher(req: Request) { |
25 | | - const dispatcher = await ensureDispatcher() |
| 21 | + const dispatcher = await nodeDispatcher |
26 | 22 | if (!dispatcher) return fetch(req) |
27 | 23 | return fetch(req, { dispatcher } as RequestInit) |
28 | 24 | } |
0 commit comments