use serde::{Deserialize, Serialize};
use std::{collections::HashMap, future::Future, pin::Pin, sync::Arc};
use tokio::sync::Mutex;
use walr::WAL;
type Cache = HashMap<String, String>;
#[derive(Serialize, Deserialize)]
enum CacheLog {
Remove(String),
Insert { key: String, value: String },
}
impl CacheLog {
fn inner(self) -> (String, Option<String>) {
match self {
Self::Remove(key) => (key, None),
Self::Insert { key, value } => (key, Some(value)),
}
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
fn replay_handler(logs: Vec<CacheLog>, checkpoint: Arc<Mutex<Cache>>) -> ReplayHandlerResult {
Box::pin(async move {
let mut checkpoint = checkpoint.lock().await;
for log in logs {
match log {
CacheLog::Insert { key, value } => checkpoint.insert(key, value),
CacheLog::Remove(key) => checkpoint.remove(&key),
};
}
Ok(())
})
}
let mut wal: WAL<CacheLog, Cache> =
WAL::open("./cache_wal", Box::new(replay_handler), None).await?;
let mut cache = wal.replay().await?;
let log = CacheLog::Insert {
key: "some id".to_string(),
value: "some data".to_string(),
};
wal.log(&log).await?;
let (key, value) = log.inner();
cache.insert(key, value.unwrap());
let mut logs = vec![];
for string in vec!["1".to_string(), "2".to_string()] {
logs.push(CacheLog::Insert {
key: string.clone(),
value: string,
});
}
wal.log_many(&logs).await?;
for log in logs {
let (key, value) = log.inner();
cache.insert(key, value.unwrap());
}
wal.checkpoint(&cache).await?;
Ok(())
}