switchgear_components/pool/
error.rs

1use std::borrow::Cow;
2use std::fmt::{Display, Formatter};
3use switchgear_service_api::service::{HasServiceErrorSource, ServiceErrorSource};
4use thiserror::Error;
5use tonic::{transport, Code, Status};
6
7#[derive(Error, Debug)]
8pub enum LnPoolErrorSourceKind {
9    #[error("CLN tonic gRPC error: {0}")]
10    TonicError(Status),
11    #[error("CLN transport connection error: {0}")]
12    TransportError(transport::Error),
13    #[error("invalid configuration for: {0}")]
14    InvalidConfiguration(String),
15    #[error("invalid credentials for {0}")]
16    InvalidCredentials(String),
17    #[error("memory error: {0}")]
18    MemoryError(String),
19    #[error("json error: {0}")]
20    JsonError(serde_json::Error),
21}
22
23#[derive(Error, Debug)]
24pub struct LnPoolError {
25    context: Cow<'static, str>,
26    #[source]
27    source: LnPoolErrorSourceKind,
28    esource: ServiceErrorSource,
29}
30
31impl Display for LnPoolError {
32    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
33        write!(
34            f,
35            "LnPoolError: while {}: {}",
36            self.context.as_ref(),
37            self.source
38        )
39    }
40}
41
42impl LnPoolError {
43    fn new<C: Into<Cow<'static, str>>>(
44        source: LnPoolErrorSourceKind,
45        esource: ServiceErrorSource,
46        context: C,
47    ) -> Self {
48        Self {
49            context: context.into(),
50            source,
51            esource,
52        }
53    }
54
55    pub fn from_invalid_configuration<C: Into<Cow<'static, str>>>(
56        source: C,
57        esource: ServiceErrorSource,
58        context: C,
59    ) -> Self {
60        Self::new(
61            LnPoolErrorSourceKind::InvalidConfiguration(source.into().to_string()),
62            esource,
63            context.into(),
64        )
65    }
66
67    pub fn from_invalid_credentials<C: Into<Cow<'static, str>>>(
68        source: C,
69        esource: ServiceErrorSource,
70        context: C,
71    ) -> Self {
72        Self::new(
73            LnPoolErrorSourceKind::InvalidCredentials(source.into().to_string()),
74            esource,
75            context.into(),
76        )
77    }
78
79    pub fn from_tonic_error<C: Into<Cow<'static, str>>>(source: Status, context: C) -> Self {
80        let esource = Self::from_tonic_code(source.code());
81        Self::new(LnPoolErrorSourceKind::TonicError(source), esource, context)
82    }
83
84    pub fn from_transport_error<C: Into<Cow<'static, str>>>(
85        source: transport::Error,
86        esource: ServiceErrorSource,
87        context: C,
88    ) -> Self {
89        Self::new(
90            LnPoolErrorSourceKind::TransportError(source),
91            esource,
92            context,
93        )
94    }
95
96    pub fn from_memory_error<C: Into<Cow<'static, str>>>(source: String, context: C) -> Self {
97        Self::new(
98            LnPoolErrorSourceKind::MemoryError(source),
99            ServiceErrorSource::Internal,
100            context,
101        )
102    }
103
104    pub fn from_json_error<C: Into<Cow<'static, str>>>(
105        source: serde_json::Error,
106        context: C,
107    ) -> Self {
108        Self::new(
109            LnPoolErrorSourceKind::JsonError(source),
110            ServiceErrorSource::Internal,
111            context,
112        )
113    }
114
115    pub fn context(&self) -> &str {
116        self.context.as_ref()
117    }
118
119    pub fn source(&self) -> &LnPoolErrorSourceKind {
120        &self.source
121    }
122
123    pub fn esource(&self) -> ServiceErrorSource {
124        self.esource
125    }
126
127    fn from_tonic_code(code: Code) -> ServiceErrorSource {
128        match code {
129            Code::InvalidArgument | Code::OutOfRange | Code::AlreadyExists => {
130                ServiceErrorSource::Downstream
131            }
132
133            _ => ServiceErrorSource::Upstream,
134        }
135    }
136}
137
138impl HasServiceErrorSource for LnPoolError {
139    fn get_service_error_source(&self) -> ServiceErrorSource {
140        self.esource
141    }
142}