Repository navigation
feat(transport): bypass keep-alive pool reuse for configured hosts via OCX_FRESH_CONNECTION_HOSTS #4804
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(transport): bypass keep-alive pool reuse for configured hosts via OCX_FRESH_CONNECTION_HOSTS #4804
Changes from all commits
6f5fafe
7d0d024
c719c8a
83668e1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -43,6 +43,31 @@ export function safeOriginLabel(url: string): string { | |
| } | ||
| } | ||
|
|
||
| /** | ||
| * Check whether a target host should bypass Bun's keep-alive pool reuse. | ||
| * Configured via the `OCX_FRESH_CONNECTION_HOSTS` environment variable (comma-separated). | ||
| */ | ||
| export function wantsFreshConnection( | ||
| input: Parameters<typeof globalThis.fetch>[0], | ||
| hostsEnv = process.env.OCX_FRESH_CONNECTION_HOSTS, | ||
| ): boolean { | ||
| if (!hostsEnv) return false; | ||
| try { | ||
| const rawUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url; | ||
| const host = new URL(rawUrl).hostname.toLowerCase(); | ||
| const targets = hostsEnv | ||
| .split(",") | ||
| .map(h => h.trim().toLowerCase().replace(/^\.+/, "")) | ||
| .filter(Boolean); | ||
| for (const target of targets) { | ||
| if (host === target || host.endsWith(`.${target}`)) return true; | ||
| } | ||
| } catch { | ||
| /* unparseable target URL keeps default connection behavior */ | ||
| } | ||
| return false; | ||
| } | ||
|
|
||
|
|
||
|
|
||
| export interface PaceAwareFetch { | ||
|
|
@@ -83,8 +108,19 @@ export function providerFetch( | |
| ) as typeof globalThis.fetch; | ||
| const httpFetch = Object.assign( | ||
| async (input: Parameters<typeof globalThis.fetch>[0], init?: RequestInit) => { | ||
| options.beforeDispatch?.(new Headers(init?.headers ?? (input instanceof Request ? input.headers : undefined))); | ||
| const dispatchInit = { ...withUpstreamHttpVersion(input, init, provider), timeout: 0 }; | ||
| const headers = new Headers(init?.headers ?? (input instanceof Request ? input.headers : undefined)); | ||
| const fresh = wantsFreshConnection(input); | ||
| options.beforeDispatch?.(headers); | ||
| if (fresh) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win 🔎 Supported by static analysis🏁 Script executed: sed -n '40,135p' src/server/responses/fetch-helpers.ts
sed -n '385,465p' src/server/responses/request-transport.ts
sed -n '315,365p' src/server/chat-native.ts
rg -n -C 5 'dispatchOverride|rebuilt\.url|activeRequest|wantsFreshConnection|fresh-connection' src testsRepository: lidge-jun/opencodex Length of output: 50375 🏁 Script executed: set -e
printf '%s\n' '--- fetch helper and transport helper bindings ---'
sed -n '1,145p' src/server/responses/fetch-helpers.ts
sed -n '360,460p' src/server/responses/request-transport.ts
printf '%s\n' '--- native Chat send path ---'
sed -n '300,365p' src/server/chat-native.ts
printf '%s\n' '--- recovery-init definition ---'
rg -n -C 8 'function applyUpstreamRecoveryInit|const applyUpstreamRecoveryInit|applyUpstreamRecoveryInit' src/server src
printf '%s\n' '--- fresh connection tests ---'
sed -n '1,180p' tests/responses/fresh-connection-optout.test.ts
printf '%s\n' '--- native and OAuth callers around fetch ---'
rg -n -C 8 'fetchWithHeaderTimeout\(|providerFetch\(activeProvider|dispatchOverride: oauthDispatch' src/server/chat-native.ts src/server/responses/adapter-dispatch.ts src/server/responses/adapter-continuation.tsRepository: lidge-jun/opencodex Length of output: 50376 🏁 Script executed: set -e
printf '%s\n' '--- upstream retry helper ---'
rg -n 'export (function|const) applyUpstreamRecoveryInit|applyUpstreamRecoveryInit' src/lib/upstream-retry.ts
sed -n '1,180p' src/lib/upstream-retry.ts
printf '%s\n' '--- fresh connection tests ---'
sed -n '1,180p' tests/responses/fresh-connection-optout.test.ts
printf '%s\n' '--- native request construction ---'
sed -n '245,305p' src/server/chat-native.ts
rg -n -C 4 'function buildActiveRequest|const buildActiveRequest|buildActiveRequest' src/server/chat-native.ts
printf '%s\n' '--- AdapterRequest declarations and builders ---'
rg -n -C 5 'interface AdapterRequest|type AdapterRequest' src/server src/adaptersRepository: lidge-jun/opencodex Length of output: 19841 🏁 Script executed: set -e
printf '%s\n' '--- recovery-init implementation ---'
sed -n '450,490p' src/lib/upstream-retry.ts
printf '%s\n' '--- native passthrough request builder ---'
rg -n -C 10 'buildOpenAIChatPassthroughRequest' src
printf '%s\n' '--- Connection/keepalive construction in native request path ---'
rg -n -C 3 'Connection|keepalive' src/server/chat-native.ts src/adapters src/server/responses/fetch-helpers.tsRepository: lidge-jun/opencodex Length of output: 22844 Recompute fresh-connection settings after dispatch overrides rebuild the destination.
The native Chat override can rebuild Recompute 🤖 Prompt for AI Agents |
||
| headers.set("Connection", "close"); | ||
| } | ||
| const versioned = withUpstreamHttpVersion(input, init, provider); | ||
| const dispatchInit = { | ||
| ...versioned, | ||
| timeout: 0, | ||
| headers, | ||
| ...(fresh ? { keepalive: false } : {}), | ||
| }; | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| return options.dispatchOverride | ||
| ? options.dispatchOverride(input, dispatchInit, dispatch) | ||
| : dispatch(input, dispatchInit); | ||
|
|
@@ -211,3 +247,4 @@ export async function fetchWithHeaderTimeout( | |
| clearTimeout(timer); | ||
| } | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,143 @@ | ||
| import { describe, expect, test } from "bun:test"; | ||
| import { wantsFreshConnection, providerFetch } from "../../src/server/responses/fetch-helpers"; | ||
| import type { OcxProviderConfig } from "../../src/types"; | ||
|
|
||
| describe("wantsFreshConnection", () => { | ||
| test("returns false when env is unset or empty", () => { | ||
| expect(wantsFreshConnection("https://opencode.ai/zen/v1", undefined)).toBe(false); | ||
| expect(wantsFreshConnection("https://opencode.ai/zen/v1", "")).toBe(false); | ||
| expect(wantsFreshConnection("https://opencode.ai/zen/v1", " ")).toBe(false); | ||
| }); | ||
|
|
||
| test("matches exact hostname and subdomain suffixes case-insensitively, trimming leading dots", () => { | ||
| const env = "opencode.ai, .API.Cloudflare.Com"; | ||
| expect(wantsFreshConnection("https://opencode.ai/zen/v1", env)).toBe(true); | ||
| expect(wantsFreshConnection("https://api.opencode.ai/zen/v1", env)).toBe(true); | ||
| expect(wantsFreshConnection("https://api.cloudflare.com/v1", env)).toBe(true); | ||
| expect(wantsFreshConnection("https://other-cloudflare.com/v1", env)).toBe(false); | ||
| expect(wantsFreshConnection("https://notopencode.ai/v1", env)).toBe(false); | ||
| }); | ||
|
|
||
| test("returns false for unparseable URLs without throwing", () => { | ||
| expect(wantsFreshConnection("::not-a-url::", "opencode.ai")).toBe(false); | ||
| }); | ||
| }); | ||
|
|
||
| describe("providerFetch fresh connection dispatch", () => { | ||
| test("injects Connection: close and keepalive: false when host matches env", async () => { | ||
| const previous = process.env.OCX_FRESH_CONNECTION_HOSTS; | ||
| process.env.OCX_FRESH_CONNECTION_HOSTS = "special-relay.test"; | ||
| let observedInit: RequestInit | undefined; | ||
|
|
||
| const dummyProvider: OcxProviderConfig = { | ||
| adapter: "openai-responses", | ||
| baseUrl: "https://special-relay.test/v1", | ||
| fetch: (async (_input, init) => { | ||
| observedInit = init; | ||
| return new Response("ok", { status: 200 }); | ||
| }) as typeof globalThis.fetch, | ||
| }; | ||
|
|
||
| try { | ||
| const fetcher = providerFetch(dummyProvider); | ||
| await fetcher("https://special-relay.test/v1/responses", { method: "POST" }); | ||
|
|
||
| expect(observedInit).toBeDefined(); | ||
| expect((observedInit as any)?.keepalive).toBe(false); | ||
| const headers = new Headers(observedInit?.headers); | ||
| expect(headers.get("Connection")).toBe("close"); | ||
| } finally { | ||
| if (previous === undefined) delete process.env.OCX_FRESH_CONNECTION_HOSTS; | ||
| else process.env.OCX_FRESH_CONNECTION_HOSTS = previous; | ||
| } | ||
| }); | ||
|
|
||
| test("overwrites caller Connection: keep-alive header when fresh connection is enforced", async () => { | ||
| const previous = process.env.OCX_FRESH_CONNECTION_HOSTS; | ||
| process.env.OCX_FRESH_CONNECTION_HOSTS = "special-relay.test"; | ||
| let observedInit: RequestInit | undefined; | ||
|
|
||
| const dummyProvider: OcxProviderConfig = { | ||
| adapter: "openai-responses", | ||
| baseUrl: "https://special-relay.test/v1", | ||
| fetch: (async (_input, init) => { | ||
| observedInit = init; | ||
| return new Response("ok", { status: 200 }); | ||
| }) as typeof globalThis.fetch, | ||
| }; | ||
|
|
||
| try { | ||
| const fetcher = providerFetch(dummyProvider); | ||
| await fetcher("https://special-relay.test/v1/responses", { | ||
| method: "POST", | ||
| headers: { Connection: "keep-alive" }, | ||
| }); | ||
|
|
||
| expect((observedInit as any)?.keepalive).toBe(false); | ||
| const headers = new Headers(observedInit?.headers); | ||
| expect(headers.get("Connection")).toBe("close"); | ||
| } finally { | ||
| if (previous === undefined) delete process.env.OCX_FRESH_CONNECTION_HOSTS; | ||
| else process.env.OCX_FRESH_CONNECTION_HOSTS = previous; | ||
| } | ||
| }); | ||
|
|
||
| test("accepts a Request object as input and applies fresh connection settings", async () => { | ||
| const previous = process.env.OCX_FRESH_CONNECTION_HOSTS; | ||
| process.env.OCX_FRESH_CONNECTION_HOSTS = ".special-relay.test"; | ||
| let observedInit: RequestInit | undefined; | ||
|
|
||
| const dummyProvider: OcxProviderConfig = { | ||
| adapter: "openai-responses", | ||
| baseUrl: "https://sub.special-relay.test/v1", | ||
| fetch: (async (_input, init) => { | ||
| observedInit = init; | ||
| return new Response("ok", { status: 200 }); | ||
| }) as typeof globalThis.fetch, | ||
| }; | ||
|
|
||
| try { | ||
| const fetcher = providerFetch(dummyProvider); | ||
| const req = new Request("https://sub.special-relay.test/v1/responses", { | ||
| method: "POST", | ||
| headers: { "x-custom": "value" }, | ||
| }); | ||
| await fetcher(req); | ||
|
|
||
| expect((observedInit as any)?.keepalive).toBe(false); | ||
| const headers = new Headers(observedInit?.headers); | ||
| expect(headers.get("Connection")).toBe("close"); | ||
| expect(headers.get("x-custom")).toBe("value"); | ||
| } finally { | ||
| if (previous === undefined) delete process.env.OCX_FRESH_CONNECTION_HOSTS; | ||
| else process.env.OCX_FRESH_CONNECTION_HOSTS = previous; | ||
| } | ||
| }); | ||
|
|
||
| test("preserves default keepalive and headers when host is not configured", async () => { | ||
| const previous = process.env.OCX_FRESH_CONNECTION_HOSTS; | ||
| delete process.env.OCX_FRESH_CONNECTION_HOSTS; | ||
| let observedInit: RequestInit | undefined; | ||
|
|
||
| const dummyProvider: OcxProviderConfig = { | ||
| adapter: "openai-responses", | ||
| baseUrl: "https://normal-relay.test/v1", | ||
| fetch: (async (_input, init) => { | ||
| observedInit = init; | ||
| return new Response("ok", { status: 200 }); | ||
| }) as typeof globalThis.fetch, | ||
| }; | ||
|
|
||
| try { | ||
| const fetcher = providerFetch(dummyProvider); | ||
| await fetcher("https://normal-relay.test/v1/responses", { method: "POST" }); | ||
|
|
||
| expect(observedInit).toBeDefined(); | ||
| expect((observedInit as any)?.keepalive).toBeUndefined(); | ||
| const headers = new Headers(observedInit?.headers); | ||
| expect(headers.has("Connection")).toBe(false); | ||
| } finally { | ||
| if (previous !== undefined) process.env.OCX_FRESH_CONNECTION_HOSTS = previous; | ||
| } | ||
| }); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Document
OCX_FRESH_CONNECTION_HOSTS.This adds a user-configurable environment variable, but this cohort has no
docs-site/update. Document its comma-separated values, exact and subdomain matching, and itsConnection: closeandkeepalive: falseeffect.As per coding guidelines, “Update
docs-site/when the change affects user-visible behavior or configuration.”🤖 Prompt for AI Agents
Source: Coding guidelines