use serde::{de::DeserializeOwned, Serialize};
use sled::{Db, Tree};
use std::{path::Path, sync::Arc, time::Duration};
use crate::prefix::IdentifierPrefix;
use super::{
tables::{SledEventTree, SledEventTreeVec},
timestamped::Timestamped,
DbError,
};
pub struct Escrow<T> {
escrow_db: Arc<EscrowDb>,
tree: SledEventTreeVec<Timestamped<T>>,
duration: Duration,
}
impl<T: Serialize + DeserializeOwned + PartialEq + Clone> Escrow<T> {
pub fn new<V>(name: V, duration: Duration, escrow_db: Arc<EscrowDb>) -> Self
where
V: AsRef<[u8]>,
{
Self {
tree: SledEventTreeVec::new(escrow_db.add_bucket(name).unwrap()),
duration,
escrow_db,
}
}
pub fn add(&self, id: &IdentifierPrefix, event: T) -> Result<(), DbError> {
let event = event.into();
if !self.tree.contains_value(&event) {
self.tree.push(self.escrow_db.get_key(id)?, event)?;
self.escrow_db.db.flush()?;
Ok(())
} else {
Ok(())
}
}
fn cleanup(&self, id: u64) -> Result<(), DbError> {
if let Some(data) = self.tree.iter_values(id) {
let new_data = data.filter(|e| !e.is_stale(self.duration).unwrap());
self.tree.put(id, new_data.collect())?;
};
Ok(())
}
pub fn get(&self, id: &IdentifierPrefix) -> Option<impl DoubleEndedIterator<Item = T>> {
let id_key = self.escrow_db.get_key(id).ok()?;
self.cleanup(id_key).ok();
self.tree
.iter_values(id_key)
.map(|t| t.map(|t| t.signed_event_message))
}
pub fn remove(&self, id: &IdentifierPrefix, event: &T) -> Result<(), DbError> {
let id_key = self.escrow_db.get_key(id)?;
self.tree.remove(id_key, &event.into())?;
self.escrow_db.db.flush()?;
Ok(())
}
pub fn get_all(&self) -> Option<impl DoubleEndedIterator<Item = T>> {
let keys = self.tree.get_keys().unwrap();
keys.for_each(|key| self.cleanup(key).unwrap());
self.tree
.get_all()
.map(|t| t.map(|t| t.signed_event_message))
}
}
pub struct EscrowDb {
identifiers: SledEventTree<IdentifierPrefix>,
db: Db,
}
impl EscrowDb {
pub fn new(path: impl AsRef<Path>) -> Result<Self, DbError> {
let db = sled::open(path)?;
Ok(Self {
identifiers: SledEventTree::new(db.open_tree(b"iids")?),
db,
})
}
pub fn add_bucket<V>(&self, name: V) -> Result<Tree, DbError>
where
V: AsRef<[u8]>,
{
Ok(self.db.open_tree(name)?)
}
pub fn get_key(&self, id: &IdentifierPrefix) -> Result<u64, DbError> {
self.identifiers.designated_key(id)
}
}