From 8a0c71c49493b73d4edd8d8f853f9c7bdff47c18 Mon Sep 17 00:00:00 2001 From: JeremyLARDENOIS Date: Sun, 10 Aug 2025 17:55:59 +0200 Subject: [PATCH] refactor(app): split service into two parts --- src/adapters/driving/for_monitoring_alerts.rs | 4 +- src/app/alert_service.rs | 88 +++++++++++++++++++ src/app/metric_service.rs | 83 +++++++++++++++++ src/configurator.rs | 6 +- src/main.rs | 3 +- 5 files changed, 178 insertions(+), 6 deletions(-) create mode 100644 src/app/alert_service.rs create mode 100644 src/app/metric_service.rs diff --git a/src/adapters/driving/for_monitoring_alerts.rs b/src/adapters/driving/for_monitoring_alerts.rs index 5448c61..13f6a49 100644 --- a/src/adapters/driving/for_monitoring_alerts.rs +++ b/src/adapters/driving/for_monitoring_alerts.rs @@ -2,11 +2,11 @@ use crate::app::ports::driving::ForMonitoringAlerts; pub struct ForMonitoringAlertsAdapter { - app : crate::app::service::Service + app : crate::app::alert_service::AlertService } impl ForMonitoringAlertsAdapter { - pub fn new(app: crate::app::service::Service) -> Self { + pub fn new(app: crate::app::alert_service::AlertService) -> Self { ForMonitoringAlertsAdapter { app } } } diff --git a/src/app/alert_service.rs b/src/app/alert_service.rs new file mode 100644 index 0000000..204d29f --- /dev/null +++ b/src/app/alert_service.rs @@ -0,0 +1,88 @@ +use crate::app::ports::driven::{ + ForFormattingMessage, ForMonitoringSystem, ForSendingNotification, +}; + +pub struct AlertService { + notifier: Box, + monitor: Box, + formatter: Box, +} + +pub fn new( + notifier: Box, + monitor: Box, + formatter: Box, +) -> AlertService { + AlertService { + notifier, + monitor, + formatter, + } +} + +impl AlertService { + /// Check for threshold violations and send alerts + pub fn alert_on_threshold_violation(&self) -> Result<(), Box> { + let violations = self.monitor.check_thresholds(); + for violation in violations { + let message = self.formatter.format_violation(violation); + self.notifier.send_notification(&message)?; + } + + Ok(()) + } +} + + +#[cfg(test)] +mod tests { + use std::collections::HashMap; + + use crate::app::ports::driven::{MockForFormattingMessage, MockForMonitoringSystem, MockForSendingNotification}; + + use super::*; + + #[test] + fn test_alert_on_threshold_violation() { + let mut notifier = MockForSendingNotification::new(); + let mut monitor = MockForMonitoringSystem::new(); + let mut formatter = MockForFormattingMessage::new(); + + notifier.expect_send_notification().returning(|_| Ok(())); + monitor.expect_check_thresholds().returning(|| vec![]); + monitor.expect_get_metrics().returning(|| HashMap::new()); + formatter.expect_format_violation().returning(|_| "".to_string()); + formatter.expect_format_summary().returning(|_| "".to_string()); + + let service = new( + Box::new(notifier), + Box::new(monitor), + Box::new(formatter), + ); + + assert!(service.alert_on_threshold_violation().is_ok()); + } + + #[test] + fn test_alert_on_threshold_violation_handles_send_error() { + let mut notifier = MockForSendingNotification::new(); + let mut monitor = MockForMonitoringSystem::new(); + let mut formatter = MockForFormattingMessage::new(); + + monitor.expect_check_thresholds().returning(|| { + vec![Box::new(crate::app::ports::driven::MockForGettingViolationData::new())] + }); + formatter.expect_format_violation().returning(|_| "Test violation".to_string()); + + notifier.expect_send_notification() + .returning(|_| Err("Network error".into())); + + let service = new( + Box::new(notifier), + Box::new(monitor), + Box::new(formatter), + ); + + assert!(service.alert_on_threshold_violation().is_err()); + } +} diff --git a/src/app/metric_service.rs b/src/app/metric_service.rs new file mode 100644 index 0000000..3780025 --- /dev/null +++ b/src/app/metric_service.rs @@ -0,0 +1,83 @@ +use crate::app::ports::driven::{ + ForFormattingMessage, ForMonitoringSystem, ForSendingNotification, +}; + +pub struct MetricService { + notifier: Box, + monitor: Box, + formatter: Box, +} + +pub fn new( + notifier: Box, + monitor: Box, + formatter: Box, +) -> MetricService { + MetricService { + notifier, + monitor, + formatter, + } +} + +impl MetricService { + /// Send a final notification with all system information + pub fn send_all_metrics_notification(&self) -> Result<(), Box> { + let summary = self.formatter.format_summary(&self.monitor.get_metrics()); + self.notifier.send_notification(&summary)?; + + Ok(()) + } +} + + +#[cfg(test)] +mod tests { + use std::collections::HashMap; + + use crate::app::ports::driven::{MockForFormattingMessage, MockForMonitoringSystem, MockForSendingNotification}; + + use super::*; + + #[test] + fn test_send_all_metrics_notification() { + let mut notifier = MockForSendingNotification::new(); + let mut monitor = MockForMonitoringSystem::new(); + let mut formatter = MockForFormattingMessage::new(); + + notifier.expect_send_notification().returning(|_| Ok(())); + monitor.expect_check_thresholds().returning(|| vec![]); + monitor.expect_get_metrics().returning(|| HashMap::new()); + formatter.expect_format_violation().returning(|_| "".to_string()); + formatter.expect_format_summary().returning(|_| "".to_string()); + + let service = new( + Box::new(notifier), + Box::new(monitor), + Box::new(formatter), + ); + + assert!(service.send_all_metrics_notification().is_ok()); + } + + #[test] + fn test_send_all_metrics_notification_handles_send_error() { + let mut notifier = MockForSendingNotification::new(); + let mut monitor = MockForMonitoringSystem::new(); + let mut formatter = MockForFormattingMessage::new(); + + monitor.expect_get_metrics().returning(|| HashMap::new()); + formatter.expect_format_summary().returning(|_| "Test summary".to_string()); + + notifier.expect_send_notification() + .returning(|_| Err("Network error".into())); + + let service = new( + Box::new(notifier), + Box::new(monitor), + Box::new(formatter), + ); + + assert!(service.send_all_metrics_notification().is_err()); + } +} diff --git a/src/configurator.rs b/src/configurator.rs index 0be264c..484f2a1 100644 --- a/src/configurator.rs +++ b/src/configurator.rs @@ -23,7 +23,7 @@ pub fn get_cron_actor( let formatter = actors::driven::for_formatting_message::alert_formatter::AlertFormatter; - let service = app::service::new( + let service = app::alert_service::new( Box::new(discord_adapter), Box::new(system_monitor_adapter), Box::new(formatter), @@ -34,7 +34,7 @@ pub fn get_cron_actor( actors::driving::cron_alerts::CronAlertsActor::new(Box::new(service_adapter), duration) } -pub fn get_get_service() -> app::service::Service { +pub fn get_get_service() -> app::metric_service::MetricService { let notifier = actors::driven::for_sending_notification::print::StdoutNotificationActor::new(); let monitor = @@ -44,7 +44,7 @@ pub fn get_get_service() -> app::service::Service { let formatter = actors::driven::for_formatting_message::alert_formatter::AlertFormatter; - app::service::new( + app::metric_service::new( Box::new(notifier), Box::new(system_monitor_adapter), Box::new(formatter), diff --git a/src/main.rs b/src/main.rs index 93f5ad9..90c649c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,9 @@ use clap::{Parser, Subcommand}; mod app { + pub mod alert_service; + pub mod metric_service; pub mod ports; - pub mod service; } mod adapters {