//! Database backup freshness check storage. use super::{BackupCheckResult, Result, SqlitePool}; use tracing::instrument; #[instrument(skip_all)] pub async fn insert_backup_check(pool: &SqlitePool, result: &BackupCheckResult) -> Result { let row = sqlx::query( "INSERT INTO backup_checks (target, database_name, status, last_backup_at, size_bytes, age_hours, checked_at, error) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", ) .bind(&result.target) .bind(&result.database_name) .bind(&result.status) .bind(&result.last_backup_at) .bind(result.size_bytes) .bind(result.age_hours) .bind(&result.checked_at) .bind(&result.error) .execute(pool) .await?; Ok(row.last_insert_rowid()) } /// Get the latest backup check for a specific target and database. #[instrument(skip_all)] pub async fn get_latest_backup_check( pool: &SqlitePool, target: &str, database_name: &str, ) -> Result> { Ok(sqlx::query_as::<_, BackupCheckRow>( "SELECT id, target, database_name, status, last_backup_at, size_bytes, age_hours, checked_at, error FROM backup_checks WHERE target = ? AND database_name = ? ORDER BY id DESC LIMIT 1", ) .bind(target) .bind(database_name) .fetch_optional(pool) .await?) } #[derive(Debug, Clone, sqlx::FromRow, serde::Serialize)] pub struct BackupCheckRow { pub id: i64, pub target: String, pub database_name: String, pub status: String, pub last_backup_at: Option, pub size_bytes: Option, pub age_hours: Option, pub checked_at: String, pub error: Option, }