switchgear_service/components/pool/
error.rs1use crate::api::service::{HasServiceErrorSource, ServiceErrorSource};
2use http;
3use std::borrow::Cow;
4use std::fmt::{Display, Formatter};
5use thiserror::Error;
6use tonic::{transport, Code, Status};
7
8#[derive(Error, Debug)]
9pub enum LnPoolErrorSourceKind {
10 #[error("CLN tonic gRPC error: {0}")]
11 ClnTonicError(Status),
12 #[error("LND tonic gRPC error: {0}")]
13 LndTonicError(Status),
14 #[error("CLN transport connection error: {0}")]
15 ClnTransportError(transport::Error),
16 #[error("LND transport connection error: {0}")]
17 LndTransportError(transport::Error),
18 #[error("invalid configuration for: {0}")]
19 InvalidConfiguration(String),
20 #[error("invalid credentials for {0}")]
21 InvalidCredentials(String),
22 #[error("invalid endpoint URI: {0}")]
23 InvalidEndpointUri(http::uri::InvalidUri),
24 #[error("memory error: {0}")]
25 MemoryError(String),
26}
27
28#[derive(Error, Debug)]
29pub struct LnPoolError {
30 context: Cow<'static, str>,
31 #[source]
32 source: LnPoolErrorSourceKind,
33 esource: ServiceErrorSource,
34}
35
36impl Display for LnPoolError {
37 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
38 write!(
39 f,
40 "LnPoolError: while {}: {}",
41 self.context.as_ref(),
42 self.source
43 )
44 }
45}
46
47impl LnPoolError {
48 fn new<C: Into<Cow<'static, str>>>(
49 source: LnPoolErrorSourceKind,
50 esource: ServiceErrorSource,
51 context: C,
52 ) -> Self {
53 Self {
54 context: context.into(),
55 source,
56 esource,
57 }
58 }
59
60 pub fn from_invalid_configuration<C: Into<Cow<'static, str>>>(
61 source: C,
62 esource: ServiceErrorSource,
63 context: C,
64 ) -> Self {
65 Self::new(
66 LnPoolErrorSourceKind::InvalidConfiguration(source.into().to_string()),
67 esource,
68 context.into(),
69 )
70 }
71
72 pub fn from_invalid_credentials<C: Into<Cow<'static, str>>>(
73 source: C,
74 esource: ServiceErrorSource,
75 context: C,
76 ) -> Self {
77 Self::new(
78 LnPoolErrorSourceKind::InvalidCredentials(source.into().to_string()),
79 esource,
80 context.into(),
81 )
82 }
83
84 pub fn from_cln_invalid_endpoint_uri<C: Into<Cow<'static, str>>>(
85 invalid_uri: http::uri::InvalidUri,
86 esource: ServiceErrorSource,
87 context: C,
88 ) -> Self {
89 Self::new(
90 LnPoolErrorSourceKind::InvalidEndpointUri(invalid_uri),
91 esource,
92 context.into(),
93 )
94 }
95
96 pub fn from_cln_tonic_error<C: Into<Cow<'static, str>>>(source: Status, context: C) -> Self {
97 let esource = Self::from_tonic_code(source.code());
98 Self::new(
99 LnPoolErrorSourceKind::ClnTonicError(source),
100 esource,
101 context,
102 )
103 }
104
105 pub fn from_cln_tonic_error_with_esource<C: Into<Cow<'static, str>>>(
106 source: Status,
107 esource: ServiceErrorSource,
108 context: C,
109 ) -> Self {
110 Self::new(
111 LnPoolErrorSourceKind::ClnTonicError(source),
112 esource,
113 context,
114 )
115 }
116
117 pub fn from_lnd_tonic_error<C: Into<Cow<'static, str>>>(source: Status, context: C) -> Self {
118 let esource = Self::from_tonic_code(source.code());
119 Self::new(
120 LnPoolErrorSourceKind::LndTonicError(source),
121 esource,
122 context,
123 )
124 }
125
126 pub fn from_lnd_tonic_error_with_esource<C: Into<Cow<'static, str>>>(
127 source: Status,
128 esource: ServiceErrorSource,
129 context: C,
130 ) -> Self {
131 Self::new(
132 LnPoolErrorSourceKind::LndTonicError(source),
133 esource,
134 context,
135 )
136 }
137
138 pub fn from_cln_transport_error<C: Into<Cow<'static, str>>>(
139 source: transport::Error,
140 esource: ServiceErrorSource,
141 context: C,
142 ) -> Self {
143 Self::new(
144 LnPoolErrorSourceKind::ClnTransportError(source),
145 esource,
146 context,
147 )
148 }
149
150 pub fn from_memory_error<C: Into<Cow<'static, str>>>(source: String, context: C) -> Self {
151 Self::new(
152 LnPoolErrorSourceKind::MemoryError(source),
153 ServiceErrorSource::Internal,
154 context,
155 )
156 }
157
158 pub fn context(&self) -> &str {
159 self.context.as_ref()
160 }
161
162 pub fn source(&self) -> &LnPoolErrorSourceKind {
163 &self.source
164 }
165
166 pub fn esource(&self) -> ServiceErrorSource {
167 self.esource
168 }
169
170 fn from_tonic_code(code: Code) -> ServiceErrorSource {
171 match code {
172 Code::InvalidArgument | Code::OutOfRange | Code::AlreadyExists => {
173 ServiceErrorSource::Downstream
174 }
175
176 _ => ServiceErrorSource::Upstream,
177 }
178 }
179}
180
181impl HasServiceErrorSource for LnPoolError {
182 fn get_service_error_source(&self) -> ServiceErrorSource {
183 self.esource
184 }
185}