use rusqlite::{Connection, OptionalExtension, Transaction, TransactionBehavior}; #[derive(Clone, Copy, PartialEq, Eq)] pub(crate) struct HeaderSync { generation: u64, } impl HeaderSync { pub(crate) fn capture(conn: &Connection) -> Result { let generation = conn .query_row( crate::queries::sqlite::queries::db_header_sync::Q_001, [], |row| row.get::<_, String>(0), ) .optional() .map_err(|e| e.to_string())? .map(|value| value.parse::().map_err(|e| e.to_string())) .transpose()? .unwrap_or(0); Ok(Self { generation }) } pub(crate) fn begin_write(self, conn: &Connection) -> Result, String> { let transaction = Transaction::new_unchecked(conn, TransactionBehavior::Immediate) .map_err(|e| e.to_string())?; if Self::capture(conn)?.generation != self.generation { return Err("Header sync superseded by cache removal; retry on next sync".into()); } Ok(transaction) } } pub(crate) fn invalidate(conn: &Transaction<'_>) -> Result<(), String> { conn.execute(crate::queries::sqlite::queries::db_header_sync::Q_002, []) .map_err(|e| e.to_string())?; Ok(()) }