Skip to main content

relay_knowledge/storage/contracts/
boundary.rs

1use std::{error::Error, fmt, future::Future, pin::Pin};
2
3pub type StorageFuture<'a, T> = Pin<Box<dyn Future<Output = Result<T, StorageError>> + Send + 'a>>;
4
5/// Storage boundary failure.
6#[derive(Debug)]
7pub enum StorageError {
8    Io(std::io::Error),
9    Sqlite(rusqlite::Error),
10    Join(tokio::task::JoinError),
11    LockPoisoned,
12    Busy(String),
13    InvalidInput(String),
14}
15
16impl fmt::Display for StorageError {
17    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
18        match self {
19            Self::Io(error) => write!(formatter, "storage I/O failed: {error}"),
20            Self::Sqlite(error) => write!(formatter, "sqlite operation failed: {error}"),
21            Self::Join(error) => write!(formatter, "storage worker failed: {error}"),
22            Self::LockPoisoned => write!(formatter, "sqlite connection lock was poisoned"),
23            Self::Busy(message) => write!(formatter, "storage busy: {message}"),
24            Self::InvalidInput(message) => write!(formatter, "invalid storage input: {message}"),
25        }
26    }
27}
28
29impl Error for StorageError {}
30
31impl From<std::io::Error> for StorageError {
32    fn from(error: std::io::Error) -> Self {
33        Self::Io(error)
34    }
35}
36
37impl From<rusqlite::Error> for StorageError {
38    fn from(error: rusqlite::Error) -> Self {
39        Self::Sqlite(error)
40    }
41}
42
43impl From<tokio::task::JoinError> for StorageError {
44    fn from(error: tokio::task::JoinError) -> Self {
45        Self::Join(error)
46    }
47}
48
49#[cfg(test)]
50#[path = "boundary_tests.rs"]
51mod tests;