TML-3072: fold ref-paired snapshots into the content-addressed store - #1024
Conversation
|
Warning Review limit reached
Next review available in: 19 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (37)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
size-limit report 📦
|
@prisma-next/extension-author-tools
@prisma-next/mongo-runtime
@prisma-next/family-mongo
@prisma-next/sql-runtime
@prisma-next/family-sql
@prisma-next/extension-arktype-json
@prisma-next/middleware-cache
@prisma-next/mongo
@prisma-next/extension-paradedb
@prisma-next/extension-pgvector
@prisma-next/extension-postgis
@prisma-next/postgres
@prisma-next/sql-orm-client
@prisma-next/sqlite
@prisma-next/extension-supabase
@prisma-next/target-mongo
@prisma-next/adapter-mongo
@prisma-next/driver-mongo
@prisma-next/contract
@prisma-next/utils
@prisma-next/config
@prisma-next/errors
@prisma-next/framework-components
@prisma-next/operations
@prisma-next/ts-render
@prisma-next/contract-authoring
@prisma-next/ids
@prisma-next/psl-parser
@prisma-next/psl-printer
@prisma-next/cli
@prisma-next/cli-telemetry
@prisma-next/config-loader
@prisma-next/emitter
@prisma-next/language-server
@prisma-next/migration-tools
prisma-next
@prisma-next/vite-plugin-contract-emit
@prisma-next/mongo-codec
@prisma-next/mongo-contract
@prisma-next/mongo-value
@prisma-next/mongo-contract-psl
@prisma-next/mongo-contract-ts
@prisma-next/mongo-emitter
@prisma-next/mongo-schema-ir
@prisma-next/mongo-query-ast
@prisma-next/mongo-orm
@prisma-next/mongo-query-builder
@prisma-next/mongo-lowering
@prisma-next/mongo-wire
@prisma-next/sql-contract
@prisma-next/sql-errors
@prisma-next/sql-operations
@prisma-next/sql-schema-ir
@prisma-next/sql-contract-psl
@prisma-next/sql-contract-ts
@prisma-next/sql-contract-emitter
@prisma-next/sql-lane-query-builder
@prisma-next/sql-relational-core
@prisma-next/sql-builder
@prisma-next/target-postgres
@prisma-next/target-sqlite
@prisma-next/adapter-postgres
@prisma-next/adapter-sqlite
@prisma-next/driver-postgres
@prisma-next/driver-sqlite
commit: |
…the store
A ref is now only its refs/<name>.json pointer ({hash, invariants}); the
contract it names resolves through migrations/snapshots/<hex>/ by the
pointer's hash. The ADR-218 paired sibling files (refs/<name>.contract.json
/ .contract.d.ts) are neither written nor read: contractAt's ref branch
reads pointer-then-store (provenance retagged 'snapshot' -> 'ref'),
ref-advancement and ref set write store-then-pointer (write-if-absent), and
ref delete removes only the pointer — store entries are shared by hash.
refs/snapshot.ts is deleted; a pointer whose store entry is missing is a
hard MIGRATION.CONTRACT_SNAPSHOT_MISSING error, and the pointer-absent
error is renamed MIGRATION.REF_NOT_RESOLVABLE to describe what it now
means. The one-shot migrator folds existing ref pairs into the store, and
the 0.16-to-0.17 upgrade instructions (both skills) document the layout
change. ADR 218 carries a status note; ADR 240's path-to-one-store section
now states the fold as shipped.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
854ce6d to
13a42b1
Compare
Linked issue
Refs TML-3072. Stacked on #1018 (TML-3059, the content-addressed snapshot store this folds into); review and merge that first.
At a glance
Before this PR a ref was the pointer plus paired sibling files
refs/prod.contract.json/refs/prod.contract.d.ts— a full contract copy per ref, duplicating bytes the snapshot store already holds.Decision
A ref is now only its
refs/<name>.jsonpointer; the contract it names resolves throughmigrations/snapshots/<hex>/by the pointer's hash. The ADR-218 ref-paired snapshot files are neither written nor read anywhere,refs/snapshot.tsis deleted, and "snapshot" stops being an overloaded concept: ref = pointer, one content-addressed store. The one-shot layout migrator from #1018 also folds any existing ref pairs, so downstream trees convert in the same single run. Design record: the "Snapshot concept boundary, and the path to one store" section of ADR 240, now stated as shipped; ADR 218 carries a status note.Reviewer notes
ref deleteno longer deletes contract bytes. Store entries are shared by hash — another ref or a migration bookend may reference the same contract — so delete removes only the pointer. Orphan store entries are by design (content-addressed, write-if-absent); the old orphan-healing logic is deleted with nothing to heal.MIGRATION.CONTRACT_SNAPSHOT_MISSINGerror, never a silent fallback to graph-node resolution (one e2e scenario asserting that fallback was deleted — its premise no longer exists). The pointer-absent error is renamedMIGRATION.SNAPSHOT_MISSING→MIGRATION.REF_NOT_RESOLVABLEwith text describing what it now means; error codes are new in 0.17 (ADR 239), so the rename ships before any release carries the old name.ContractAtResult.provenanceliteral'snapshot'→'ref'— the old name was inverted (the literal store read was tagged'graph-node'while'snapshot'meant the refs read). Swept throughplan-resolution.ts,migration-plan.tsoutput, and tests.contractAtnow returns the pointer's hash for the ref branch (authoritative), not the caller's hash argument; pinned by a test.How it fits together
contractAt's ref branch (aggregate.ts) reads the pointer viareadRef, then the store entry keyed by the pointer's hash. Pointer absent → existing graph-node fallback →REF_NOT_RESOLVABLE.executeRefAdvancement(db init/db update/migrate --advance-ref) writes store-then-pointer;ref setjust writes the pointer (it reads the bytes from the store, so the store write is a guaranteed no-op).ref deleteunlinks the pointer only.scripts/migrate-migrations-layout.mjsgains a refs step: plan (pointer must exist, innerstorage.storageHashmust equal the pointer's hash,.d.tsmust exist — any violation aborts before a single write across all roots), then apply (write-if-absent into the store, delete the pair, pointer untouched).**/refs/*.contract.jsondetection glob.Behavior changes & evidence
ref set/ advancement write no paired files;ref deleteleaves store bytes. Impl: ref.ts, ref-advancement.ts. Evidence: ref.test.ts, cli.ref-pointer-integration.e2e.test.ts (renamed from cli.ref-snapshot-integration)..d.ts).Summary
Removes the last full-contract copies in the RC-frozen
migrations/layout so every contract snapshot (migration bookend, ref, extension head) lives behind one hash-addressed store. Sequenced before the RC layout freeze becauserefs/<name>.contract.*is public on-disk surface.Testing performed
pnpm build,pnpm typecheck(143/143),pnpm lint:deps,pnpm lint:throws(delta 0),pnpm lint:casts(−5),pnpm lint:framework-vocabulary,pnpm fixtures:checkpnpm test:packages— 13,325 passed (migration-tools 585, cli 1,350)pnpm test:integration— 1,172 passed (one run hit the known sql-orm-client PGlite parallel-load flake, "portal C_N does not exist", in 3 files; full re-run 1,172/1,172 green)pnpm test:e2e— 109 passed;pnpm test:scripts— all passedpnpm check:upgrade-coverage --mode pr,pnpm check:release-notes --mode pr,pnpm lint:skillsSkill update
Both 0.16-to-0.17 upgrade-instruction files gained a
ref-paired-snapshots-moved-to-content-addressed-storeentry;skills/prisma-next-migrations/SKILL.mdandskills/prisma-next-migration-review/SKILL.mdreworded to the pointer+store model.Alternatives considered
ref deletewhen unreferenced. Rejected: requires reference counting across refs and graph nodes for no benefit; orphan content-addressed entries are inert and reclaimed naturally by the migrator/regen flows.SNAPSHOT_MISSINGerror too. Kept: it serves a second, unrelated scenario (viaRef: false) that was never part of the paired-snapshot model; only the migration-tools error whose meaning actually changed was renamed.Checklist
git commit -s) per the DCO.TML-NNNN: <sentence-case title>form.