switchgear_components/pool/
error.rs1use 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}