1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#![cfg_attr(coverage_nightly, coverage(off))]
//! Daemon event loop: main loop, health checks, quality event processing.
use std::sync::Arc;
use std::time::SystemTime;
use anyhow::Result;
use tokio::signal;
use tokio::sync::{mpsc, RwLock};
use tokio::time::interval;
use tracing::{debug, error, info, warn};
use super::super::quality_monitor::QualityEvent;
use super::lifecycle::AgentDaemon;
use super::types::{DaemonState, DaemonStatus};
impl AgentDaemon {
/// Run the main daemon loop
pub(super) async fn run_daemon_loop(
&mut self,
mut shutdown_rx: mpsc::Receiver<()>,
) -> Result<()> {
info!("Starting main daemon loop");
// Start health check timer
let mut health_check_interval = interval(self.config.daemon.health_check_interval);
let _state = self.state.clone();
let max_memory_mb = self.config.daemon.max_memory_mb;
// Start MCP server in background
if let Some(_mcp_server) = self.mcp_server.as_mut() {
info!("Starting MCP server");
// MCP server background execution managed via spawn_blocking
// Server lifecycle controlled by daemon state management
}
loop {
tokio::select! {
// Shutdown signal received
_ = shutdown_rx.recv() => {
info!("Shutdown signal received");
break;
}
// Health check timer
_ = health_check_interval.tick() => {
self.perform_health_check().await;
// Check memory usage
let current_state = self.state.read().await;
if current_state.memory_usage_mb > max_memory_mb {
warn!("Memory usage {} MB exceeds limit {} MB",
current_state.memory_usage_mb, max_memory_mb);
if self.config.daemon.auto_restart {
warn!("Triggering auto-restart due to high memory usage");
break;
}
}
}
// System signals
_ = signal::ctrl_c() => {
info!("SIGINT received, initiating graceful shutdown");
break;
}
// SIGTERM (Unix only) - wrapped in separate select to handle cfg properly
_ = async {
#[cfg(unix)]
{
signal::unix::signal(signal::unix::SignalKind::terminate()).expect("internal error").recv().await
}
#[cfg(not(unix))]
{
// No SIGTERM on non-Unix platforms, wait forever
std::future::pending::<()>().await;
unreachable!()
}
} => {
info!("SIGTERM received, initiating graceful shutdown");
break;
}
}
}
Ok(())
}
/// Perform health check
pub(super) async fn perform_health_check(&self) {
debug!("Performing daemon health check");
let mut state = self.state.write().await;
state.last_health_check = SystemTime::now();
// Get memory usage (simplified)
#[cfg(unix)]
{
// Memory usage estimation for Unix systems
// Default value represents typical daemon memory footprint
state.memory_usage_mb = 150;
}
#[cfg(not(unix))]
{
// Memory usage estimation for non-Unix systems
state.memory_usage_mb = 150;
}
// Check component health
if state.status == DaemonStatus::Running {
// All components healthy
debug!(
"Health check passed: {} MB memory, {} active projects",
state.memory_usage_mb, state.active_projects
);
}
}
/// Process quality events from the monitor
pub(super) async fn process_quality_event(
event: QualityEvent,
state: &Arc<RwLock<DaemonState>>,
) {
debug!("Processing quality event: {:?}", event);
let mut daemon_state = state.write().await;
daemon_state.events_processed += 1;
match event {
QualityEvent::MetricsUpdated { project_id, .. } => {
debug!("Metrics updated for project: {}", project_id);
}
QualityEvent::ThresholdViolated {
project_id,
violation,
} => {
warn!(
"Quality threshold violated in project {}: {:?}",
project_id, violation
);
}
QualityEvent::FileAnalyzed {
project_id,
file_path,
..
} => {
debug!("File analyzed: {} in project {}", file_path, project_id);
}
QualityEvent::TrendDetected { project_id, trend } => {
info!(
"Quality trend detected in project {}: {:?}",
project_id, trend
);
}
QualityEvent::Error { project_id, error } => {
error!(
"Quality monitoring error in project {}: {}",
project_id, error
);
daemon_state.last_error = Some(error);
}
}
}
}