tokio_task_scheduler/error.rs
1//! Error types for the scheduler library
2//!
3//! This module provides comprehensive error handling for the scheduler,
4//! including specific error types for different failure scenarios and
5//! recovery strategies.
6
7use thiserror::Error;
8use std::time::Duration;
9use chrono;
10
11/// Errors that can occur during scheduler operations
12///
13/// This enum represents all possible errors that can occur during
14/// task scheduling, execution, and persistence operations.
15#[derive(Error, Debug, Clone)]
16pub enum SchedulerError {
17 /// Error when a task's execution fails
18 #[error("Task execution failed: {0}")]
19 TaskExecutionFailed(String),
20
21 /// Error when attempting to operate on a non-existent task
22 #[error("Task with ID {0} not found")]
23 TaskNotFound(String),
24
25 /// Error when parsing an invalid time format
26 #[error("Invalid time format. Expected format: HH:MM or HH:MM:SS, got {0}")]
27 InvalidTimeFormat(String),
28
29 /// Error when attempting to create an invalid schedule
30 #[error("Invalid schedule: {0}")]
31 InvalidSchedule(String),
32
33 /// Error during I/O operations
34 #[error("IO error: {0}")]
35 IoError(String),
36
37 /// Error when attempting to create a duplicate task
38 #[error("Task already exists: {0}")]
39 TaskAlreadyExists(String),
40
41 /// Error when maximum retry attempts are exceeded
42 #[error("Max retries ({max_retries}) exceeded for task. Last error: {last_error}")]
43 MaxRetriesExceeded {
44 max_retries: u32,
45 last_error: String,
46 },
47
48 /// Error when unable to retrieve task status
49 #[error("Failed to retrieve task status")]
50 TaskStatusError,
51
52 /// Error when a scheduling conflict occurs
53 #[error("Scheduling conflict: Task cannot be scheduled at the specified time")]
54 SchedulingConflict,
55
56 /// Error during persistence operations
57 #[error("Persistence error: {0}")]
58 PersistenceError(String),
59}
60
61impl From<std::io::Error> for SchedulerError {
62 fn from(error: std::io::Error) -> Self {
63 SchedulerError::IoError(error.to_string())
64 }
65}
66
67impl SchedulerError {
68 /// Suggests a recovery strategy based on the error type
69 ///
70 /// # Returns
71 ///
72 /// * `Some(RecoveryStrategy)` - A suggested recovery strategy for the error
73 /// * `None` - If no recovery strategy is available for this error type
74 pub fn recovery_strategy(&self) -> Option<RecoveryStrategy> {
75 match self {
76 SchedulerError::TaskExecutionFailed(_) => Some(RecoveryStrategy::Retry),
77 SchedulerError::TaskNotFound(_) => Some(RecoveryStrategy::Skip),
78 SchedulerError::InvalidTimeFormat(_) => Some(RecoveryStrategy::Skip),
79 SchedulerError::MaxRetriesExceeded { .. } => Some(RecoveryStrategy::Abort),
80 SchedulerError::SchedulingConflict => Some(RecoveryStrategy::Pause),
81 _ => None
82 }
83 }
84}
85
86/// Suggested recovery strategies for different error types
87///
88/// These strategies provide guidance on how to handle specific error cases
89/// in an automated way.
90#[derive(Debug, Clone, Copy)]
91pub enum RecoveryStrategy {
92 /// Retry the failed operation
93 Retry,
94 /// Skip the failed operation and continue
95 Skip,
96 /// Abort the current operation
97 Abort,
98 /// Pause the scheduler
99 Pause,
100}
101
102/// Error context provides additional information about an error
103///
104/// This struct contains metadata about an error occurrence, including
105/// retry delays and context-specific information.
106#[derive(Debug, Clone)]
107pub struct ErrorContext {
108 pub error: SchedulerError,
109 pub timestamp: chrono::DateTime<chrono::Utc>,
110 pub retry_delay: Option<Duration>,
111}
112
113impl ErrorContext {
114 /// Creates a new error context
115 ///
116 /// # Arguments
117 ///
118 /// * `error` - The scheduler error to create context for
119 ///
120 /// # Returns
121 ///
122 /// A new ErrorContext instance
123 pub fn new(error: SchedulerError) -> Self {
124 Self {
125 error,
126 timestamp: chrono::Utc::now(),
127 retry_delay: None,
128 }
129 }
130
131 /// Sets a retry delay for the error
132 ///
133 /// # Arguments
134 ///
135 /// * `delay` - The duration to wait before retrying
136 ///
137 /// # Returns
138 ///
139 /// The updated ErrorContext instance
140 pub fn with_retry_delay(mut self, delay: Duration) -> Self {
141 self.retry_delay = Some(delay);
142 self
143 }
144}