StatifierRouter.Migrations (StatifierRouter v0.7.0)

Copy Markdown View Source

Versioned migrations for this package's tables, in the shape statifier_persistence's StatifierPersistence.Ecto.Migrations uses: the host writes one ordinary migration that delegates here, and later package versions ship higher-numbered migration modules the same call picks up.

defmodule MyApp.Repo.Migrations.AddStatifierRouter do
  use Ecto.Migration

  def up, do: StatifierRouter.Migrations.up(prefix: "routing")
  def down, do: StatifierRouter.Migrations.down(prefix: "routing")
end

The options are the two storage options of StatifierRouter.Config, :table_prefix and :prefix, resolved the same way, :from and :version, and the three layout options statifier_persistence's migrations helper takes, under the same spellings:

  • :table_prefix - a string prefixed to every table name, default "statifier_router_". Pass the same value the host's StatifierRouter.Config carries.
  • :prefix - the Postgres schema the tables live in, default nil. When it is set, up/1 creates the schema if it does not exist and down/1 leaves it in place: dropping a schema the host may share is not this package's call.
  • :from and :version - where a call starts and where it ends, in both directions. up/1 migrates from from: (default: V01) up through version: (default: the newest this package knows), and down/1 rolls back from from: (default: the newest) down through version: (default: V01, that is, everything).
  • :leading_columns - host-owned columns placed immediately after id in every table a version creates, in the order given, default []. A keyword list of name: {type, opts}, where type and opts are what Ecto.Migration.add/3 takes: leading_columns: [branch_id: {:text, null: true}] puts a nullable branch_id at ordinal position 2 on all four tables. The package's schemas do not declare the column, so the package never reads or writes it; a default or a NOT NULL belongs to a later migration of the host's own. A name a table the call creates already declares - any column StatifierRouter.Migrations.V01 or StatifierRouter.Migrations.V02 lists for it - raises ArgumentError naming the column and those tables, before any DDL runs, where Postgres would otherwise refuse the CREATE TABLE with a duplicate column. A name only a table the call does not create declares is a host column like any other: up(from: 2) may lead with expires_at, which only V01's dedupe table has. The primary key is the repo's :migration_primary_key and is not checked: a repo that sets it to false may lead with an id of its own.
  • :timestamps_position - where inserted_at goes in every table a version creates that has one (the address table, the routing ledger and the subscription table; the dedupe table has none): :trailing (default: the layout StatifierRouter.Migrations.V01 and StatifierRouter.Migrations.V02 document) or :leading (immediately after id and the :leading_columns). The address table's terminal_seen_at is not a timestamp column in this sense and stays where it is.
  • :column_collations - a collation per package text column, applied wherever a version declares that column in a CREATE TABLE, default [] (every column takes the database default). A keyword list of name: collation, the collation a non-empty string: column_collations: [execution_id: "C"] declares execution_id COLLATE "C" on the address table, the routing ledger and the subscription table. The names are the text columns the versions declare - scope, document, key, execution_id, binding_id, message_id, outcome, reason and invoke_id - and the collation must be one the database knows; a host column takes its collation in its own :leading_columns opts instead.

The three layout options apply to a fresh create only. Each table is laid out by the version that creates it - V01 the address table, the dedupe table and the routing ledger, V02 the subscription table - and no version re-places a column in a table that already exists, so adding an option later changes nothing in the tables already built. Left out, every version builds exactly the tables it built before the options existed. down/1 accepts them too, so one options list serves both directions, and ignores them.

A host already running an older version writes its next migration with from: set to the first version it has not run, rather than re-running V01's CREATE TABLE against tables that already exist. A host whose first migration is capped with version: N caps its rollback to match with from: N.

A fault in the options raises ArgumentError: a migration has no caller to hand an {:error, reason} to.

StatifierRouter.Migrations.V01 records what the first version creates, and StatifierRouter.Migrations.V02 what the second adds.

:from is inclusive: up(from: 2) runs V02, and a host already on V01 that writes it gets the subscription table without V01's CREATE TABLE running a second time (ADR-0007, section 6).

Summary

Functions

Rolls the tables back from from: (default: the newest version this package knows) down through version: (default: V01, that is, everything).

Migrates the tables from from: (default: V01) up through version: (default: the newest).

Functions

down(opts \\ [])

@spec down(keyword()) :: :ok

Rolls the tables back from from: (default: the newest version this package knows) down through version: (default: V01, that is, everything).

up(opts \\ [])

@spec up(keyword()) :: :ok

Migrates the tables from from: (default: V01) up through version: (default: the newest).