Skip to main content

xet_runtime/
error.rs

1use thiserror::Error;
2
3#[derive(Debug, Error)]
4#[non_exhaustive]
5pub enum RuntimeError {
6    #[error("Error initializing runtime: {0:?}")]
7    RuntimeInit(std::io::Error),
8
9    #[error("Invalid runtime: {0}")]
10    InvalidRuntime(String),
11
12    #[error("A XetRuntime is already attached to this tokio runtime handle with Id {0}")]
13    ExternalAlreadyAttached(tokio::runtime::Id),
14
15    #[error("Task panic: {0:?}")]
16    TaskPanic(String),
17
18    #[error("Task cancelled; possible runtime shutdown in progress ({0}).")]
19    TaskCanceled(String),
20
21    #[error("Reqwest error: {0}")]
22    ReqwestError(#[from] reqwest::Error),
23
24    #[error("Lock poisoned: {0}")]
25    LockPoisoned(String),
26
27    #[error("Keyboard interrupt (SIGINT)")]
28    KeyboardInterrupt,
29
30    #[error("{0}")]
31    Other(String),
32}
33
34// PoisonError<T> is generic over the lock-guard type, so #[from] cannot be used directly.
35// This blanket impl gives the same `?`-propagation ergonomics for any poisoned std lock.
36impl<T> From<std::sync::PoisonError<T>> for RuntimeError {
37    fn from(e: std::sync::PoisonError<T>) -> Self {
38        RuntimeError::LockPoisoned(e.to_string())
39    }
40}
41
42impl From<tokio::task::JoinError> for RuntimeError {
43    fn from(err: tokio::task::JoinError) -> Self {
44        if err.is_panic() {
45            tracing::error!("Panic reported on xet worker task: {err:?}");
46            RuntimeError::TaskPanic(format!("{err:?}"))
47        } else if err.is_cancelled() {
48            RuntimeError::TaskCanceled(format!("{err}"))
49        } else {
50            RuntimeError::Other(format!("task join error: {err}"))
51        }
52    }
53}
54
55pub type Result<T> = std::result::Result<T, RuntimeError>;