Skip to main content

restore_from

Function restore_from 

Source
pub async fn restore_from(
    pool: SqlitePool,
    db_path: &Path,
    backup_path: &Path,
    now: DateTime<Utc>,
) -> DbResult<RestoreOutcome>
Expand description

Restores db_path from a backup_to-produced file, replacing its entire contents.

Takes pool by value, not &SqlitePool: restoring means the file underneath every existing connection is about to be replaced out from under them, so the caller’s old pool must be given up, not merely borrowed. The type system then enforces that the old handle can’t accidentally go on being used afterward — every caller must switch to RestoreOutcome::pool.

Safety, in order:

  1. backup_path is validated (PRAGMA integrity_check, plus confirming a real tune_runs table exists) before anything about the live database is touched, so a corrupt or unrelated file never gets a chance to destroy good data.
  2. The caller’s own connections to db_path are closed first, so step 3’s exclusivity check isn’t confused by this process’s own still-open pool.
  3. If db_path already exists, [exclusive_pre_restore_snapshot] both confirms no other connection — in this process or another — still holds it open, and, while that’s proven true, takes a consistent VACUUM INTO copy of it (see RestoreOutcome::pre_restore_backup). Restoring the wrong backup, or restoring when a fresh backup was what was actually wanted, is still recoverable afterward. Using VACUUM INTO here rather than a raw file copy means the safety copy can never be silently missing data that was still sitting in a WAL file — the same reason backup_to uses it.
  4. The backup is copied into place via write-to-a-temp-file-then-rename, so a crash or a full disk mid-copy leaves the original db_path untouched rather than half-overwritten (rename onto an existing path is atomic on the same filesystem, which a same-directory temp file guarantees; renaming a file onto an existing file — as opposed to a directory — replaces it on Windows too, via MOVEFILE_REPLACE_EXISTING, so no Windows-specific fallback is needed here).
  5. Any stale -wal/-shm sidecar files left over from the old db_path are removed — they describe uncommitted changes to a database that, after step 4, no longer exists at that path.
  6. db_path is reopened via connect, which reapplies the standard pragmas and runs any migrations the backup predates forward — restoring an older backup transparently upgrades its schema, exactly as opening an old database file normally would.

Restoring while another bhtune process (for instance bhtune-server, running alongside the CLI) has db_path open returns DbError::DatabaseInUse instead of proceeding — see [exclusive_pre_restore_snapshot] for how that’s detected and its residual, deliberately-accepted race.