use std::collections::{HashMap, VecDeque};
use std::sync::{Arc, RwLock};
use std::time::Instant;
use once_cell::sync::Lazy;
use super::types::{FailureCategory, FailureMode};
pub static FMEA_REGISTRY: Lazy<Arc<RwLock<FmeaRegistry>>> = Lazy::new(|| {
let mut registry = FmeaRegistry::new();
super::catalog::register_critical_failures(&mut registry);
Arc::new(RwLock::new(registry))
});
#[derive(Debug)]
pub struct FmeaRegistry {
failure_modes: HashMap<String, FailureMode>,
events: VecDeque<FailureEvent>,
max_events: usize,
}
impl FmeaRegistry {
pub fn new() -> Self {
Self {
failure_modes: HashMap::new(),
events: VecDeque::new(),
max_events: 1000,
}
}
pub fn register(&mut self, mode: FailureMode) {
self.failure_modes.insert(mode.id.clone(), mode);
}
pub fn record_event(&mut self, event: FailureEvent) {
if self.events.len() >= self.max_events {
self.events.pop_front();
}
self.events.push_back(event);
}
pub fn get_failure_mode(&self, id: &str) -> Option<&FailureMode> {
self.failure_modes.get(id)
}
pub fn all_failure_modes(&self) -> impl Iterator<Item = &FailureMode> {
self.failure_modes.values()
}
pub fn failure_modes_by_category(
&self, category: FailureCategory,
) -> impl Iterator<Item = &FailureMode> {
self.failure_modes
.values()
.filter(move |m| m.category == category)
}
pub fn recent_events(&self, limit: usize) -> impl Iterator<Item = &FailureEvent> {
self.events.iter().rev().take(limit)
}
pub fn events_for_mode<'a>(
&'a self, mode_id: &'a str,
) -> impl Iterator<Item = &'a FailureEvent> {
self.events.iter().filter(move |e| e.mode_id == mode_id)
}
pub fn event_count(&self) -> usize {
self.events.len()
}
pub fn failure_mode_count(&self) -> usize {
self.failure_modes.len()
}
#[cfg(test)]
pub fn clear_events(&mut self) {
self.events.clear();
}
}
impl Default for FmeaRegistry {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct FailureEvent {
pub mode_id: String,
pub timestamp: Instant,
pub error_message: String,
pub context: Option<String>,
pub source_chain: Vec<String>,
pub operation: String,
pub metadata: HashMap<String, String>,
}
impl FailureEvent {
pub fn new(mode_id: String, operation: String, error_message: String) -> Self {
Self {
mode_id,
timestamp: Instant::now(),
error_message,
context: None,
source_chain: Vec::new(),
operation,
metadata: HashMap::new(),
}
}
pub fn with_context(mut self, context: String) -> Self {
self.context = Some(context);
self
}
pub fn with_source_chain(mut self, chain: Vec<String>) -> Self {
self.source_chain = chain;
self
}
pub fn with_metadata(mut self, key: String, value: String) -> Self {
self.metadata.insert(key, value);
self
}
}
impl Default for FailureEvent {
fn default() -> Self {
Self::new(String::new(), String::new(), String::new())
}
}