fix: idempotent migrations (ADD COLUMN IF NOT EXISTS), stale doc, safety note

This commit is contained in:
atlas 2026-07-10 16:25:02 +02:00 committed by mara
commit c47faf0af9
5 changed files with 80 additions and 26 deletions

View file

@ -162,23 +162,34 @@ pub struct Broker {
/// `messages` — the last column added before versioning.
const BROKER_MIGRATIONS: &[&str] = &[
// v1: acked_at on messages, with backfill so existing delivered rows
// are not phantom-requeued on the next open. The multi-statement
// batch runs atomically (execute_batch wraps in a transaction).
"ALTER TABLE messages ADD COLUMN acked_at INTEGER;\
UPDATE messages SET acked_at = delivered_at WHERE delivered_at IS NOT NULL;",
// are not phantom-requeued on the next open.
//
// IF NOT EXISTS: safe to run on a partially-migrated legacy DB where
// acked_at already exists but priority (the legacy marker) does not.
// The BEGIN/COMMIT block makes ALTER + UPDATE atomic — if the UPDATE
// fails the version counter is not bumped and the whole step retries.
"BEGIN;\
ALTER TABLE messages ADD COLUMN IF NOT EXISTS acked_at INTEGER;\
UPDATE messages SET acked_at = delivered_at \
WHERE delivered_at IS NOT NULL AND acked_at IS NULL;\
COMMIT;",
// v2: in_reply_to for thread-parent tracking. NULL = root of a thread.
"ALTER TABLE messages ADD COLUMN in_reply_to INTEGER",
"ALTER TABLE messages ADD COLUMN IF NOT EXISTS in_reply_to INTEGER",
// v3: priority for operator-message fast-path. Rebuild the delivery
// index to include priority as a secondary sort key.
"ALTER TABLE messages ADD COLUMN priority INTEGER NOT NULL DEFAULT 0;\
"BEGIN;\
ALTER TABLE messages ADD COLUMN IF NOT EXISTS \
priority INTEGER NOT NULL DEFAULT 0;\
DROP INDEX IF EXISTS idx_messages_undelivered;\
CREATE INDEX idx_messages_undelivered \
ON messages (recipient, priority DESC, id) WHERE delivered_at IS NULL",
CREATE INDEX IF NOT EXISTS idx_messages_undelivered \
ON messages (recipient, priority DESC, id) WHERE delivered_at IS NULL;\
COMMIT;",
// v4: attempt_count on reminders for the MAX_REMINDER_ATTEMPTS cap.
"ALTER TABLE reminders ADD COLUMN attempt_count INTEGER NOT NULL DEFAULT 0",
"ALTER TABLE reminders ADD COLUMN IF NOT EXISTS \
attempt_count INTEGER NOT NULL DEFAULT 0",
// v5: last_error on reminders — last delivery failure surfaced on the
// dashboard so a stuck reminder is visible without digging in logs.
"ALTER TABLE reminders ADD COLUMN last_error TEXT",
"ALTER TABLE reminders ADD COLUMN IF NOT EXISTS last_error TEXT",
];
impl Broker {
@ -1134,11 +1145,6 @@ impl Broker {
}
}
/// Idempotent messages-table migrations. Adds `acked_at` and
/// back-fills it for every already-delivered row, so the
/// pre-migration sessions count as "fully handled" and won't be
/// resurfaced by the first `requeue_inflight` after upgrade.
#[cfg(test)]
mod tests {
use super::*;