Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@
* a write terminal (`create`, `update`, `delete`) is a type error
* *and* a runtime error — it cannot be smuggled through with a cast
* on one side without failing on the other.
* - On a cache hit, telemetry's `afterExecute` event reports
* `source: 'middleware'`. Telemetry is wired in front of the cache
* in `db.ts`, so observability still works for cached reads.
* - On a cache hit, every registered middleware's `afterExecute` still
* fires and reports `source: 'middleware'` — the `slowQueryWarning`
* middleware in `db.ts` observes cached reads too — so observability
* is preserved even though the driver is skipped.
* - Schema migrations rotate `meta.storageHash`, which feeds
* `contentHash`, so cached entries from a previous schema cannot
* accidentally serve queries against the new schema.
Expand Down
8 changes: 6 additions & 2 deletions examples/prisma-next-demo/src/prisma/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,12 @@ export const db = postgres<Contract>({
contractJson,
extensions: [pgvector],
middleware: [
// Cache first so its `intercept` short-circuits before any downstream
// middleware (`lints`, `budgets`) fires on a hit. The cache stores
// Cache first: interceptors are consulted in registration order and
// the first non-`undefined` result wins, so the cache gets first
// claim. A hit skips only the driver call and per-row `onRow` hooks:
// every middleware's `beforeExecute` (`lints`, `budgets`) has already
// run before any `intercept` is consulted, and `afterExecute` still
// fires for all of them with `source: 'middleware'`. The cache stores
// raw rows; the runtime still runs `decodeRow` on the hit path, so
// consumers see decoded values in both cases.
createCacheMiddleware({ maxEntries: 1_000 }),
Expand Down
13 changes: 7 additions & 6 deletions packages/3-extensions/middleware-cache/src/cache-middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,12 +100,13 @@ async function resolveCacheKey(
* The middleware uses three hooks:
*
* - `intercept` — on each execution, checks the cache. On a hit, returns
* the cached raw rows; the runtime skips `beforeExecute`, `runDriver`,
* and `onRow`, and yields the cached rows to the consumer (which, in
* the SQL runtime, sees them after the standard `decodeRow` pass —
* i.e. the cache stores wire-format values). On a miss, records a
* pending buffer keyed on the `exec` object identity and returns
* `undefined` (passthrough).
* the cached raw rows; the runtime skips `runDriver` and `onRow`
* (`beforeExecute` is not affected — it has already run for every
* middleware before any `intercept` is consulted) and yields the
* cached rows to the consumer (which, in the SQL runtime, sees them
* after the standard `decodeRow` pass — i.e. the cache stores
* wire-format values). On a miss, records a pending buffer keyed on
* the `exec` object identity and returns `undefined` (passthrough).
* - `onRow` — on the miss path, appends each row yielded by the driver
* to the pending buffer.
* - `afterExecute` — on the miss path, commits the buffer to the store
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -774,3 +774,13 @@ updated to the shipped forms. No code, API, contract shape, or emitted
artefact changes. No extension-author action required. Incidental docs-only
diff.
-->

<!--
PR #915 (middleware doc-comment lifecycle fixes): comments-only. The only
`packages/3-extensions/` touch is doc comments in
`packages/3-extensions/middleware-cache/src/cache-middleware.ts`, correcting
stale claims about the cache-hit lifecycle (a hit skips only the driver call
and per-row `onRow` hooks; `beforeExecute` has already run, `afterExecute`
still fires; `decodeRow` still runs). No SPI or behavioural change.
No user action required. Incidental substrate diff only.
-->
Original file line number Diff line number Diff line change
Expand Up @@ -316,3 +316,15 @@ vitest `retry` config that absorbs a known intermittent PGlite (WASM) abort. A
re-emit picks up any contract shape. No user action required. Incidental
substrate diff only.
-->

<!--
PR #915 (middleware doc-comment lifecycle fixes): comments-only. The only
`examples/` touches are doc comments in
`examples/prisma-next-demo/src/prisma/db.ts` and
`examples/prisma-next-demo/src/orm-client/find-user-by-id-cached.ts`,
correcting stale claims about what runs on a cache-middleware hit (every
`beforeExecute` has already run before `intercept` is consulted,
`afterExecute` still fires with `source: 'middleware'`, and `decodeRow`
still runs on the hit path). No code, contract, or emitted-artefact change.
No user action required. Incidental substrate diff only.
-->
Loading