PhoenixKit.Migrations.Postgres.V205 (phoenix_kit v2.41.0)

Copy Markdown View Source

V205: storage profiles and variant sets, the schema half (phase 4 of dev_docs/plans/2026-09-22-storage-libraries.md).

A library says where its bytes live by pointing at a storage profile, and which derived files it gets by pointing at a variant set. Both default to NULL, which means the Default one, so nothing changes for an existing install:

  • phoenix_kit_storage_profiles — copies_originals, copies_variants, min_copies_on_write and a revision bumped on every change. One row is seeded: Default, under the fixed uuid 00000000-0000-7000-8000-000000000002, with both copy counts taken from storage_redundancy_copies.
  • phoenix_kit_storage_profile_buckets — the profile's buckets, each with a role (primary | replica | backup), what it stores (all | originals | derived), a fixed write_priority (NULL = the shuffled pool), a serve_order and a status (active | read_only | draining). storage_class and encryption are reserved. Every bucket joins Default: write_priority is its priority (0 becomes the pool) and serve_order is today's read order, local buckets first and then by priority. A bucket a profile uses cannot be deleted.
  • phoenix_kit_variant_sets — generate_variants and generate_tiles (seeded from storage_auto_generate_variants and storage_tile_generation_enabled), selectable (user libraries may pick it) and a revision. One row is seeded: Default, under 00000000-0000-7000-8000-000000000003.
  • variant_set_uuid on phoenix_kit_storage_dimensions: NOT NULL, ON DELETE CASCADE, with the Default set's uuid as its column DEFAULT, so every existing size is in Default and a writer that names no set keeps working. Size names are unique per set instead of site-wide (phoenix_kit_storage_dimensions_name_index gains a leading variant_set_uuid).
  • storage_profile_uuid / variant_set_uuid on libraries (NULL = the Default, ON DELETE RESTRICT).
  • What a file was placed by: placed_profile_uuid / placed_revision and placed_variant_set_uuid / placed_variant_revision on files. NULL means the Default at revision 1, which is what every existing file is, so no file row is rewritten. A file is stale, and the reconciler moves or regenerates it, when what it was placed by differs from its library's. reconcile_attempted_at is when the reconciler last tried a file and could not finish it: it waits a while before the next try, so a file that keeps failing is not retried on every pass. The files that are under-replicated today are marked stale here (placed_revision = 0): the ones whose completed instances do not each have as many active locations on enabled buckets as the Default wants (or as there are enabled buckets, if fewer).
  • spec_hash on file instances: which spec of a size produced the instance. Stamped here on every instance whose name is a size of the Default set (or one of its alternative formats), with that size's current spec (PhoenixKit.Modules.Storage.VariantSets.spec_hash/2 computes the same value). Instances not made from a size (the original, an annotated thumbnail, a burned render) have none.

Nothing is copied, moved or regenerated here.

Locks

New tables and nullable columns without defaults are metadata-only. The dimensions column has a constant default (metadata-only) and becomes NOT NULL through a validated check (the V164 pattern). The spec_hash stamp is one UPDATE over the instances named like a size. The name index is a plain rebuild on a table of a few rows.

Re-runnable.

Summary

Functions

Rolls V205 back. Sizes of any set other than Default are deleted (size names become unique site-wide again), then the tables and columns go.

Functions

down(opts)

Rolls V205 back. Sizes of any set other than Default are deleted (size names become unique site-wide again), then the tables and columns go.