use forge_models::{TaskOwnershipContext, TaskRecord}; use std::collections::HashMap; use std::sync::{Arc, RwLock}; pub trait TaskRepository: Send + Sync { fn reset(&self) -> Result<(), String>; fn list_catalog(&self) -> Result, String>; fn get_catalog_entry(&self, id: &str) -> Result, String>; fn save_catalog_entry(&self, id: String, entry: TaskRecord) -> Result<(), String>; fn delete_catalog_entry(&self, id: &str) -> Result<(), String>; fn get_ownership(&self, id: &str) -> Result, String>; fn save_ownership(&self, id: String, ownership: TaskOwnershipContext) -> Result<(), String>; fn delete_ownership(&self, id: &str) -> Result<(), String>; fn list_active_statuses(&self) -> Result, String>; fn get_active_status(&self, id: &str) -> Result, String>; fn set_active_status(&self, id: String, status: String) -> Result<(), String>; fn delete_active_status(&self, id: &str) -> Result<(), String>; fn get_completed_status(&self, id: &str) -> Result, String>; fn set_completed_status(&self, id: String, status: String) -> Result<(), String>; fn delete_completed_status(&self, id: &str) -> Result<(), String>; fn increment_defuse_count(&self, id: &str) -> Result; fn get_defuse_count(&self, id: &str) -> Result; fn clear_defuse_count(&self, id: &str) -> Result<(), String>; } #[derive(Debug, Default)] struct TaskState { catalog: HashMap, ownership: HashMap, active_statuses: HashMap, completed_statuses: HashMap, defuse_counts: HashMap, } #[derive(Clone, Debug, Default)] pub struct InMemoryTaskRepository { state: Arc>, } impl InMemoryTaskRepository { pub fn new() -> Self { Self::default() } } impl TaskRepository for InMemoryTaskRepository { fn reset(&self) -> Result<(), String> { let mut state = self .state .write() .map_err(|_| "Task state lock poisoned.".to_string())?; state.catalog.clear(); state.ownership.clear(); state.active_statuses.clear(); state.completed_statuses.clear(); state.defuse_counts.clear(); Ok(()) } fn list_catalog(&self) -> Result, String> { self.state .read() .map(|state| state.catalog.clone()) .map_err(|_| "Task catalog state lock poisoned.".to_string()) } fn get_catalog_entry(&self, id: &str) -> Result, String> { self.state .read() .map(|state| state.catalog.get(id).cloned()) .map_err(|_| "Task catalog state lock poisoned.".to_string()) } fn save_catalog_entry(&self, id: String, entry: TaskRecord) -> Result<(), String> { self.state .write() .map_err(|_| "Task catalog state lock poisoned.".to_string())? .catalog .insert(id, entry); Ok(()) } fn delete_catalog_entry(&self, id: &str) -> Result<(), String> { self.state .write() .map_err(|_| "Task catalog state lock poisoned.".to_string())? .catalog .remove(id); Ok(()) } fn get_ownership(&self, id: &str) -> Result, String> { self.state .read() .map(|state| state.ownership.get(id).cloned()) .map_err(|_| "Task ownership state lock poisoned.".to_string()) } fn save_ownership(&self, id: String, ownership: TaskOwnershipContext) -> Result<(), String> { self.state .write() .map_err(|_| "Task ownership state lock poisoned.".to_string())? .ownership .insert(id, ownership); Ok(()) } fn delete_ownership(&self, id: &str) -> Result<(), String> { self.state .write() .map_err(|_| "Task ownership state lock poisoned.".to_string())? .ownership .remove(id); Ok(()) } fn list_active_statuses(&self) -> Result, String> { self.state .read() .map(|state| state.active_statuses.clone()) .map_err(|_| "Task status state lock poisoned.".to_string()) } fn get_active_status(&self, id: &str) -> Result, String> { self.state .read() .map(|state| state.active_statuses.get(id).cloned()) .map_err(|_| "Task status state lock poisoned.".to_string()) } fn set_active_status(&self, id: String, status: String) -> Result<(), String> { self.state .write() .map_err(|_| "Task status state lock poisoned.".to_string())? .active_statuses .insert(id, status); Ok(()) } fn delete_active_status(&self, id: &str) -> Result<(), String> { self.state .write() .map_err(|_| "Task status state lock poisoned.".to_string())? .active_statuses .remove(id); Ok(()) } fn get_completed_status(&self, id: &str) -> Result, String> { self.state .read() .map(|state| state.completed_statuses.get(id).cloned()) .map_err(|_| "Task completed status state lock poisoned.".to_string()) } fn set_completed_status(&self, id: String, status: String) -> Result<(), String> { self.state .write() .map_err(|_| "Task completed status state lock poisoned.".to_string())? .completed_statuses .insert(id, status); Ok(()) } fn delete_completed_status(&self, id: &str) -> Result<(), String> { self.state .write() .map_err(|_| "Task completed status state lock poisoned.".to_string())? .completed_statuses .remove(id); Ok(()) } fn increment_defuse_count(&self, id: &str) -> Result { let mut state = self .state .write() .map_err(|_| "Task defuse state lock poisoned.".to_string())?; let next_count = 1 + state.defuse_counts.get(id).copied().unwrap_or_default(); state.defuse_counts.insert(id.to_string(), next_count); Ok(next_count) } fn get_defuse_count(&self, id: &str) -> Result { self.state .read() .map(|state| state.defuse_counts.get(id).copied().unwrap_or_default()) .map_err(|_| "Task defuse state lock poisoned.".to_string()) } fn clear_defuse_count(&self, id: &str) -> Result<(), String> { self.state .write() .map_err(|_| "Task defuse state lock poisoned.".to_string())? .defuse_counts .remove(id); Ok(()) } }