1use async_trait::async_trait;
2use chrono::{DateTime, Utc};
3use flume::Sender;
4use std::sync::{Arc, OnceLock};
5use std::time::Instant;
6
7pub mod local_disk;
8#[cfg(feature = "rocksdb")]
9pub mod rocks;
10pub mod spool_id;
11
12pub use spool_id::SpoolId;
13
14#[derive(Debug)]
15pub enum SpoolEntry {
16 Item { id: SpoolId, data: Vec<u8> },
17 Corrupt { id: SpoolId, error: String },
18}
19
20#[async_trait]
21pub trait Spool: Send + Sync {
22 async fn load(&self, id: SpoolId) -> anyhow::Result<Vec<u8>>;
24
25 async fn remove(&self, id: SpoolId) -> anyhow::Result<()>;
27
28 async fn store(
30 &self,
31 id: SpoolId,
32 data: Arc<Box<[u8]>>,
33 force_sync: bool,
34 deadline: Option<Instant>,
35 ) -> anyhow::Result<()>;
36
37 fn enumerate(
45 &self,
46 sender: Sender<SpoolEntry>,
47 start_time: DateTime<Utc>,
48 ) -> anyhow::Result<()>;
49
50 async fn cleanup(&self) -> anyhow::Result<()>;
52
53 async fn shutdown(&self) -> anyhow::Result<()>;
55
56 async fn advise_low_memory(&self) -> anyhow::Result<isize>;
62}
63
64static DATA: OnceLock<Arc<dyn Spool + Send + Sync>> = OnceLock::new();
65static META: OnceLock<Arc<dyn Spool + Send + Sync>> = OnceLock::new();
66
67pub fn get_meta_spool() -> &'static Arc<dyn Spool + Send + Sync> {
68 META.get().expect("set_meta_spool has not been called")
69}
70
71pub fn get_data_spool() -> &'static Arc<dyn Spool + Send + Sync> {
72 DATA.get().expect("set_data_spool has not been called")
73}
74
75pub fn set_meta_spool(meta: Arc<dyn Spool + Send + Sync>) {
76 META.set(meta)
77 .map_err(|_| "set_meta_spool has already been called")
78 .unwrap();
79}
80
81pub fn set_data_spool(data: Arc<dyn Spool + Send + Sync>) {
82 DATA.set(data)
83 .map_err(|_| "set_data_spool has already been called")
84 .unwrap();
85}