mirror of
https://github.com/karatektus/pl_mail.git
synced 2026-10-25 10:04:18 +00:00
A deploy carrying a migration brought up one service out of four. php,
imap-supervisor, messenger-worker and scheduler are the same image running the
same entrypoint, they start within milliseconds of each other against one
database, and every one of them migrates on boot. All four read the ledger
before any of them writes to it, so all four decide the same migration is
pending; one wins and the rest die on
SQLSTATE[42701]: Duplicate column: 7
ERROR: column "timezone" of relation "user" already exists
which under `set -e` is a container that never comes up. The timezone column in
v0.0.6 is what exposed it, not what caused it -- any migration would have done,
and `--all-or-nothing` makes it likelier rather than safer, because the losers
are held for as long as the whole batch takes instead of one statement.
Reproduced before it was fixed: four concurrent migrates against one database,
three exited 7 with that message verbatim. The same four under the lock all exit
0, one migrates and three find the ledger current.
The losers still run the migration rather than skipping it. Skipping would mean
a container coming up against a schema nobody in that process verified, which is
the failure this is supposed to prevent, one step later.
The lock cannot be a line of shell, which is the whole reason there is a command
here. `pg_advisory_lock()` is scoped to the session, so taking it with
`dbal:run-sql` hands it straight back when that process exits and leaves the
migration it was meant to protect running unguarded. It has to be held by the
connection that migrates, which means one PHP process doing both.
Waiting is bounded. A container OOM-killed mid-migration would otherwise hang
every other service in the stack forever with nothing on stdout to say why, so a
timeout reports what it was waiting for -- and refuses to migrate anyway, which
is the only answer that is not a guess about what the holder was doing.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>