use crate::error::{DbError, Result};
use crate::integrity::audit::audit_current;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RebuildReport {
pub rows_rebuilt: usize,
pub drift_after: usize,
}
pub async fn rebuild_current(conn: &libsql::Connection) -> Result<RebuildReport> {
let tx = conn
.transaction_with_behavior(libsql::TransactionBehavior::Immediate)
.await?;
match rebuild_within(&tx, Verify::Yes).await {
Ok(report) => {
tx.commit().await?;
Ok(report)
}
Err(e) => {
let _ = tx.rollback().await;
Err(e)
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum Verify {
Yes,
No,
}
pub(crate) async fn rebuild_within(
conn: &libsql::Connection,
verify: Verify,
) -> Result<RebuildReport> {
conn.execute("DELETE FROM links_current", ()).await?;
let insert_query = format!(
"INSERT INTO links_current \
(source_id, target_id, edge_type, valid_from, valid_to, weight, properties, recorded_at) \
{projection}",
projection = super::LATEST_BELIEF_PROJECTION
);
let rows_inserted = conn.execute(&insert_query, ()).await?;
if verify == Verify::No {
return Ok(RebuildReport {
rows_rebuilt: rows_inserted as usize,
drift_after: 0,
});
}
match audit_current(conn).await {
Ok(0) => Ok(RebuildReport {
rows_rebuilt: rows_inserted as usize,
drift_after: 0,
}),
Ok(n) => Err(DbError::RebuildFailed { n }),
Err(DbError::CurrentDrift { n }) => Err(DbError::RebuildFailed { n }),
Err(e) => Err(e),
}
}