perf(edge): hand requests only the Function answers on before the middleware

SO
19h ago
+1308-90

Summary

Hand requests the edge can only pass on to the Function on before running the application's middleware at the edge, so the Function runs the middleware itself: one dispatch instead of two in series.

Why

Under a matching middleware, several request kinds ran the middleware at the edge (a dispatch to its Worker) and were then handed to the Function anyway (a second dispatch, behind the first) — where a plain rsc request goes to the Function at once. Those kinds are:

  • a router's payload request only the Function can render: a member of a class whose record proves no member's Flight, or a page whose record holds a resume, asked for other than as a static prefetch;
  • a static Pages page or Pages fallback, which a middleware's decision always makes private.

And a route body's record was read only once the middleware had answered, in series behind it.

Handing them on at once removes a serial round trip — and a cold middleware Worker's start — from time to first byte; reading a body's record beside the middleware takes the read off the path behind it.

Changes

  • handlers/payload-ahead.ts (payloadAhead, asked after middlewareMatches and before the header rules) hands on, with rsc-payload-ahead and no middleware outcome:

    • a member of a class with a shell under a policy that reads no member's own record (memberFlightUnproved, now shared with partGeneration);
    • a page with no build payload whose record holds a resume, asked for other than as a static prefetch. This is known from the record the isolate holds (new non-touching SharedByteLru.peek; an expired one is still read again behind, as answering it would have), or, holding none, from the build's delivery, with the record read behind the response so the next request is judged by the record. Not judged under a hold of zero.

    Build payloads, partial fallbacks, upgraded and shell-less members, static prefetches and complete held records still run the middleware at the edge.

  • HostedGate.handOn(configured), asked once a matcher covers the request and before anything else is begun, reusing the rules already judged:

    • static pages and Pages fallbacks hand on (static-page-private); their rewrites already went to the Function.
  • Route bodies still run the middleware — it may rewrite onto a shipped file, which the edge serves from storage and the Function need not carry — but their record read now begins beside it (start) and is taken by the answer or let go to finish into memory (abandon); none is begun for a body no answer would take it for (private project or validation, application credentials on the classified request, header rules that are conditioned, refuse sharing or set a cookie).

  • Local check: accepts rsc-payload-ahead only where it holds (covered path, generations served, no partial fallback, one of the two kinds, no middleware decision kept), and records peeked records as evidence.

  • README, README.ja and the core README say which requests go to the application before its middleware.

Tests

  • New edge suite payload-ahead.test.ts, detecting middleware dispatches by MIDDLEWARE_ONLY_HEADER: both kinds hand on with no dispatch; shell-less members, partial fallbacks, upgraded members, static prefetches and complete held records still run the middleware; a page with nothing held is handed on and the next request is answered at the edge.
  • A non-prefetch partial-fallback case in partial-fallback-wiring.test.ts.
  • Static-page and fallback-page cases with no middleware dispatch; route-body cases: a read that begins beside the middleware, none for a body the Function answers whatever the middleware decides, and a shipped file a body with credentials is rewritten to still served from storage.
  • Local unit tests for the new checker case (part-handoffs.test.ts), accept/reject cases in check.test.ts, and evidence capture for peek.
  • Existing tests are updated where the dispatch count or read timing intentionally changes.
  • The new tests were checked to fail with the logic disabled.
  • Locally: the touched and neighbouring edge suites, the local part-handoffs/generation-evidence/check suites, eslint, oxfmt, tsc (edge, local), check:vocabulary.

Notes

  • The one accepted divergence, as for plain rsc requests: a middleware rewrite onto a large shipped file the Function does not carry. Static pages and Pages fallbacks already handed a rewrite on to the Function, so nothing changes for them.
  • A HEAD payload request meeting the same conditions is also handed on before the middleware (it was handed on after it before).
  • The after-middleware privacy branches of static and fallback pages are kept as a backstop, though no covered request reaches them now.

Review fixes

  • The core README names a validation request among what hands a body on before the middleware; the payload passage in servedAtEdge is reworded (cubic).

  • Codex (route-body.ts, handing a private body on before the middleware loses a rewrite onto a shipped file): route bodies run the middleware again; only the record read moved beside it.

Not changed

  • cubic (payload-ahead.ts, a class member handed on whatever its prefetch header and with no check for a held generation): partGeneration already handed such a member to the Function for a static prefetch as for a navigation; the only generation it waived the rule for is a shell-less member's own record, which never reaches payloadAhead (classification.entry is undefined for one).
  • cubic (part-handoffs.ts, accepting rsc-payload-ahead by delivery where a complete generation was seen): the evidence is the stack's, not one request's, and a complete generation is held after a legitimate ahead handoff — the read behind it brings it in — so rejecting on it would fail handoffs the edge made rightly.