Dowser. Migrator
(Dowser.Client v0.5.0)
View Source
Runs the migrations (Dowser.Migration) of a repo, from Mix —
mix dowser.migrate, mix dowser.rollback — or from a release, where Mix
isn't available:
defmodule MyApp.Release do
def migrate do
Application.ensure_all_started(:dowser_client)
Dowser.Migrator.run(MyApp.Search, :up, all: true, reindex: true)
end
endWhere migrations live
In priv/dowser/migrations/ of the repo's application, or in the
:migrations_path the repo is configured with, relative to the
application's directory:
config :my_app, MyApp.Search, migrations_path: "priv/search/migrations"What a run does
It takes the repo's migration lock — one migrator at a time — then plans
the whole run before sending any change: each index's migrations are folded
together, checked against the index's mapping, settings and version, so a
migration that can't run fails with nothing changed (Dowser.Migration.Error).
The migrations it runs are recorded in the dowser_schema_migrations index.
An index that must be copied — a field modified, renamed or removed, a
static setting — is copied into a new index only with reindex: true:
- writes to the index are blocked (
write_block: falseto skip it), so a document written during the copy can't be lost: the write fails instead, for the application to retry; - the new index is created, and the documents copied into it — through the script of the migrations' field operations;
- the alias moves onto it;
- the old index stays, writes blocked, for a rollback to move the alias
back — unless
delete_previous: true.
If the copy fails, it is undone: the new index deleted, the old one
unblocked. If even that fails, or the node running it dies, the lock stays
with what the copy had changed, and every run refuses to start until
recover/2 (mix dowser.recover) has undone it.
Rolling back
A rollback runs down/0, or change/0 inverted. An index the rolled-back
migrations had copied moves back onto its previous index when it still
exists — no copy, but the documents written since the migration aren't in
it. Otherwise it is copied again (reindex: true), the operations reverted:
a removed field's values are lost.
Summary
Types
A migration: its version, name and module (once loaded).
Functions
A plan from plan/3 as text: each index, then the requests sent for it.
repo's migrations — from its files and its records — with whether each
has run: {:up | :down, version, name}, by version. A migration recorded
without a file has the name "** FILE NOT FOUND **".
Where repo's migration files are: its :migrations_path, or
priv/dowser/migrations, in its application's directory.
Plans a run as run/3 would — same options — without changing anything or
taking the lock: the migrations it would run, and the requests it would
send. format_plan/1 prints them.
Undoes what a run left behind when it stopped in the middle of copying an index — the node died, or undoing the failed copy failed — and releases the lock
Runs repo's pending migrations (:up) or rolls back the last ones
(:down), returning the versions it ran.
Types
Functions
A plan from plan/3 as text: each index, then the requests sent for it.
@spec migrations(Dowser.Repo.t(), keyword()) :: [{:up | :down, integer(), String.t()}]
repo's migrations — from its files and its records — with whether each
has run: {:up | :down, version, name}, by version. A migration recorded
without a file has the name "** FILE NOT FOUND **".
@spec migrations_path(Dowser.Repo.t()) :: String.t()
Where repo's migration files are: its :migrations_path, or
priv/dowser/migrations, in its application's directory.
@spec plan(Dowser.Repo.t(), :up | :down, keyword()) :: {[migration()], Dowser.Migration.Planner.plan()}
Plans a run as run/3 would — same options — without changing anything or
taking the lock: the migrations it would run, and the requests it would
send. format_plan/1 prints them.
@spec recover(Dowser.Repo.t(), keyword()) :: {:ok, term()} | {:error, term()}
Undoes what a run left behind when it stopped in the middle of copying an index — the node died, or undoing the failed copy failed — and releases the lock:
- the alias hadn't moved: the new index is deleted, the old one
unblocked; returns
{:ok, {:undone, index}}; - the alias had moved: the copy is kept — as if the run had finished it,
whose next run records the migrations; returns
{:ok, {:kept, index}}.
Returns {:ok, :released} for a lock with no copy in progress, {:ok, :unlocked} without a lock.
@spec run(Dowser.Repo.t(), :up | :down, keyword()) :: [integer()]
Runs repo's pending migrations (:up) or rolls back the last ones
(:down), returning the versions it ran.
Options:
:all— every pending migration (the default up), or every one run (down).:step— the next/lastn(down defaults tostep: 1).:to— up to and including that version (up), down to and including it (down).:reindex— allow copying indices (defaultfalse): without it, a migration needing a copy aborts the run before it changes anything.:write_block— block writes to an index while it is copied (defaulttrue).:delete_previous— delete the index a copy replaced (defaultfalse).:poll_interval— how often a copy's progress is checked, in milliseconds (default1000).:log—falseto log nothing.:migrations_path— where the migration files are.:migrations— the migrations themselves, as{version, module}, rather than files.
Raises a Dowser.Migration.Error when the run can't be planned or a step
fails, a Dowser.Migration.IrreversibleError when a rollback can't be.