refactor(app): split service into two parts

This commit is contained in:
2025-08-10 17:55:59 +02:00
parent a9149178d4
commit 8a0c71c494
5 changed files with 178 additions and 6 deletions

View File

@@ -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 }
}
}

88
src/app/alert_service.rs Normal file
View File

@@ -0,0 +1,88 @@
use crate::app::ports::driven::{
ForFormattingMessage, ForMonitoringSystem, ForSendingNotification,
};
pub struct AlertService {
notifier: Box<dyn ForSendingNotification>,
monitor: Box<dyn ForMonitoringSystem>,
formatter: Box<dyn ForFormattingMessage>,
}
pub fn new(
notifier: Box<dyn ForSendingNotification>,
monitor: Box<dyn ForMonitoringSystem>,
formatter: Box<dyn ForFormattingMessage>,
) -> AlertService {
AlertService {
notifier,
monitor,
formatter,
}
}
impl AlertService {
/// Check for threshold violations and send alerts
pub fn alert_on_threshold_violation(&self) -> Result<(), Box<dyn std::error::Error>> {
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());
}
}

83
src/app/metric_service.rs Normal file
View File

@@ -0,0 +1,83 @@
use crate::app::ports::driven::{
ForFormattingMessage, ForMonitoringSystem, ForSendingNotification,
};
pub struct MetricService {
notifier: Box<dyn ForSendingNotification>,
monitor: Box<dyn ForMonitoringSystem>,
formatter: Box<dyn ForFormattingMessage>,
}
pub fn new(
notifier: Box<dyn ForSendingNotification>,
monitor: Box<dyn ForMonitoringSystem>,
formatter: Box<dyn ForFormattingMessage>,
) -> MetricService {
MetricService {
notifier,
monitor,
formatter,
}
}
impl MetricService {
/// Send a final notification with all system information
pub fn send_all_metrics_notification(&self) -> Result<(), Box<dyn std::error::Error>> {
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());
}
}

View File

@@ -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),

View File

@@ -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 {