use std::sync::Arc;
use anyhow::Result;
use futures::executor::block_on;
use satoridb::executor::{Executor, WorkerCache};
use satoridb::storage::{Storage, Vector};
use satoridb::wal::runtime::Walrus;
use tempfile::TempDir;
fn init_wal(tempdir: &TempDir) -> Arc<Walrus> {
Arc::new(Walrus::with_data_dir(tempdir.path().to_path_buf()).expect("walrus init"))
}
#[test]
fn oversized_bucket_is_not_cached() -> Result<()> {
let tmp = tempfile::tempdir()?;
let wal = init_wal(&tmp);
let storage = Storage::new(wal);
let mut big_vectors = Vec::new();
for i in 0..2u64 {
let data = vec![1.0f32; 1024];
big_vectors.push(Vector::new(i, data));
}
block_on(storage.put_chunk_raw(0, &big_vectors))?;
let cache = WorkerCache::new(4, 2 * 1024, usize::MAX); let executor = Executor::new(storage.clone(), cache);
let q = vec![0.0f32; 1024];
let first = block_on(executor.query(&q, &[0], 10, 0, Arc::new(Vec::new()), false))?;
assert_eq!(first.len(), 2);
let new_vec = Vector::new(99, vec![2.0f32; 1024]);
block_on(storage.put_chunk_raw(0, &[new_vec]))?;
let second = block_on(executor.query(&q, &[0], 10, 0, Arc::new(Vec::new()), false))?;
let ids: Vec<u64> = second.iter().map(|(id, _, _)| *id).collect();
assert!(
ids.contains(&99),
"bucket 0 should be reloaded on each query when over the cache byte limit"
);
Ok(())
}
#[test]
fn small_bucket_stays_cached_until_version_bump() -> Result<()> {
let tmp = tempfile::tempdir()?;
let wal = init_wal(&tmp);
let storage = Storage::new(wal);
let v0 = Vector::new(1, vec![0.0f32; 4]);
block_on(storage.put_chunk_raw(1, &[v0]))?;
let cache = WorkerCache::new(4, 16 * 1024, usize::MAX);
let executor = Executor::new(storage.clone(), cache);
let q = vec![0.0f32; 4];
let initial = block_on(executor.query(&q, &[1], 10, 0, Arc::new(Vec::new()), false))?;
assert_eq!(initial.len(), 1);
let v1 = Vector::new(2, vec![1.0f32; 4]);
block_on(storage.put_chunk_raw(1, &[v1]))?;
let still_cached = block_on(executor.query(&q, &[1], 10, 0, Arc::new(Vec::new()), false))?;
assert_eq!(
still_cached.len(),
1,
"cache should serve stale contents when routing_version is unchanged"
);
let refreshed = block_on(executor.query(&q, &[1], 10, 1, Arc::new(vec![1]), false))?;
assert_eq!(
refreshed.len(),
2,
"after routing bump + changed bucket, executor should reload fresh data"
);
Ok(())
}