rusty_files/server/
state.rs1use crate::SearchEngine;
2use crate::server::config::ServerConfig;
3use crate::server::models::FileChangeEvent;
4use dashmap::DashMap;
5use parking_lot::RwLock;
6use std::path::PathBuf;
7use std::sync::atomic::{AtomicU64, Ordering};
8use std::sync::Arc;
9use std::time::Instant;
10use chrono::{DateTime, Utc};
11use tokio::sync::broadcast;
12
13pub struct AppState {
14 pub engine: Arc<RwLock<SearchEngine>>,
15 pub config: Arc<ServerConfig>,
16 pub metrics: Arc<Metrics>,
17 pub watchers: Arc<DashMap<String, WatchHandle>>,
18 pub event_tx: broadcast::Sender<FileChangeEvent>,
19 pub start_time: Instant,
20}
21
22impl AppState {
23 pub fn new(engine: SearchEngine, config: ServerConfig) -> Self {
24 let (event_tx, _) = broadcast::channel(1000);
25
26 Self {
27 engine: Arc::new(RwLock::new(engine)),
28 config: Arc::new(config),
29 metrics: Arc::new(Metrics::new()),
30 watchers: Arc::new(DashMap::new()),
31 event_tx,
32 start_time: Instant::now(),
33 }
34 }
35
36 pub fn uptime_seconds(&self) -> u64 {
37 self.start_time.elapsed().as_secs()
38 }
39}
40
41pub struct Metrics {
42 pub total_searches: AtomicU64,
43 pub total_search_time_ms: AtomicU64,
44 pub cache_hits: AtomicU64,
45 pub cache_misses: AtomicU64,
46}
47
48impl Metrics {
49 pub fn new() -> Self {
50 Self {
51 total_searches: AtomicU64::new(0),
52 total_search_time_ms: AtomicU64::new(0),
53 cache_hits: AtomicU64::new(0),
54 cache_misses: AtomicU64::new(0),
55 }
56 }
57
58 pub fn record_search(&self, duration_ms: u64) {
59 self.total_searches.fetch_add(1, Ordering::Relaxed);
60 self.total_search_time_ms
61 .fetch_add(duration_ms, Ordering::Relaxed);
62 }
63
64 pub fn avg_search_time_ms(&self) -> f64 {
65 let total = self.total_searches.load(Ordering::Relaxed);
66 if total == 0 {
67 return 0.0;
68 }
69 self.total_search_time_ms.load(Ordering::Relaxed) as f64 / total as f64
70 }
71
72 pub fn cache_hit_rate(&self) -> f32 {
73 let hits = self.cache_hits.load(Ordering::Relaxed);
74 let misses = self.cache_misses.load(Ordering::Relaxed);
75 let total = hits + misses;
76
77 if total == 0 {
78 return 0.0;
79 }
80
81 hits as f32 / total as f32
82 }
83}
84
85pub struct WatchHandle {
86 pub path: PathBuf,
87 pub recursive: bool,
88 pub created_at: DateTime<Utc>,
89}