Repository navigation
feat(router): Web Standards GenFetch dispatch arm + fetch bench cells (#58, #59) - #82
Merged
Merged
Conversation
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.
Contributor
|
I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".
|
Deploying chttpjs with
|
| Latest commit: |
3fea8be
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://5f14c474.chttpjs.pages.dev |
| Branch Preview URL: | https://devin-1792348542-genfetch-be.chttpjs.pages.dev |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #58, closes #59.
#58 — Web Standards-shaped GenDispatch arm. New
GenFetch/DispatchFetchFncontract (contracts/route-contract-fetch.md,ROUTE_CONTRACT_VERSION→ 4):dispatchFetchtakes the same normalized primitives_dispatchPrimconsumes (method, url, headers, webReq, body, bodyU8, FetchResponseSink) and returnsPromise<boolean>.app.fetch/app.fetchShimconsultapp._genFetchfirst and decline to_dispatchPrimonfalse.@chttp/unpluginemits a sibling module<stem>.gen.fetch.tsbesideroutes.gen.ts; apps wire it viaapp.withFetchDispatch(new CompiledFetchRoutes(app)).FetchResponseSinkgains streaming members —writeHeadarms ReadableStream mode,write()enqueues,endStream()closes — sostreamSSE/streamTextemit real chunkedReadableStreambodies underapp.fetch(verified by new stream tests), not buffered strings. Two latent fetch-path bugs fixed along the way:runChainPromisedidn't catch synchronous chain throws (unhandled rejection instead of 500) andallow405Promisenever expanded*/GET→HEADinAllow.#59 — fetch bench cells + v2 re-baseline.
bench/apps/chttp-fetch.tsnow serves the canonical table throughapp.fetchbehind a node:http bridge that builds a realRequestper message (kept its scriptc-gate routes, still 100%); newapps/chttp-elf-fetch.tsserves the same table throughapp.fetchShimunder scriptc (new Requestis not runtime-constructible there).run.shgainschttp-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% ofchttp-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 undiciRequest/Responseconstruction +text()re-buffering in the bridge, not dispatch (proven by the ELF parity row).chttp-fetch-bun= 55–93% ofchttp-bun, same shape smaller penalty.vs raw-noderatios are the stable read.Verified:
pnpm -r testgreen (87 router incl. new genfetch parity, 24 stream, 21 unplugin e2e incl. a real emitted module drivingapp.fetch/fetchShim),bash scripts/scriptc-gate.sh10/10 at 100%, lint/fmt clean,docs:buildok, 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