Skip to content

fix: cancel extension fetch proxy requests - #587

Closed
JustYannicc wants to merge 115 commits into
SuperCmdLabs:mainfrom
JustYannicc:codex/perf-wave4-extension-fetch-proxy
Closed

fix: cancel extension fetch proxy requests#587
JustYannicc wants to merge 115 commits into
SuperCmdLabs:mainfrom
JustYannicc:codex/perf-wave4-extension-fetch-proxy

Conversation

@JustYannicc

Copy link
Copy Markdown
Collaborator

What changed

  • Moved the renderer extension fetch proxy into a small extension-fetch-bridge helper that generates a request ID for every proxied HTTP(S) fetch.
  • Wired init.signal and Request.signal aborts to electron.cancelHttpRequest(requestId) and removed abort listeners on every terminal proxied path.
  • Preserved native fetch fallback for non-HTTP URLs and IPC-unsupported bodies, and kept the binary download response path intact.
  • Replaced sync zlib response decoding in the main HTTP proxy with async zlib decoding and a single-settle guard for cancel, timeout, socket error, redirect, and decode completion races.
  • Added targeted tests for abort propagation/listener cleanup and async compressed response decoding.

Why

Extension-level fetch() requests could be abandoned after an extension unmounted or aborted, but the bridge did not pass requestId, so main-process sockets/work stayed alive until natural completion. Large compressed proxied responses also decoded synchronously on the Electron main thread, creating a cross-extension stall risk.

Compatibility impact

HTTP(S) extension fetch responses keep the same Response construction, headers, status fields, URL override, native fallback behavior, and binary download handling. Aborted proxied fetches now reject with AbortError, matching platform fetch semantics, while non-HTTP and unsupported body requests continue through native fetch.

How tested

  • node --test scripts/test-extension-fetch-proxy-abort.mjs scripts/test-http-response-decode-async.mjs scripts/test-use-fetch-stale-runs.mjs
  • pnpm run build:main
  • pnpm run typecheck:renderer
  • pnpm run build:renderer
  • Codex LSP diagnostics on src/renderer/src/extension-fetch-bridge.ts, src/renderer/src/ExtensionView.tsx, src/main/http-response-decode.ts, and src/main/main.ts: no diagnostics found.

Performance evidence

Abort/request cleanup before: extension fetch IPC sent { url, method, headers, body } with no requestId, so http-request-cancel could not reach activeHttpRequests; abort listeners were not part of the bridge.

Abort/request cleanup after: scripts/test-extension-fetch-proxy-abort.mjs verifies each proxied fetch sends an extensionFetch: request ID, duplicate aborts emit exactly one cancel for that ID, the abort listener count goes 1 -> 0 after completion, and the success path finishes with zero abort listeners and no cancel calls. Existing stale-run coverage in scripts/test-use-fetch-stale-runs.mjs still passes for request replacement/unmount cancellation patterns.

Decompression before: main proxy used brotliDecompressSync, gunzipSync, and inflateSync before converting full response bodies to UTF-8.

Decompression after: src/main/http-response-decode.ts uses async zlib APIs only; the deterministic gzip fixture test confirmed decoded text compatibility and logged event-loop timer evidence for a 9,800,000 byte fixture. Test run evidence: sync baseline delayed the timer by 24.78 ms while async decode allowed it at 1.466 ms; repeat validation after the type fix logged 4.612 ms sync vs 2.802 ms async.

Stack validation

Started from detached base 206eab8280a2eb91a57e4e74ea6df99e45a55cb4 and created codex/perf-wave4-extension-fetch-proxy. No coordinator markdown, playbooks, prompts, or generated lockfiles are included.

Replaces

Replaces the perf wave 4 coordinator finding for extension fetch proxy abort propagation and compressed response main-thread stall risk.

…perf-wave2-integration-stack-20260704

# Conflicts:
#	src/renderer/src/raycast-api/hooks/use-cached-promise.ts
…perf-wave2-integration-stack-20260704

# Conflicts:
#	src/renderer/src/raycast-api/list-runtime-renderers.tsx
#	src/renderer/src/raycast-api/list-runtime.tsx
…perf-wave2-integration-stack-20260704

# Conflicts:
#	src/renderer/src/CameraExtension.tsx
…perf-wave2-integration-stack-20260704

# Conflicts:
#	src/renderer/src/raycast-api/list-runtime.tsx
…perf-wave2-integration-stack-20260704

# Conflicts:
#	scripts/bench-script-command-discovery.mjs
#	scripts/benchmark-file-search-delete-batch.mjs
#	scripts/lib/script-command-runner-harness.mjs
#	scripts/lib/ts-import.mjs
#	scripts/test-file-search-delete-batch.mjs
#	scripts/test-script-command-runner.mjs
#	src/main/file-search-index.ts
#	src/main/main.ts
…perf-wave2-integration-stack-20260704

# Conflicts:
#	scripts/lib/script-command-runner-harness.mjs
#	scripts/lib/ts-import.mjs
#	scripts/test-extension-lifecycle-sandbox.mjs
#	scripts/test-script-command-runner.mjs
#	src/main/main.ts
#	src/renderer/src/ExtensionView.tsx
…perf-wave2-integration-stack-20260704

# Conflicts:
#	.github/workflows/project-checks.yml
#	scripts/test-root-search-perf.mjs
#	src/renderer/src/CameraExtension.tsx
#	src/renderer/src/raycast-api/list-runtime.tsx
…erf-wave3-integration-stack-20260704

# Conflicts:
#	package.json
#	scripts/measure-extension-bundle-cache.mjs
#	scripts/test-icon-runtime-file-icon-cache.mjs
#	src/main/extension-runner.ts
#	src/renderer/src/components/HiddenExtensionRunners.tsx
#	src/renderer/src/raycast-api/icon-runtime-render.tsx
…/perf-wave3-integration-stack-20260704

# Conflicts:
#	scripts/test-browser-search-performance.mjs
#	scripts/test-root-search-perf.mjs
@JustYannicc

Copy link
Copy Markdown
Collaborator Author

Closing in favor of #601, which fully replaces this granular PR in the wave4 runtime/main consolidation. Literal validation now passes with /opt/homebrew/opt/node@22/bin/npm run build:main, and #601 is ready for review.

@JustYannicc JustYannicc closed this Jul 5, 2026
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.

1 participant