Architecture remediation A/B/F: poison-tolerant locks, graceful backend init, doc fixes
Workstream A — poison-tolerant locking: - Add utils/lock.rs with MutexSafe/RwLockSafe extension traits that recover a poisoned std::sync lock instead of panicking, plus unit tests. - Replace all 153 .lock().unwrap() and 4 .read()/.write().unwrap() production sites with _safe variants across 14 files, eliminating the player crash-cascade class. Tokio async mutexes are unchanged. Workstream B — graceful backend init: - create_player_backend no longer panics when MPV/ExoPlayer fail to initialize; it falls back to NullBackend and emits a backend-init-failed event so the UI can show "playback unavailable" instead of the app crashing. Fatal DB-setup panics are kept. Workstream F — doc reconciliation: - Rewrite software-architecture.md's inaccurate "thin UI / ~800 lines" claims to reflect reality (~20.5k non-test frontend) and document the events+polling hybrid plus the new locking/backend-init behavior.
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
use crate::utils::lock::MutexSafe;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::{Duration, Instant};
|
||||
@@ -34,7 +35,7 @@ impl EventThrottler {
|
||||
|
||||
/// Checks if enough time has elapsed since the last report for this item
|
||||
pub fn should_report(&self, item_id: &str) -> bool {
|
||||
let last_times = self.last_report_time.lock().unwrap();
|
||||
let last_times = self.last_report_time.lock_safe();
|
||||
|
||||
if let Some(last_time) = last_times.get(item_id) {
|
||||
let elapsed = last_time.elapsed();
|
||||
@@ -54,7 +55,7 @@ impl EventThrottler {
|
||||
|
||||
/// Marks the item as reported at the current time
|
||||
pub fn mark_reported(&self, item_id: &str) {
|
||||
let mut last_times = self.last_report_time.lock().unwrap();
|
||||
let mut last_times = self.last_report_time.lock_safe();
|
||||
last_times.insert(item_id.to_string(), Instant::now());
|
||||
|
||||
log::debug!(
|
||||
@@ -66,14 +67,14 @@ impl EventThrottler {
|
||||
|
||||
/// Clears all tracked report times
|
||||
pub fn clear(&self) {
|
||||
let mut last_times = self.last_report_time.lock().unwrap();
|
||||
let mut last_times = self.last_report_time.lock_safe();
|
||||
last_times.clear();
|
||||
log::debug!("[EventThrottler] Cleared all tracked report times");
|
||||
}
|
||||
|
||||
/// Removes a specific item from tracking
|
||||
pub fn clear_item(&self, item_id: &str) {
|
||||
let mut last_times = self.last_report_time.lock().unwrap();
|
||||
let mut last_times = self.last_report_time.lock_safe();
|
||||
last_times.remove(item_id);
|
||||
log::debug!("[EventThrottler] Cleared tracking for {}", item_id);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user