Skip to content

feat(router): Web Standards GenFetch dispatch arm + fetch bench cells (#58, #59) - #82

Merged
devin-ai-integration[bot] merged 7 commits into
mainfrom
devin/1792348542-genfetch-bench
Oct 18, 2026
Merged

devin-ai-integration[bot] merged 7 commits into
mainfrom
devin/1792348542-genfetch-bench

Conversation

@espetro

@espetro espetro commented Oct 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes #58, closes #59.

#58 — Web Standards-shaped GenDispatch arm. New GenFetch/DispatchFetchFn contract (contracts/route-contract-fetch.md, ROUTE_CONTRACT_VERSION → 4): dispatchFetch takes the same normalized primitives _dispatchPrim consumes (method, url, headers, webReq, body, bodyU8, FetchResponseSink) and returns Promise<boolean>. app.fetch/app.fetchShim consult app._genFetch first and decline to _dispatchPrim on false. @chttp/unplugin emits a sibling module <stem>.gen.fetch.ts beside routes.gen.ts; apps wire it via app.withFetchDispatch(new CompiledFetchRoutes(app)).

FetchResponseSink gains streaming members — writeHead arms ReadableStream mode, write() enqueues, endStream() closes — so streamSSE/streamText emit real chunked ReadableStream bodies under app.fetch (verified by new stream tests), not buffered strings. Two latent fetch-path bugs fixed along the way: runChainPromise didn't catch synchronous chain throws (unhandled rejection instead of 500) and allow405Promise never expanded * / GET→HEAD in Allow.

#59 — fetch bench cells + v2 re-baseline. bench/apps/chttp-fetch.ts now serves the canonical table through app.fetch behind a node:http bridge that builds a real Request per message (kept its scriptc-gate routes, still 100%); new apps/chttp-elf-fetch.ts serves the same table through app.fetchShim under scriptc (new Request is not runtime-constructible there). run.sh gains chttp-fetch-node, chttp-fetch-bun, chttp-scriptc, chttp-elf-fetch.

Bench headline (fresh 9-subject run, all cells non-zero):

  • chttp-elf-fetch ≈ chttp-scriptc (93–140%) — the fetch-shaped dispatch arm is at parity; the arm itself costs nothing measurable.
  • chttp-fetch-node = 53–73% of chttp-node — misses bench: add chttp-fetch + chttp-elf-fetch cells, re-baseline v2 on PR #56 numbers #59's 80–95% prediction; the gap is undici Request/Response construction + text() re-buffering in the bridge, not dispatch (proven by the ELF parity row). chttp-fetch-bun = 55–93% of chttp-bun, same shape smaller penalty.
  • Raw controls did not hold ±5% on echo/deep cells this run — flagged in the caveats, same-run vs raw-node ratios are the stable read.

Verified: pnpm -r test green (87 router incl. new genfetch parity, 24 stream, 21 unplugin e2e incl. a real emitted module driving app.fetch/fetchShim), bash scripts/scriptc-gate.sh 10/10 at 100%, lint/fmt clean, docs:build ok, fixture builds + serves with both arms wired.

Link to Devin session: https://app.devin.ai/sessions/467f2bf46881408bbd9398b50997bc23
Open in Devin Desktop: https://app.devin.ai/desktop/session/467f2bf46881408bbd9398b50997bc23?variant=devin
Requested by: @espetro

contracts/route-contract-fetch.md: a parallel contract to route-contract.md
for the fetch surface. GenFetch.dispatchFetch takes the same normalized
primitives _dispatchPrim consumes (method/url/headers/webReq/body/bodyU8/
FetchResponseSink) and returns Promise<boolean>; app.fetch and app.fetchShim
try the emitted dispatch first and decline to _dispatchPrim on false.
ROUTE_CONTRACT_VERSION bumps to v4 across both arms.

FetchResponseSink gains streaming members: writeHead arms ReadableStream
mode, write() enqueues through the stream controller (buffered until
toResponse() hands it over), endStream() closes it — SSE handlers produce
a chunked ReadableStream body, not a buffered string.

Also fixes two latent fetch-path divergences: runChainPromise did not
catch a synchronous chain throw (unhandled rejection instead of 500),
and allow405Promise never expanded * or GET->HEAD in the Allow header.
ChunkStream gains a FetchStreamWriter arm: when constructed without a
ServerResponse (c._nodeRes === null) it writes through the ResponseSink
streaming members, so streamSSE/streamText produce a real chunked
ReadableStream under app.fetch. The Node arm is unchanged; the
connection: keep-alive header stays Node-only (forbidden header name).
emitfetch.ts mirrors emitGenModule against the Web Standards contract:
the emitted class extends GenFetch and its dispatchFetch takes normalized
primitives, builds ReqView through the contract surface (_seedPm/_setWeb/
_setBody), and runs chains through _guardFetch/_bufferFetch. generate()
writes the fetch sibling beside routes.gen.ts unconditionally; contract
stamp bumps to v4. e2e covers a real emitted module driving app.fetch
and app.fetchShim end to end.
Regenerates .chttp/ artifacts at contract v4 and wires
CompiledFetchRoutes via app.withFetchDispatch so the fixture exercises
the emitted fetch dispatch at startup.
apps/chttp-fetch.ts is now the canonical route set served through
app.fetch (a node:http bridge builds a real Request per message) — it
keeps its scriptc-gate routes (/url, /vars, /cookies) and stays at 100%
coverage. apps/chttp-elf-fetch.ts serves the same table through
app.fetchShim for the scriptc ELF cell. run.sh gains chttp-fetch-node,
chttp-fetch-bun, chttp-scriptc, and chttp-elf-fetch subjects; the
Dockerfile builds the new ELF.
Adds the 2026-10-18 section: chttp-fetch-node/-bun/-elf-fetch medians on
the canonical 8-cell matrix, cross-compares, and caveats. Headline: the
fetch-shaped dispatch arm is at parity with the Node arm
(chttp-elf-fetch 93-140% of chttp-scriptc); the app.fetch node:http
bridge pays undici Request/Response churn (53-73% of chttp-node,
below the 80-95% prediction — documented). Raw controls did not hold
+/-5% on echo/deep cells this run; flagged rather than smoothed.
@devin-ai-integration

Copy link
Copy Markdown
Contributor

I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".

  • Disable automatic comment, CI, and merge conflict monitoring

@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying chttpjs with  Cloudflare Pages  Cloudflare Pages

Latest commit: 3fea8be
Status: ✅  Deploy successful!
Preview URL: https://5f14c474.chttpjs.pages.dev
Branch Preview URL: https://devin-1792348542-genfetch-be.chttpjs.pages.dev

View logs

@devin-ai-integration
devin-ai-integration Bot merged commit 43816dd into main Oct 18, 2026
3 checks passed
@devin-ai-integration
devin-ai-integration Bot deleted the devin/1792348542-genfetch-bench branch October 18, 2026 19:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant