use std::sync::Arc;
use haematite::db::ShardReclaimAnswer;
use haematite::{Database, DatabaseConfig, EventStore, ReclaimStart, RuntimeOptions};
use super::reclaim_route::SharedReclaimSpine;
fn spine(dir: &std::path::Path) -> Result<Arc<EventStore>, Box<dyn std::error::Error>> {
let database = Database::create(
DatabaseConfig {
data_dir: dir.to_path_buf(),
shard_count: 3,
distributed: None,
executor_threads: None,
node_cache_budget: Some(haematite::NodeCacheBudget::Unlimited),
retention: haematite::Retention::reclaim(0),
},
RuntimeOptions {
long_wait_interval: std::time::Duration::from_secs(5),
reclaim_start: ReclaimStart::Held,
},
)?;
Ok(Arc::new(EventStore::new(database)))
}
#[test]
fn nothing_answers_before_the_spine_is_installed() {
let shared = SharedReclaimSpine::default();
assert!(shared.status().is_none());
assert!(shared.quiesce().is_none());
}
#[test]
fn the_record_answers_every_shard_and_quiesce_answers_the_stores_word()
-> Result<(), Box<dyn std::error::Error>> {
let dir = tempfile::tempdir()?;
let shared = SharedReclaimSpine::default();
let spine = spine(dir.path())?;
assert!(shared.install(&spine));
let status = shared.status().ok_or("installed")?;
assert_eq!(status.shards.len(), 3);
assert!(
status
.shards
.iter()
.all(|shard| matches!(shard, ShardReclaimAnswer::Answered { .. }))
);
let body = serde_json::to_string(&status)?;
assert!(body.contains("\"shards\""));
let held = shared.quiesce().ok_or("installed")?;
assert!(!held.quiesced, "a held spine was quiesced");
assert!(
held.refused
.as_deref()
.is_some_and(|refused| refused.contains("reclaim_held")),
"{:?}",
held.refused
);
spine.database().release_reclaim()?;
let answer = shared.quiesce().ok_or("installed")?;
assert!(answer.quiesced, "released: {:?}", answer.refused);
assert_eq!(answer.status.shards.len(), 3);
let again = shared.quiesce().ok_or("installed")?;
assert!(again.quiesced, "{:?}", again.refused);
assert_eq!(again.passes_run, 0, "nothing written: no pass was needed");
Ok(())
}
#[test]
fn the_route_never_holds_the_spine_open() -> Result<(), Box<dyn std::error::Error>> {
let dir = tempfile::tempdir()?;
let shared = SharedReclaimSpine::default();
let spine = spine(dir.path())?;
assert!(shared.install(&spine));
assert!(shared.status().is_some());
drop(spine);
assert!(shared.status().is_none(), "the route kept the closed spine");
assert!(shared.quiesce().is_none());
Ok(())
}