use super::executor::ExecutionResult;
use super::store::CronStore;
use super::types::{CronTask, TaskStatus};
use anyhow::Result;
use std::sync::Arc;
pub struct TaskMonitor {
store: Arc<CronStore>,
}
impl TaskMonitor {
pub fn new(store: Arc<CronStore>) -> Self {
Self { store }
}
pub fn record_execution(&self, task: &mut CronTask, result: &ExecutionResult) -> Result<()> {
let now = std::time::SystemTime::now()
.duration_since(std::time::SystemTime::UNIX_EPOCH)?
.as_secs();
task.last_run = Some(now);
if result.success {
task.status = TaskStatus::Completed;
task.retry_count = 0;
task.last_error = None;
tracing::info!(
"Task '{}' completed in {}ms: {}",
task.id,
result.duration_ms,
result.output
);
} else {
task.retry_count += 1;
task.last_error = result.error.clone();
if task.retry_count >= task.max_retries {
task.status = TaskStatus::Failed;
tracing::error!(
"Task '{}' failed after {} retries: {}",
task.id,
task.retry_count,
result.error.as_deref().unwrap_or("unknown")
);
} else {
task.status = TaskStatus::Pending;
tracing::warn!(
"Task '{}' failed (attempt {}/{}): {}",
task.id,
task.retry_count,
task.max_retries,
result.error.as_deref().unwrap_or("unknown")
);
}
}
self.store.save(task)?;
Ok(())
}
pub fn get_failed_tasks(&self) -> Result<Vec<CronTask>> {
let tasks = self.store.list_all()?;
Ok(tasks
.into_iter()
.filter(|t| t.status == TaskStatus::Failed)
.collect())
}
pub fn reset_task(&self, task_id: &str) -> Result<bool> {
if let Some(mut task) = self.store.load(task_id)? {
task.status = TaskStatus::Pending;
task.retry_count = 0;
task.last_error = None;
self.store.save(&task)?;
Ok(true)
} else {
Ok(false)
}
}
}