use std::collections::HashMap;
use std::time::{Duration, Instant};
use uuid::Uuid;
pub(crate) struct ScriptRegistry {
limit: Duration,
scripts: HashMap<Uuid, (String, Instant)>,
}
impl ScriptRegistry {
pub(crate) fn new(limit: Duration) -> Self {
Self {
limit,
scripts: HashMap::new(),
}
}
pub(crate) fn get(&mut self, id: &Uuid) -> Option<String> {
let now = Instant::now();
if let Some(o) = self.scripts.get_mut(id) {
o.1 = now;
}
self.scripts.get(id).map(|(s, _)| s.to_string())
}
pub(crate) fn remove(&mut self, id: &Uuid) {
self.scripts.remove(id);
}
pub(crate) fn store(&mut self, script: String) -> Uuid {
let id = Uuid::new_v4();
let now = Instant::now();
let limit = self.limit;
self.scripts
.retain(|_, &mut (_, last_accessed)| now.duration_since(last_accessed) <= limit);
self.scripts.insert(id, (script, now));
id
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_script_registry_get_none() {
let mut registry = ScriptRegistry::new(Duration::from_millis(0));
assert!(registry
.get(&Uuid::parse_str("50b0cb8f-1f59-4ba5-8935-ba54bb64bc3f").unwrap())
.is_none());
let script = "function() { return 3 + 4; }";
let id = registry.store(script.to_string());
assert_eq!(registry.get(&id), Some(script.to_string()));
}
#[test]
fn test_script_registry_store_and_get() {
let mut registry = ScriptRegistry::new(Duration::from_millis(0));
let script = "function() { return 3 + 4; }";
let id = registry.store(script.to_string());
assert_eq!(registry.get(&id), Some(script.to_string()));
}
#[test]
fn test_script_registry_store_and_remove() {
let mut registry = ScriptRegistry::new(Duration::from_millis(60000));
let script = "function() { return 3 + 4; }";
let id = registry.store(script.to_string());
registry.remove(&id);
assert_eq!(registry.get(&id), None);
}
#[test]
fn test_script_registry_evicts_old_entries() {
let mut registry = ScriptRegistry::new(Duration::from_millis(1));
let script = "function() { return 3 + 4; }";
let id = registry.store(script.to_string());
std::thread::sleep(Duration::from_millis(50));
let _ = registry.store(script.to_string());
assert_eq!(registry.get(&id), None);
}
#[test]
fn test_script_registry_get_extends_eviction() {
let mut registry = ScriptRegistry::new(Duration::from_millis(10));
let script = "function() { return 3 + 4; }";
let id = registry.store(script.to_string());
std::thread::sleep(Duration::from_millis(100));
let _ = registry.get(&id);
let _ = registry.store(script.to_string());
assert_eq!(registry.get(&id), Some(script.to_string()));
}
}