Skip to main content

ff_backend_postgres/
migrate.rs

1//! Schema-migration application.
2//!
3//! **RFC-v0.7 Wave 0, Q12.** Migrations are applied **out-of-band by
4//! the operator** via a future `sqlx migrate run` CLI entry (or this
5//! `apply_migrations` function in tests). The ff-server binary does
6//! NOT auto-apply on backend connect; at boot it runs a
7//! schema-version check ([`crate::version::check_schema_version`])
8//! and refuses to start on mismatch per Q12's branch rules. The
9//! rationale lives in the adjudication block in
10//! `rfcs/drafts/v0.7-migration-master.md §Q12`:
11//!
12//! 1. Auto-apply across N replicas races on the sqlx advisory lock
13//!    and stalls rolling deploys.
14//! 2. Auto-apply fights peer-team-boundaries — cairn's SRE owns DDL
15//!    timing.
16
17use sqlx::PgPool;
18
19/// Apply all pending migrations bundled in this crate's
20/// `migrations/` directory.
21///
22/// **Out-of-band only.** Wave 0 ships a placeholder `0001_*.sql`
23/// (just `SELECT 1;`) so the machinery is exercised; wave 3
24/// replaces it with the real schema. Callers: tests + a future
25/// `ff-migrate` CLI. Must NOT be called from
26/// `PostgresBackend::connect`.
27pub async fn apply_migrations(pool: &PgPool) -> Result<(), MigrationError> {
28    sqlx::migrate!("./migrations").run(pool).await?;
29    Ok(())
30}
31
32/// Migration application failure. Thin newtype over
33/// `sqlx::migrate::MigrateError` so we can attach crate-local context
34/// in later waves (e.g. DDL-lock-timeout hint, destructive-migration
35/// guard) without breaking the public fn signature.
36#[derive(Debug, thiserror::Error)]
37pub enum MigrationError {
38    /// Wrap sqlx's typed migration error (version mismatch, checksum
39    /// failure, connection error, etc.).
40    #[error(transparent)]
41    Sqlx(#[from] sqlx::migrate::MigrateError),
42}