mago_database/
error.rs

1use globset::Error as GlobSetError;
2
3/// The primary error type for all database loading and mutation operations.
4///
5/// This enum consolidates errors from various sources, including file I/O,
6/// pattern matching, and concurrent access issues, into a single, unified type.
7#[derive(Debug)]
8pub enum DatabaseError {
9    /// An attempt was made to access a file that does not exist in the database.
10    FileNotFound,
11    /// An error occurred during a filesystem read or write operation.
12    IOError(std::io::Error),
13    /// The set of user-provided glob patterns could not be compiled into a `GlobSet`.
14    InvalidGlobSet(GlobSetError),
15    /// An attempt was made to commit or consume a `ChangeLog` while other
16    /// references to it still exist, indicating that other threads may not have
17    /// finished their work.
18    ChangeLogInUse,
19    /// The lock on a `ChangeLog` was "poisoned."
20    ///
21    /// This happens when a thread panics while holding the lock, leaving the
22    /// data in an unrecoverable and potentially inconsistent state.
23    PoisonedLogMutex,
24}
25
26impl std::fmt::Display for DatabaseError {
27    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28        match self {
29            Self::FileNotFound => write!(f, "file not found in database"),
30            Self::IOError(err) => write!(f, "I/O error: {err}"),
31            Self::InvalidGlobSet(err) => write!(f, "failed to build exclusion filter from patterns: {err}"),
32            Self::ChangeLogInUse => {
33                write!(f, "cannot commit changelog because it is still in use by another thread")
34            }
35            Self::PoisonedLogMutex => {
36                write!(f, "changelog is in an unrecoverable state because a thread panicked while modifying it")
37            }
38        }
39    }
40}
41
42impl std::error::Error for DatabaseError {
43    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
44        match self {
45            Self::IOError(err) => Some(err),
46            Self::InvalidGlobSet(err) => Some(err),
47            _ => None,
48        }
49    }
50}
51
52impl From<std::io::Error> for DatabaseError {
53    fn from(error: std::io::Error) -> Self {
54        Self::IOError(error)
55    }
56}
57
58impl From<GlobSetError> for DatabaseError {
59    fn from(error: GlobSetError) -> Self {
60        Self::InvalidGlobSet(error)
61    }
62}