use alloc::string::String;
use alloc::vec::Vec;
use crate::bytes::Bytes;
use crate::persistence::{InsertSummary, Origin, storage};
use super::Bundle;
const BATCH: usize = 1024;
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct ImportReport {
pub namespaces: Vec<String>,
pub imported: usize,
pub skipped: usize,
pub failed: usize,
}
pub fn import(bundle: &dyn Bundle) -> ImportReport {
let mut report = ImportReport::default();
for namespace in bundle.namespaces() {
let target = storage::open(&namespace);
let mut batch: Vec<(Bytes, Bytes)> = Vec::with_capacity(BATCH);
let mut total = InsertSummary::default();
let commit = |batch: &mut Vec<(Bytes, Bytes)>, total: &mut InsertSummary| {
if batch.is_empty() {
return;
}
let summary = target.insert_many(&mut batch.drain(..), Origin::Imported);
total.stored += summary.stored;
total.conflict += summary.conflict;
total.failed += summary.failed;
};
bundle.scan(&namespace, &mut |key, value| {
batch.push((
Bytes::from_bytes_vec(key.to_vec()),
Bytes::from_bytes_vec(value.to_vec()),
));
if batch.len() == BATCH {
commit(&mut batch, &mut total);
}
});
commit(&mut batch, &mut total);
let (imported, skipped) = (total.stored, total.conflict);
log::debug!("Imported {imported} entries into {namespace} ({skipped} already present)");
if total.failed > 0 {
log::warn!("Failed to import {} entries into {namespace}", total.failed);
}
report.namespaces.push(namespace);
report.imported += imported;
report.skipped += skipped;
report.failed += total.failed;
}
log::info!(
"Imported {} entries from {} into {} namespaces ({} already present)",
report.imported,
bundle.describe(),
report.namespaces.len(),
report.skipped,
);
report
}