use std::sync::{Arc, Mutex, PoisonError};
use std::time::Duration;
use engenho_store::StoreMesh;
use crate::runtime_health::{Relist, RelistFault, Relisted};
pub(crate) async fn single_voter_store(name: &str) -> Arc<StoreMesh> {
let router = engenho_store::InProcessRouter::new();
let config = engenho_store::default_config(name).expect("the default store config builds");
let mesh = StoreMesh::start(1, "in-process://1".into(), router, config)
.await
.expect("the store starts");
mesh.initialize_singleton()
.await
.expect("the single voter initializes");
assert!(
mesh.wait_for_leadership(Duration::from_secs(5)).await,
"the single voter leads"
);
Arc::new(mesh)
}
#[derive(Debug, Clone, Copy, Default)]
pub(crate) enum RelistAnswer {
#[default]
Lists,
Fails,
Slowly(Duration),
Hangs,
}
#[derive(Debug, Default)]
pub(crate) struct ScriptedRuntime {
answer: Mutex<RelistAnswer>,
}
impl ScriptedRuntime {
pub(crate) const CONTAINERS: usize = 3;
pub(crate) fn set(&self, answer: RelistAnswer) {
*self.answer.lock().unwrap_or_else(PoisonError::into_inner) = answer;
}
}
#[async_trait::async_trait]
impl Relist for ScriptedRuntime {
async fn relist(&self) -> Result<Relisted, RelistFault> {
let answer = *self.answer.lock().unwrap_or_else(PoisonError::into_inner);
match answer {
RelistAnswer::Lists => Ok(Relisted::new(Self::CONTAINERS)),
RelistAnswer::Fails => Err(RelistFault::new(std::io::Error::other(
"podman.sock: connection refused",
))),
RelistAnswer::Slowly(after) => {
tokio::time::sleep(after).await;
Ok(Relisted::new(Self::CONTAINERS))
}
RelistAnswer::Hangs => std::future::pending().await,
}
}
}