use kevy_store::Store;
use crate::state::Ctx;
pub(crate) fn on_write(ctx: &Ctx<'_>, store: &mut Store, key: &[u8]) {
if !store.packed_rows_enabled() {
return;
}
let Some(tables) = ctx.state.catalogs.table() else { return };
let Some(spec) = tables.iter().find(|t| key.starts_with(&t.prefix)) else { return };
let names: Vec<Vec<u8>> = spec.columns.iter().map(|(n, _)| n.clone()).collect();
store.pack_row(key, &names);
}
#[derive(Debug)]
pub(crate) struct PackJob {
names: Vec<Vec<u8>>,
keys: Vec<Vec<u8>>,
pos: usize,
}
#[derive(Debug, Default)]
pub(crate) struct PackBackfill {
generation: u64,
jobs: Vec<PackJob>,
}
const BATCH: usize = 2048;
pub(crate) fn on_tick(ctx: &Ctx<'_>, store: &mut Store) {
if !store.packed_rows_enabled() {
return;
}
let mut bf = ctx.shard.packing.borrow_mut();
let generation = ctx.state.catalogs.table_gen();
if bf.generation != generation {
bf.jobs = collect_jobs(ctx, store);
bf.generation = generation;
}
let Some(job) = bf.jobs.iter_mut().find(|j| j.pos < j.keys.len()) else { return };
let end = (job.pos + BATCH).min(job.keys.len());
let slice: Vec<Vec<u8>> = job.keys[job.pos..end].to_vec();
let names = job.names.clone();
job.pos = end;
let done = job.pos >= job.keys.len();
drop(bf);
for key in &slice {
store.pack_row(key, &names);
}
if done {
let mut bf = ctx.shard.packing.borrow_mut();
bf.jobs.retain(|j| j.pos < j.keys.len());
}
}
fn collect_jobs(ctx: &Ctx<'_>, store: &mut Store) -> Vec<PackJob> {
let Some(tables) = ctx.state.catalogs.table() else { return Vec::new() };
tables
.iter()
.map(|t| {
let mut pat = t.prefix.clone();
pat.push(b'*');
PackJob {
names: t.columns.iter().map(|(n, _)| n.clone()).collect(),
keys: store.collect_keys(Some(&pat), None),
pos: 0,
}
})
.collect()
}