use anyhow::Result;
use std::collections::BTreeMap;
use std::sync::Arc;
use crate::domain::ports::RowRepository;
use crate::domain::table_diff::RowMap;
use crate::domain::value_objects::{ColumnName, Schema, TableName};
use crate::infrastructure::config::TableConfig;
pub struct SnapshotService {
target_repo: Arc<dyn RowRepository>,
}
impl SnapshotService {
pub fn new(target_repo: Arc<dyn RowRepository>) -> Self {
Self { target_repo }
}
pub async fn capture(
&self,
target_schema: &Schema,
tables: &[TableConfig],
) -> Result<BTreeMap<String, Vec<RowMap>>> {
let mut handles = Vec::with_capacity(tables.len());
for table_cfg in tables {
let repo = Arc::clone(&self.target_repo);
let schema = target_schema.clone();
let table_cfg = table_cfg.clone();
let handle = tokio::spawn(async move {
let table_name = TableName(table_cfg.name.clone());
let pk_cols: Vec<ColumnName> = table_cfg
.primary_key
.iter()
.map(|pk| ColumnName(pk.clone()))
.collect();
let rows = repo
.fetch_rows(&schema, &table_name, &pk_cols, &table_cfg.excluded_columns)
.await?;
Ok::<_, anyhow::Error>((table_cfg.name.clone(), rows))
});
handles.push(handle);
}
let mut snapshot = BTreeMap::new();
for handle in handles {
let (table_name, rows) = handle.await??;
snapshot.insert(table_name, rows);
}
Ok(snapshot)
}
}