# Compiled only when the user has ecto_sql (Oban-style): fief itself has no # hard dependency on Ecto โ€” see the optional deps note in mix.exs. if Code.ensure_loaded?(Ecto.Migration) do defmodule Fief.Authority.Postgres.Migrations do @moduledoc """ Table definitions for `Fief.Authority.Postgres` (implementation.md ยง3.1): five tables, every one keyed by namespace โ€” the instance name, stringified. One set of migrations covers all instances sharing the database; adding an instance is rows, never DDL. Lives under the adapter it provisions โ€” it exists solely to set up `Fief.Authority.Postgres`'s tables. Run from your own Ecto migration: defmodule MyApp.Repo.Migrations.AddFief do use Ecto.Migration def up, do: Fief.Authority.Postgres.Migrations.up() def down, do: Fief.Authority.Postgres.Migrations.down() end The DDL is idempotent (`IF NOT EXISTS`), so re-running `up/0` is safe. """ use Ecto.Migration @tables ~w(fief_leases fief_members fief_table fief_meta fief_leader) @doc "Create the five fief tables." def up do execute(""" CREATE TABLE IF NOT EXISTS fief_leases ( ns text NOT NULL, node text NOT NULL, expires_at timestamptz NOT NULL, granted_at timestamptz NOT NULL, PRIMARY KEY (ns, node) ) """) execute(""" CREATE TABLE IF NOT EXISTS fief_members ( ns text NOT NULL, node text NOT NULL, status text NOT NULL, joined_at timestamptz NOT NULL, PRIMARY KEY (ns, node) ) """) # prev_owner NULL = settled; epoch = the namespace epoch of the last # successful CAS on this row (the M4 row-epoch decision). execute(""" CREATE TABLE IF NOT EXISTS fief_table ( ns text NOT NULL, vnode integer NOT NULL, owner text NOT NULL, prev_owner text, epoch bigint NOT NULL, PRIMARY KEY (ns, vnode) ) """) # The per-namespace epoch/term domain plus the immutable first-writer-wins # config: `config` carries the full config term (ETF); partitions and # impl_fingerprint are broken out for operator visibility. execute(""" CREATE TABLE IF NOT EXISTS fief_meta ( ns text PRIMARY KEY, epoch bigint NOT NULL DEFAULT 0, max_term bigint NOT NULL DEFAULT 0, partitions integer, impl_fingerprint text, config bytea ) """) execute(""" CREATE TABLE IF NOT EXISTS fief_leader ( ns text PRIMARY KEY, holder text NOT NULL, term bigint NOT NULL, expires_at timestamptz NOT NULL ) """) end @doc "Drop the five fief tables." def down do for table <- @tables, do: execute("DROP TABLE IF EXISTS #{table}") end end end