feat(migrations): add maven_versions.size_bytes column, backfill, and index

Summary

Step 1 of the Maven version size accounting plan (issue #550 (closed)): add maven_versions.size_bytes per ADR-007's artifact-level storage accounting, with the backfill and the size-ordered partial index.

  • ColumnADD COLUMN size_bytes bigint NOT NULL DEFAULT 0. The constant default keeps the ADD metadata-only (no table rewrite) on PG 11+, so old and new binaries coexist in a rolling deploy.
  • Backfill — a set-based recompute grouped by version: distinct blob_sha256 per maven_version_id from maven_files joined to blob_storage_blobs on (namespace_id, sha256). Soft-deleted files are included; package-level rows (maven_version_id IS NULL) are excluded; fileless versions keep DEFAULT 0. The direct join substitutes for the ADR's blob_storage_blobs_by_namespace shadow, documented in the migration comment and the plan.
  • Index(namespace_id, maven_package_id, size_bytes DESC) WHERE soft_deleted_at IS NULL, mirroring the remote twin.

Rolling-deploy safe: the store's inserts use explicit column lists, so the regenerated jet column changes no query semantics.

Files changed

  • internal/datastore/migrations/sql/20260813150000_add_maven_versions_size_bytes.sql — the migration (Up/Down, squawk exemptions carried where required)
  • internal/datastore/migrations/structure.sql — regenerated schema dump (column on parent + all 64 partitions, ON ONLY index + ATTACH PARTITION entries)
  • internal/datastore/jet/artifact_registry/public/{model,table}/maven_versions.go — regenerated jet types
  • internal/datastore/migrations/maven_schema_integration_test.go — column-shape, default, NULL-rejection, partition-recursion, index-shape, and backfill tests
  • internal/datastore/migrations/migrations_checksum_test.go — head-version constant moved in lockstep

Test coverage

  • Column shape (bigint NOT NULL), DEFAULT 0 materialization
  • Explicit-NULL insertion rejected
  • Index shape incl. the size-ordered DESC and the soft_deleted_at IS NULL predicate
  • Recursion over all 64 partitions
  • Backfill correctness against hand-written expected constants (dedupe, soft-deleted inclusion, package-level exclusion, fileless default)

E2e scenario catalogs

No catalog scenario added or affected — the catalogs in docs/testing/e2e/ cover user-level Docker/OCI flows; this work adds a schema column, a backfill, and an index with no user-flow delta (said per the testing-catalogs guardrail). The management-API display field that surfaces size_bytes is Step 5 of the plan and lands separately.

Size justification

Reviewable LOC is 827 — over the 500 ceiling in docs/dev/development-model.md. The excess is almost entirely the schema-integration and helpers suites for the single migration (review fixes added the same-size dedupe fixture, Down/Up round-trip assertions, a negative-storability test, and shared format-neutral helpers); the count also includes 51 lines in CLAUDE.md for the comment-and-test conventions this MR codifies, and splitting tests from the migration would defeat the test-first structure, so the size is justified as-is.

Database Review Evidence

Note

Timings are from CI (db:migrate matrix, goose verbose) against an empty database, in apply / rollback order per PG version. Production-scale validation via Database Lab is not yet available. See Database review evidence for the matrix rationale and how to read the numbers.

Migration PG 16 PG 17 PG 18
20260813150000_add_maven_versions_size_bytes.sql OK (195.03ms / 50.58ms) OK (96.2ms / 49.36ms) OK (160.02ms / 37.75ms)

Migration notes:

  • No anomalies: all versions apply and roll back cleanly, sub-second on an empty database (well under the 1s slow-migration bar and the 5-minute boot budget); up/down asymmetry is within noise; PG 16's up timing (195ms) trails PG 17/18 but is trivial in absolute terms.

Related to #550 (closed)

Edited by Moaz Khalifa

Merge request reports

Loading
Loading