use std::collections::HashMap;
use std::sync::Mutex;
#[derive(Debug, Clone)]
pub struct ReplicaEntry {
pub payload: Vec<u8>,
pub sequence: u64,
pub timestamp_millis: i64,
}
#[derive(Debug, Default)]
pub struct ReplicaStore {
entries: Mutex<HashMap<String, ReplicaEntry>>,
}
impl ReplicaStore {
pub fn new() -> Self {
Self::default()
}
fn key(grain_type: &str, grain_key: &str) -> String {
format!("{}/{}", grain_type, grain_key)
}
pub fn update(
&self,
grain_type: &str,
grain_key: &str,
payload: Vec<u8>,
sequence: u64,
timestamp_millis: i64,
) {
let mut entries = self.entries.lock().expect("replica store lock poisoned");
entries.insert(
Self::key(grain_type, grain_key),
ReplicaEntry {
payload,
sequence,
timestamp_millis,
},
);
}
pub fn get(&self, grain_type: &str, grain_key: &str) -> Option<ReplicaEntry> {
let entries = self.entries.lock().expect("replica store lock poisoned");
entries.get(&Self::key(grain_type, grain_key)).cloned()
}
pub fn is_fresh(&self, grain_type: &str, grain_key: &str, max_staleness_millis: i64) -> bool {
let entries = self.entries.lock().expect("replica store lock poisoned");
if let Some(entry) = entries.get(&Self::key(grain_type, grain_key)) {
let now = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap_or_default()
.as_millis() as i64;
(now - entry.timestamp_millis) <= max_staleness_millis
} else {
false
}
}
pub fn remove(&self, grain_type: &str, grain_key: &str) {
let mut entries = self.entries.lock().expect("replica store lock poisoned");
entries.remove(&Self::key(grain_type, grain_key));
}
}