Skip to main content

moirai_core/
error.rs

1//! Error types and handling for the Moirai runtime.
2
3use core::fmt;
4
5/// Errors that can occur during task operations.
6#[allow(clippy::module_name_repetitions)]
7#[must_use]
8#[derive(Debug, Clone, PartialEq, Eq)]
9pub enum TaskError {
10    /// Task was cancelled before completion
11    Cancelled,
12    /// Task panicked during execution
13    Panicked,
14    /// Task exceeded its execution time limit
15    Timeout,
16    /// Task failed due to resource exhaustion
17    ResourceExhausted,
18    /// Task failed due to an invalid operation
19    InvalidOperation,
20    /// Generic task execution error
21    ExecutionFailed(TaskErrorKind),
22    /// Task execution timed out waiting for completion
23    ExecutionTimeout,
24    /// Task result was not found in storage
25    ResultNotFound,
26    /// Task failed to spawn
27    SpawnFailed,
28    /// Task is not in a valid state for the operation
29    InvalidState,
30    /// Task has already completed
31    AlreadyCompleted,
32}
33
34/// Specific kinds of task execution errors.
35#[must_use]
36#[derive(Debug, Clone, PartialEq, Eq)]
37pub enum TaskErrorKind {
38    /// I/O operation failed
39    Io,
40    /// Network operation failed
41    Network,
42    /// File system operation failed
43    FileSystem,
44    /// Permission denied
45    PermissionDenied,
46    /// Resource not found
47    NotFound,
48    /// Operation would block
49    WouldBlock,
50    /// Operation interrupted
51    Interrupted,
52    /// Invalid input provided
53    InvalidInput,
54    /// Other error
55    Other,
56}
57
58impl fmt::Display for TaskError {
59    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60        match self {
61            Self::Cancelled => write!(f, "Task was cancelled"),
62            Self::Panicked => write!(f, "Task panicked during execution"),
63            Self::ExecutionTimeout => write!(f, "Task execution timed out"),
64            Self::ResultNotFound => write!(f, "Task result not found"),
65            Self::SpawnFailed => write!(f, "Task failed to spawn"),
66            Self::Timeout => write!(f, "Task exceeded execution time limit"),
67            Self::ResourceExhausted => write!(f, "Task failed due to resource exhaustion"),
68            Self::InvalidOperation => write!(f, "Invalid operation"),
69            Self::ExecutionFailed(kind) => write!(f, "Task execution failed: {kind}"),
70            Self::InvalidState => write!(f, "Task is not in a valid state for the operation"),
71            Self::AlreadyCompleted => write!(f, "Task has already completed"),
72        }
73    }
74}
75
76impl fmt::Display for TaskErrorKind {
77    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78        match self {
79            Self::Io => write!(f, "I/O error"),
80            Self::Network => write!(f, "Network error"),
81            Self::FileSystem => write!(f, "File system error"),
82            Self::PermissionDenied => write!(f, "Permission denied"),
83            Self::NotFound => write!(f, "Resource not found"),
84            Self::WouldBlock => write!(f, "Operation would block"),
85            Self::Interrupted => write!(f, "Operation interrupted"),
86            Self::InvalidInput => write!(f, "Invalid input"),
87            Self::Other => write!(f, "Other error"),
88        }
89    }
90}
91
92/// Errors that can occur during executor operations.
93#[allow(clippy::module_name_repetitions)]
94#[must_use]
95#[derive(Debug, Clone, PartialEq, Eq)]
96pub enum ExecutorError {
97    /// Executor is shutting down
98    ShuttingDown,
99    /// Executor is already running
100    AlreadyRunning,
101    /// Executor configuration is invalid
102    InvalidConfiguration,
103    /// Thread pool creation failed
104    ThreadPoolCreationFailed,
105    /// Task spawn failed
106    SpawnFailed(TaskError),
107    /// Resource exhaustion detected
108    ResourceExhausted(String),
109    /// Performance anomaly detected
110    PerformanceAnomaly(String),
111    /// No scheduler available
112    NoSchedulerAvailable,
113    /// Scheduler error
114    SchedulerError(SchedulerError),
115}
116
117impl fmt::Display for ExecutorError {
118    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
119        match self {
120            Self::ShuttingDown => write!(f, "Executor is shutting down"),
121            Self::AlreadyRunning => write!(f, "Executor is already running"),
122            Self::InvalidConfiguration => write!(f, "Invalid executor configuration"),
123            Self::ThreadPoolCreationFailed => write!(f, "Failed to create thread pool"),
124            Self::SpawnFailed(err) => write!(f, "Failed to spawn task: {err}"),
125            Self::ResourceExhausted(msg) => write!(f, "Resource exhausted: {msg}"),
126            Self::PerformanceAnomaly(msg) => write!(f, "Performance anomaly: {msg}"),
127            Self::NoSchedulerAvailable => write!(f, "No scheduler available"),
128            Self::SchedulerError(err) => write!(f, "Scheduler error: {err}"),
129        }
130    }
131}
132
133/// Errors that can occur during scheduler operations.
134#[allow(clippy::module_name_repetitions)]
135#[must_use]
136#[derive(Debug, Clone, PartialEq, Eq)]
137pub enum SchedulerError {
138    /// Queue is full and cannot accept more tasks
139    QueueFull,
140    /// Queue is empty
141    QueueEmpty,
142    /// Work stealing failed
143    StealFailed,
144    /// Invalid scheduler state
145    InvalidState,
146    /// System failure occurred
147    SystemFailure(String),
148    /// Invalid scheduler reference
149    InvalidScheduler,
150}
151
152impl fmt::Display for SchedulerError {
153    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
154        match self {
155            Self::QueueFull => write!(f, "Task queue is full"),
156            Self::QueueEmpty => write!(f, "Task queue is empty"),
157            Self::StealFailed => write!(f, "Work stealing failed"),
158            Self::InvalidState => write!(f, "Invalid scheduler state"),
159            Self::SystemFailure(msg) => write!(f, "System failure: {msg}"),
160            Self::InvalidScheduler => write!(f, "Invalid scheduler reference"),
161        }
162    }
163}
164
165/// A result type for task operations.
166pub type TaskResult<T> = Result<T, TaskError>;
167
168/// A result type for executor operations.
169pub type ExecutorResult<T> = Result<T, ExecutorError>;
170
171/// A result type for scheduler operations.
172pub type SchedulerResult<T> = Result<T, SchedulerError>;
173
174#[cfg(feature = "std")]
175impl std::error::Error for TaskError {}
176
177#[cfg(feature = "std")]
178impl std::error::Error for ExecutorError {}
179
180#[cfg(feature = "std")]
181impl std::error::Error for SchedulerError {}
182
183#[cfg(test)]
184mod tests {
185    use super::*;
186
187    #[test]
188    fn test_error_display() {
189        assert_eq!(format!("{}", TaskError::Cancelled), "Task was cancelled");
190        assert_eq!(
191            format!("{}", TaskError::ExecutionFailed(TaskErrorKind::Io)),
192            "Task execution failed: I/O error"
193        );
194        assert_eq!(
195            format!("{}", ExecutorError::ShuttingDown),
196            "Executor is shutting down"
197        );
198        assert_eq!(
199            format!("{}", SchedulerError::QueueFull),
200            "Task queue is full"
201        );
202    }
203}