1use std::sync::Arc;
2
3use memberlist_core::{
4 delegate::DelegateError as MemberlistDelegateError, proto::TinyVec, transport::Transport,
5};
6
7use crate::{
8 delegate::{Delegate, MergeDelegate},
9 serf::{SerfDelegate, SerfState},
10 types::Member,
11};
12
13pub use crate::snapshot::SnapshotError;
14
15#[derive(thiserror::Error)]
17pub enum SerfDelegateError<D: Delegate> {
18 #[error(transparent)]
20 Serf(#[from] SerfError),
21 #[error(transparent)]
23 Merge(<D as MergeDelegate>::Error),
24}
25
26impl<D: Delegate> core::fmt::Debug for SerfDelegateError<D> {
27 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28 match self {
29 Self::Merge(err) => write!(f, "{err:?}"),
30 Self::Serf(err) => write!(f, "{err:?}"),
31 }
32 }
33}
34
35impl<D: Delegate> SerfDelegateError<D> {
36 #[inline]
38 pub const fn merge(err: <D as MergeDelegate>::Error) -> Self {
39 Self::Merge(err)
40 }
41
42 #[inline]
44 pub const fn serf(err: crate::error::SerfError) -> Self {
45 Self::Serf(err)
46 }
47}
48
49impl<T, D> From<MemberlistDelegateError<SerfDelegate<T, D>>> for SerfDelegateError<D>
50where
51 D: Delegate<Id = T::Id, Address = T::ResolvedAddress>,
52 T: Transport,
53{
54 fn from(value: MemberlistDelegateError<SerfDelegate<T, D>>) -> Self {
55 match value {
56 MemberlistDelegateError::AliveDelegate(e) => e,
57 MemberlistDelegateError::MergeDelegate(e) => e,
58 }
59 }
60}
61
62#[derive(thiserror::Error)]
64pub enum Error<T, D>
65where
66 D: Delegate<Id = T::Id, Address = T::ResolvedAddress>,
67 T: Transport,
68{
69 #[error(transparent)]
71 Memberlist(#[from] memberlist_core::error::Error<T, SerfDelegate<T, D>>),
72 #[error(transparent)]
74 Serf(#[from] SerfError),
75 #[error(transparent)]
77 Relay(#[from] RelayError<T, D>),
78 #[error("errors:\n{}", format_multiple_errors(.0))]
80 Multiple(Arc<[Self]>),
81}
82
83impl<T, D> core::fmt::Debug for Error<T, D>
84where
85 D: Delegate<Id = T::Id, Address = T::ResolvedAddress>,
86 T: Transport,
87{
88 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
89 match self {
90 Self::Memberlist(e) => write!(f, "{e:?}"),
91 Self::Serf(e) => write!(f, "{e:?}"),
92 Self::Relay(e) => write!(f, "{e:?}"),
93 Self::Multiple(e) => write!(f, "{e:?}"),
94 }
95 }
96}
97
98impl<T, D> From<SnapshotError> for Error<T, D>
99where
100 D: Delegate<Id = T::Id, Address = T::ResolvedAddress>,
101 T: Transport,
102{
103 fn from(value: SnapshotError) -> Self {
104 Self::Serf(SerfError::Snapshot(value))
105 }
106}
107
108impl<T, D> From<memberlist_core::proto::EncodeError> for Error<T, D>
109where
110 D: Delegate<Id = T::Id, Address = T::ResolvedAddress>,
111 T: Transport,
112{
113 fn from(e: memberlist_core::proto::EncodeError) -> Self {
114 Self::Serf(e.into())
115 }
116}
117
118impl<T, D> From<memberlist_core::proto::DecodeError> for Error<T, D>
119where
120 D: Delegate<Id = T::Id, Address = T::ResolvedAddress>,
121 T: Transport,
122{
123 fn from(e: memberlist_core::proto::DecodeError) -> Self {
124 Self::Serf(e.into())
125 }
126}
127
128impl<T, D> Error<T, D>
129where
130 D: Delegate<Id = T::Id, Address = T::ResolvedAddress>,
131 T: Transport,
132{
133 #[inline]
135 pub const fn query_response_too_large(limit: usize, got: usize) -> Self {
136 Self::Serf(SerfError::QueryResponseTooLarge { limit, got })
137 }
138
139 #[inline]
141 pub const fn query_timeout() -> Self {
142 Self::Serf(SerfError::QueryTimeout)
143 }
144
145 #[inline]
147 pub const fn query_already_responsed() -> Self {
148 Self::Serf(SerfError::QueryAlreadyResponsed)
149 }
150
151 #[inline]
153 pub const fn query_response_delivery_failed() -> Self {
154 Self::Serf(SerfError::QueryResponseDeliveryFailed)
155 }
156
157 #[inline]
159 pub const fn relayed_response_too_large(size: usize) -> Self {
160 Self::Serf(SerfError::RelayedResponseTooLarge(size))
161 }
162
163 #[inline]
165 pub const fn relay(err: RelayError<T, D>) -> Self {
166 Self::Relay(err)
167 }
168
169 #[inline]
171 pub const fn fail_truncate_response() -> Self {
172 Self::Serf(SerfError::FailTruncateResponse)
173 }
174
175 #[inline]
177 pub const fn tags_too_large(size: usize) -> Self {
178 Self::Serf(SerfError::TagsTooLarge(size))
179 }
180
181 #[inline]
183 pub const fn query_too_large(size: usize) -> Self {
184 Self::Serf(SerfError::QueryTooLarge(size))
185 }
186
187 #[inline]
189 pub const fn user_event_limit_too_large(size: usize) -> Self {
190 Self::Serf(SerfError::UserEventLimitTooLarge(size))
191 }
192
193 #[inline]
195 pub const fn user_event_too_large(size: usize) -> Self {
196 Self::Serf(SerfError::UserEventTooLarge(size))
197 }
198
199 #[inline]
201 pub const fn raw_user_event_too_large(size: usize) -> Self {
202 Self::Serf(SerfError::RawUserEventTooLarge(size))
203 }
204
205 #[inline]
207 pub const fn broadcast_channel_closed() -> Self {
208 Self::Serf(SerfError::BroadcastChannelClosed)
209 }
210
211 #[inline]
213 pub const fn removal_broadcast_timeout() -> Self {
214 Self::Serf(SerfError::RemovalBroadcastTimeout)
215 }
216
217 #[inline]
219 pub const fn snapshot(err: SnapshotError) -> Self {
220 Self::Serf(SerfError::Snapshot(err))
221 }
222
223 #[inline]
225 pub const fn bad_leave_status(status: SerfState) -> Self {
226 Self::Serf(SerfError::BadLeaveStatus(status))
227 }
228
229 #[inline]
231 pub const fn bad_join_status(status: SerfState) -> Self {
232 Self::Serf(SerfError::BadJoinStatus(status))
233 }
234
235 #[inline]
237 pub const fn coordinates_disabled() -> Self {
238 Self::Serf(SerfError::CoordinatesDisabled)
239 }
240}
241
242#[derive(Debug, thiserror::Error)]
244pub enum SerfError {
245 #[error("user event exceeds configured limit of {0} bytes before encoding")]
247 UserEventLimitTooLarge(usize),
248 #[error("user event exceeds sane limit of {0} bytes before encoding")]
250 UserEventTooLarge(usize),
251 #[error("join called on {0} statues")]
253 BadJoinStatus(SerfState),
254 #[error("leave called on {0} statues")]
256 BadLeaveStatus(SerfState),
257 #[error("user event exceeds sane limit of {0} bytes after encoding")]
259 RawUserEventTooLarge(usize),
260 #[error("query exceeds limit of {0} bytes")]
262 QueryTooLarge(usize),
263 #[error("query response is past the deadline")]
265 QueryTimeout,
266 #[error("query response ({got} bytes) exceeds limit of {limit} bytes")]
268 QueryResponseTooLarge {
269 limit: usize,
271 got: usize,
273 },
274 #[error("query response already sent")]
276 QueryAlreadyResponsed,
277 #[error("failed to truncate response so that it fits into message")]
279 FailTruncateResponse,
280 #[error("encoded length of tags exceeds limit of {0} bytes")]
282 TagsTooLarge(usize),
283 #[error("relayed response exceeds limit of {0} bytes")]
285 RelayedResponseTooLarge(usize),
286 #[error("failed to deliver query response, dropping")]
288 QueryResponseDeliveryFailed,
289 #[error("coordinates are disabled")]
291 CoordinatesDisabled,
292 #[error(transparent)]
294 Snapshot(#[from] SnapshotError),
295 #[error(transparent)]
297 Decode(#[from] memberlist_core::proto::DecodeError),
298 #[error(transparent)]
300 Encode(#[from] memberlist_core::proto::EncodeError),
301 #[error("timed out broadcasting node removal")]
303 RemovalBroadcastTimeout,
304 #[error("timed out broadcasting channel closed")]
306 BroadcastChannelClosed,
307}
308
309pub struct RelayError<T, D>(
311 #[allow(clippy::type_complexity)]
312 TinyVec<(
313 Member<T::Id, T::ResolvedAddress>,
314 memberlist_core::error::Error<T, SerfDelegate<T, D>>,
315 )>,
316)
317where
318 D: Delegate<Id = T::Id, Address = T::ResolvedAddress>,
319 T: Transport;
320
321impl<T, D>
322 From<
323 TinyVec<(
324 Member<T::Id, T::ResolvedAddress>,
325 memberlist_core::error::Error<T, SerfDelegate<T, D>>,
326 )>,
327 > for RelayError<T, D>
328where
329 D: Delegate<Id = T::Id, Address = T::ResolvedAddress>,
330 T: Transport,
331{
332 fn from(
333 value: TinyVec<(
334 Member<T::Id, T::ResolvedAddress>,
335 memberlist_core::error::Error<T, SerfDelegate<T, D>>,
336 )>,
337 ) -> Self {
338 Self(value)
339 }
340}
341
342impl<T, D> core::fmt::Display for RelayError<T, D>
343where
344 D: Delegate<Id = T::Id, Address = T::ResolvedAddress>,
345 T: Transport,
346{
347 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
348 writeln!(f, "relay errors:")?;
349
350 for (member, err) in self.0.iter() {
351 writeln!(
352 f,
353 "\tfailed to send relay response to {}: {}",
354 member.node().id(),
355 err
356 )?;
357 }
358 Ok(())
359 }
360}
361
362impl<T, D> core::fmt::Debug for RelayError<T, D>
363where
364 D: Delegate<Id = T::Id, Address = T::ResolvedAddress>,
365 T: Transport,
366{
367 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
368 core::fmt::Display::fmt(self, f)
369 }
370}
371
372impl<T, D> std::error::Error for RelayError<T, D>
373where
374 D: Delegate<Id = T::Id, Address = T::ResolvedAddress>,
375 T: Transport,
376{
377}
378
379fn format_multiple_errors<T, D>(errors: &[Error<T, D>]) -> String
380where
381 D: Delegate<Id = T::Id, Address = T::ResolvedAddress>,
382 T: Transport,
383{
384 errors
385 .iter()
386 .enumerate()
387 .map(|(i, err)| format!(" {}. {}", i + 1, err))
388 .collect::<Vec<_>>()
389 .join("\n")
390}