Fix user-stopped service display and flag timing issues
All checks were successful
Build and Release / build-and-release (push) Successful in 2m10s

Improve user-stopped service tracking behavior:

Service Display Fix:
- Services widget now shows actual systemctl status (active/inactive)
- Use info.status instead of hardcoded text based on widget_status
- User-stopped services correctly display 'inactive' with green OK icon
- Prevents misleading 'active' display for stopped services

User-Stopped Flag Timing Fix:
- Clear user-stopped flag AFTER successful service start, not when command sent
- Prevents warnings during service startup transition period
- Service remains Status::OK during 'activating' state for user-stopped services
- Flag only cleared when systemctl start command actually succeeds
- Failed start attempts preserve user-stopped flag

Result: Clean service state tracking with accurate display and no false alerts
during intentional user operations.

Bump version to v0.1.45
This commit is contained in:
Christoffer Martinsson 2025-10-30 11:11:39 +01:00
parent a82c81e8e3
commit aeae60146d
6 changed files with 20 additions and 21 deletions

6
Cargo.lock generated
View File

@ -270,7 +270,7 @@ checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d"
[[package]] [[package]]
name = "cm-dashboard" name = "cm-dashboard"
version = "0.1.43" version = "0.1.44"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"chrono", "chrono",
@ -291,7 +291,7 @@ dependencies = [
[[package]] [[package]]
name = "cm-dashboard-agent" name = "cm-dashboard-agent"
version = "0.1.43" version = "0.1.44"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
@ -314,7 +314,7 @@ dependencies = [
[[package]] [[package]]
name = "cm-dashboard-shared" name = "cm-dashboard-shared"
version = "0.1.43" version = "0.1.44"
dependencies = [ dependencies = [
"chrono", "chrono",
"serde", "serde",

View File

@ -1,6 +1,6 @@
[package] [package]
name = "cm-dashboard-agent" name = "cm-dashboard-agent"
version = "0.1.44" version = "0.1.45"
edition = "2021" edition = "2021"
[dependencies] [dependencies]

View File

@ -288,7 +288,7 @@ impl Agent {
info!("Executing systemctl {} {} (user action: {})", action_str, service_name, is_user_action); info!("Executing systemctl {} {} (user action: {})", action_str, service_name, is_user_action);
// Handle user-stopped service tracking before systemctl execution // Handle user-stopped service tracking before systemctl execution (stop only)
match action { match action {
ServiceAction::UserStop => { ServiceAction::UserStop => {
info!("Marking service '{}' as user-stopped", service_name); info!("Marking service '{}' as user-stopped", service_name);
@ -299,15 +299,6 @@ impl Agent {
UserStoppedServiceTracker::update_global(&self.service_tracker); UserStoppedServiceTracker::update_global(&self.service_tracker);
} }
} }
ServiceAction::UserStart => {
info!("Clearing user-stopped flag for service '{}'", service_name);
if let Err(e) = self.service_tracker.clear_user_stopped(service_name) {
error!("Failed to clear user-stopped flag: {}", e);
} else {
// Sync to global tracker
UserStoppedServiceTracker::update_global(&self.service_tracker);
}
}
_ => {} _ => {}
} }
@ -323,6 +314,17 @@ impl Agent {
if !output.stdout.is_empty() { if !output.stdout.is_empty() {
debug!("stdout: {}", String::from_utf8_lossy(&output.stdout)); debug!("stdout: {}", String::from_utf8_lossy(&output.stdout));
} }
// Clear user-stopped flag AFTER successful start command
if matches!(action, ServiceAction::UserStart) {
info!("Clearing user-stopped flag for service '{}' after successful start", service_name);
if let Err(e) = self.service_tracker.clear_user_stopped(service_name) {
error!("Failed to clear user-stopped flag: {}", e);
} else {
// Sync to global tracker
UserStoppedServiceTracker::update_global(&self.service_tracker);
}
}
} else { } else {
let stderr = String::from_utf8_lossy(&output.stderr); let stderr = String::from_utf8_lossy(&output.stderr);
error!("Service {} {} failed: {}", service_name, action_str, stderr); error!("Service {} {} failed: {}", service_name, action_str, stderr);

View File

@ -1,6 +1,6 @@
[package] [package]
name = "cm-dashboard" name = "cm-dashboard"
version = "0.1.44" version = "0.1.45"
edition = "2021" edition = "2021"
[dependencies] [dependencies]

View File

@ -113,13 +113,10 @@ impl ServicesWidget {
name.to_string() name.to_string()
}; };
// Parent services always show active/inactive status // Parent services always show actual systemctl status
let status_str = match info.widget_status { let status_str = match info.widget_status {
Status::Ok => "active".to_string(),
Status::Pending => "pending".to_string(), Status::Pending => "pending".to_string(),
Status::Warning => "inactive".to_string(), _ => info.status.clone(), // Use actual status from agent (active/inactive/failed)
Status::Critical => "failed".to_string(),
Status::Unknown => "unknown".to_string(),
}; };
format!( format!(

View File

@ -1,6 +1,6 @@
[package] [package]
name = "cm-dashboard-shared" name = "cm-dashboard-shared"
version = "0.1.44" version = "0.1.45"
edition = "2021" edition = "2021"
[dependencies] [dependencies]