feat: add per-request store API (getRequestStore)#608
feat: add per-request store API (getRequestStore)#608JamesbbBriz wants to merge 1 commit intocloudflare:mainfrom
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 625d36e5e7
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (!isInsideUnifiedScope()) { | ||
| return new Map(); |
There was a problem hiding this comment.
Keep middleware request store stable within a request
getRequestStore() returns a brand-new Map whenever isInsideUnifiedScope() is false, which means callers outside a unified scope never see stable per-request state. In Pages Router middleware, execution is wrapped with runWithExecutionContext but not runWithRequestContext, so this branch is always taken there; two getRequestStore() calls in the same middleware invocation won't share data, and values set in middleware cannot be read later in that request path, which breaks the advertised per-request middleware behavior.
Useful? React with 👍 / 👎.
Add getRequestStore() — a per-request key-value store backed by vinext's existing AsyncLocalStorage infrastructure. Resolution order: 1. Unified scope (App Router, Pages Router API routes) → userStore 2. Fallback ALS (middleware with only ExecutionContext) → stable Map 3. Outside any scope (tests, top-level) → fresh empty Map Also wraps Pages Router API route handlers in unified request context so getRequestStore() works consistently across all code paths. Changes: - shims/unified-request-context.ts: add userStore field - shims/request-store.ts: new module with 3-tier resolution - server/api-handler.ts: wrap Pages Router API handler (dev) - entries/pages-server-entry.ts: wrap Pages Router API handler (prod) - package.json: add vinext/request-store export
cd3f29c to
5e3cb12
Compare
|
/bigbonk review this PR |
Summary
Add
getRequestStore()— a per-request key-value store backed by vinext's existing unifiedAsyncLocalStoragescope. Values are isolated per request and automatically garbage-collected when the request completes.Primary use case: per-request database clients on Cloudflare Workers, where global singletons cause alternating request failures (#537).
API
Similar pattern to SvelteKit
event.locals, Honoc.set/get, Remixcontext.Scope
Works in all code paths:
api-handler.ts)pages-server-entry.ts)Changes
shims/unified-request-context.tsuserStore: Map<string, unknown>toUnifiedRequestContext+ default increateRequestContext()shims/request-store.tsgetRequestStore()public APIserver/api-handler.tsrunWithRequestContext(dev server)entries/pages-server-entry.ts_runWithUnifiedCtx(prod/Workers)package.json"./request-store"exportMotivation
We're running a production SaaS on vinext + Cloudflare Workers (Free plan) with Prisma v7 + Hyperdrive + R2 + NextAuth. We hit the exact alternating-failure pattern from #537 and initially worked around it with a 50ms TTL heuristic. This PR provides the proper framework-level solution.
vinext already has the
UnifiedRequestContext+AsyncLocalStorageinfrastructure. This PR exposes it to users via a clean public API — 73 lines across 5 files, zero breaking changes.Test plan
Closes #537