- Fix duplicate storage pool issue by clearing cache on agent startup - Change storage pool header text to normal color for better readability - Improve services panel tree icons with proper └─ symbols for last items - Ensure fresh metrics data on each agent restart
129 lines
3.9 KiB
Rust
129 lines
3.9 KiB
Rust
use cm_dashboard_shared::{CacheConfig, Metric};
|
|
use std::collections::HashMap;
|
|
use std::fs;
|
|
use std::path::Path;
|
|
use std::sync::Arc;
|
|
use tokio::sync::RwLock;
|
|
use tracing::{info, warn, error};
|
|
|
|
/// Simple persistent cache for metrics
|
|
pub struct SimpleCache {
|
|
metrics: RwLock<HashMap<String, Metric>>,
|
|
persist_path: String,
|
|
}
|
|
|
|
impl SimpleCache {
|
|
pub fn new(config: CacheConfig) -> Self {
|
|
let cache = Self {
|
|
metrics: RwLock::new(HashMap::new()),
|
|
persist_path: config.persist_path,
|
|
};
|
|
|
|
// Clear cache file on startup to ensure fresh data
|
|
cache.clear_cache_file();
|
|
cache
|
|
}
|
|
|
|
/// Store metric in cache
|
|
pub async fn store_metric(&self, metric: Metric) {
|
|
let mut metrics = self.metrics.write().await;
|
|
metrics.insert(metric.name.clone(), metric);
|
|
}
|
|
|
|
/// Get all cached metrics
|
|
pub async fn get_all_cached_metrics(&self) -> Vec<Metric> {
|
|
let metrics = self.metrics.read().await;
|
|
metrics.values().cloned().collect()
|
|
}
|
|
|
|
/// Save cache to disk
|
|
pub async fn save_to_disk(&self) {
|
|
let metrics = self.metrics.read().await;
|
|
|
|
// Create directory if needed
|
|
if let Some(parent) = Path::new(&self.persist_path).parent() {
|
|
if let Err(e) = fs::create_dir_all(parent) {
|
|
warn!("Failed to create cache directory {}: {}", parent.display(), e);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Serialize and save
|
|
match serde_json::to_string_pretty(&*metrics) {
|
|
Ok(json) => {
|
|
if let Err(e) = fs::write(&self.persist_path, json) {
|
|
error!("Failed to save cache to {}: {}", self.persist_path, e);
|
|
}
|
|
}
|
|
Err(e) => {
|
|
error!("Failed to serialize cache: {}", e);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Load cache from disk
|
|
fn load_from_disk(&self) {
|
|
match fs::read_to_string(&self.persist_path) {
|
|
Ok(content) => {
|
|
match serde_json::from_str::<HashMap<String, Metric>>(&content) {
|
|
Ok(loaded_metrics) => {
|
|
if let Ok(mut metrics) = self.metrics.try_write() {
|
|
*metrics = loaded_metrics;
|
|
info!("Loaded {} metrics from cache", metrics.len());
|
|
}
|
|
}
|
|
Err(e) => {
|
|
warn!("Failed to parse cache file {}: {}", self.persist_path, e);
|
|
}
|
|
}
|
|
}
|
|
Err(_) => {
|
|
info!("No cache file found at {}, starting fresh", self.persist_path);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Clear cache file on startup to ensure fresh data
|
|
fn clear_cache_file(&self) {
|
|
if Path::new(&self.persist_path).exists() {
|
|
match fs::remove_file(&self.persist_path) {
|
|
Ok(_) => info!("Cleared cache file {} on startup", self.persist_path),
|
|
Err(e) => warn!("Failed to clear cache file {}: {}", self.persist_path, e),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#[derive(Clone)]
|
|
pub struct MetricCacheManager {
|
|
cache: Arc<SimpleCache>,
|
|
}
|
|
|
|
impl MetricCacheManager {
|
|
pub fn new(config: CacheConfig) -> Self {
|
|
Self {
|
|
cache: Arc::new(SimpleCache::new(config)),
|
|
}
|
|
}
|
|
|
|
pub async fn store_metric(&self, metric: Metric) {
|
|
self.cache.store_metric(metric).await;
|
|
}
|
|
|
|
pub async fn cache_metric(&self, metric: Metric) {
|
|
self.store_metric(metric).await;
|
|
}
|
|
|
|
pub async fn start_background_tasks(&self) {
|
|
// No background tasks needed for simple cache
|
|
}
|
|
|
|
pub async fn get_all_cached_metrics(&self) -> Result<Vec<Metric>, anyhow::Error> {
|
|
Ok(self.cache.get_all_cached_metrics().await)
|
|
}
|
|
|
|
pub async fn save_to_disk(&self) {
|
|
self.cache.save_to_disk().await;
|
|
}
|
|
} |