use super::SystemInfo;
use std::time::{Duration, Instant};
#[derive(Debug, Clone)]
pub struct CacheEntry {
pub info: SystemInfo,
pub cached_at: Instant,
}
#[derive(Debug, Default)]
pub struct SystemInfoCache {
entry: Option<CacheEntry>,
}
impl SystemInfoCache {
pub fn new() -> Self {
Self { entry: None }
}
pub fn get_if_valid(&self, ttl: Duration) -> Option<&SystemInfo> {
self.entry.as_ref().and_then(|entry| {
if entry.cached_at.elapsed() < ttl {
Some(&entry.info)
} else {
None
}
})
}
pub fn set(&mut self, info: SystemInfo) {
self.entry = Some(CacheEntry {
info,
cached_at: Instant::now(),
});
}
pub fn invalidate(&mut self) {
self.entry = None;
}
pub fn is_valid(&self, ttl: Duration) -> bool {
self.entry
.as_ref()
.map(|e| e.cached_at.elapsed() < ttl)
.unwrap_or(false)
}
pub fn age(&self) -> Option<Duration> {
self.entry.as_ref().map(|e| e.cached_at.elapsed())
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::thread::sleep;
fn create_test_info() -> SystemInfo {
SystemInfo {
os: super::super::OsInfo {
name: "test".to_string(),
version: "1.0".to_string(),
arch: "x86_64".to_string(),
family: "unix".to_string(),
},
shell: super::super::ShellInfo {
name: "bash".to_string(),
version: Some("5.0".to_string()),
path: std::path::PathBuf::from("/bin/bash"),
},
languages: vec![],
package_managers: vec![],
project: None,
git: None,
build_tools: vec![],
test_frameworks: vec![],
collected_at: std::time::SystemTime::now(),
}
}
#[test]
fn test_cache_empty() {
let cache = SystemInfoCache::new();
assert!(cache.get_if_valid(Duration::from_secs(60)).is_none());
assert!(!cache.is_valid(Duration::from_secs(60)));
}
#[test]
fn test_cache_set_get() {
let mut cache = SystemInfoCache::new();
let info = create_test_info();
cache.set(info);
assert!(cache.get_if_valid(Duration::from_secs(60)).is_some());
assert!(cache.is_valid(Duration::from_secs(60)));
}
#[test]
fn test_cache_invalidate() {
let mut cache = SystemInfoCache::new();
cache.set(create_test_info());
cache.invalidate();
assert!(cache.get_if_valid(Duration::from_secs(60)).is_none());
}
#[test]
fn test_cache_ttl_expiry() {
let mut cache = SystemInfoCache::new();
cache.set(create_test_info());
sleep(Duration::from_millis(10));
assert!(cache.get_if_valid(Duration::from_millis(1)).is_none());
assert!(!cache.is_valid(Duration::from_millis(1)));
}
}