use async_trait::async_trait;
use chrono::{DateTime, Utc};
use flume::Sender;
use std::sync::{Arc, OnceLock};
pub mod local_disk;
#[cfg(feature = "rocksdb")]
pub mod rocks;
pub mod spool_id;
pub use spool_id::SpoolId;
#[derive(Debug)]
pub enum SpoolEntry {
Item { id: SpoolId, data: Vec<u8> },
Corrupt { id: SpoolId, error: String },
}
#[async_trait]
pub trait Spool: Send + Sync {
async fn load(&self, id: SpoolId) -> anyhow::Result<Vec<u8>>;
async fn remove(&self, id: SpoolId) -> anyhow::Result<()>;
async fn store(
&self,
id: SpoolId,
data: Arc<Box<[u8]>>,
force_sync: bool,
) -> anyhow::Result<()>;
fn enumerate(
&self,
sender: Sender<SpoolEntry>,
start_time: DateTime<Utc>,
) -> anyhow::Result<()>;
async fn cleanup(&self) -> anyhow::Result<()>;
async fn shutdown(&self) -> anyhow::Result<()>;
async fn advise_low_memory(&self) -> anyhow::Result<isize>;
}
static DATA: OnceLock<Arc<dyn Spool + Send + Sync>> = OnceLock::new();
static META: OnceLock<Arc<dyn Spool + Send + Sync>> = OnceLock::new();
pub fn get_meta_spool() -> &'static Arc<dyn Spool + Send + Sync> {
META.get().expect("set_meta_spool has not been called")
}
pub fn get_data_spool() -> &'static Arc<dyn Spool + Send + Sync> {
DATA.get().expect("set_data_spool has not been called")
}
pub fn set_meta_spool(meta: Arc<dyn Spool + Send + Sync>) {
META.set(meta)
.map_err(|_| "set_meta_spool has already been called")
.unwrap();
}
pub fn set_data_spool(data: Arc<dyn Spool + Send + Sync>) {
DATA.set(data)
.map_err(|_| "set_data_spool has already been called")
.unwrap();
}