serf_core/
error.rs

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/// Error trait for [`Delegate`]
16#[derive(thiserror::Error)]
17pub enum SerfDelegateError<D: Delegate> {
18  /// Serf error
19  #[error(transparent)]
20  Serf(#[from] SerfError),
21  /// [`MergeDelegate`] error
22  #[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  /// Create a delegate error from a merge delegate error.
37  #[inline]
38  pub const fn merge(err: <D as MergeDelegate>::Error) -> Self {
39    Self::Merge(err)
40  }
41
42  /// Create a delegate error from a serf error.
43  #[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/// Error type for the serf crate.
63#[derive(thiserror::Error)]
64pub enum Error<T, D>
65where
66  D: Delegate<Id = T::Id, Address = T::ResolvedAddress>,
67  T: Transport,
68{
69  /// Returned when the underlyhing memberlist error
70  #[error(transparent)]
71  Memberlist(#[from] memberlist_core::error::Error<T, SerfDelegate<T, D>>),
72  /// Returned when the serf error
73  #[error(transparent)]
74  Serf(#[from] SerfError),
75  /// Returned when the relay error
76  #[error(transparent)]
77  Relay(#[from] RelayError<T, D>),
78  /// Multiple errors
79  #[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  /// Create a query response too large error
134  #[inline]
135  pub const fn query_response_too_large(limit: usize, got: usize) -> Self {
136    Self::Serf(SerfError::QueryResponseTooLarge { limit, got })
137  }
138
139  /// Create a query timeout error
140  #[inline]
141  pub const fn query_timeout() -> Self {
142    Self::Serf(SerfError::QueryTimeout)
143  }
144
145  /// Create a query already response error
146  #[inline]
147  pub const fn query_already_responsed() -> Self {
148    Self::Serf(SerfError::QueryAlreadyResponsed)
149  }
150
151  /// Create a query response delivery failed error
152  #[inline]
153  pub const fn query_response_delivery_failed() -> Self {
154    Self::Serf(SerfError::QueryResponseDeliveryFailed)
155  }
156
157  /// Create a relayed response too large error
158  #[inline]
159  pub const fn relayed_response_too_large(size: usize) -> Self {
160    Self::Serf(SerfError::RelayedResponseTooLarge(size))
161  }
162
163  /// Create a relay error
164  #[inline]
165  pub const fn relay(err: RelayError<T, D>) -> Self {
166    Self::Relay(err)
167  }
168
169  /// Create a fail truncate response error
170  #[inline]
171  pub const fn fail_truncate_response() -> Self {
172    Self::Serf(SerfError::FailTruncateResponse)
173  }
174
175  /// Create a tags too large error
176  #[inline]
177  pub const fn tags_too_large(size: usize) -> Self {
178    Self::Serf(SerfError::TagsTooLarge(size))
179  }
180
181  /// Create a query too large error
182  #[inline]
183  pub const fn query_too_large(size: usize) -> Self {
184    Self::Serf(SerfError::QueryTooLarge(size))
185  }
186
187  /// Create a user event limit too large error
188  #[inline]
189  pub const fn user_event_limit_too_large(size: usize) -> Self {
190    Self::Serf(SerfError::UserEventLimitTooLarge(size))
191  }
192
193  /// Create a user event limit too large error
194  #[inline]
195  pub const fn user_event_too_large(size: usize) -> Self {
196    Self::Serf(SerfError::UserEventTooLarge(size))
197  }
198
199  /// Create a raw user event too large error
200  #[inline]
201  pub const fn raw_user_event_too_large(size: usize) -> Self {
202    Self::Serf(SerfError::RawUserEventTooLarge(size))
203  }
204
205  /// Create a broadcast channel closed error
206  #[inline]
207  pub const fn broadcast_channel_closed() -> Self {
208    Self::Serf(SerfError::BroadcastChannelClosed)
209  }
210
211  /// Create a removal broadcast timeout error
212  #[inline]
213  pub const fn removal_broadcast_timeout() -> Self {
214    Self::Serf(SerfError::RemovalBroadcastTimeout)
215  }
216
217  /// Create a snapshot error
218  #[inline]
219  pub const fn snapshot(err: SnapshotError) -> Self {
220    Self::Serf(SerfError::Snapshot(err))
221  }
222
223  /// Create a bad leave status error
224  #[inline]
225  pub const fn bad_leave_status(status: SerfState) -> Self {
226    Self::Serf(SerfError::BadLeaveStatus(status))
227  }
228
229  /// Create a bad join status error
230  #[inline]
231  pub const fn bad_join_status(status: SerfState) -> Self {
232    Self::Serf(SerfError::BadJoinStatus(status))
233  }
234
235  /// Create a coordinates disabled error
236  #[inline]
237  pub const fn coordinates_disabled() -> Self {
238    Self::Serf(SerfError::CoordinatesDisabled)
239  }
240}
241
242/// [`Serf`](crate::Serf) error.
243#[derive(Debug, thiserror::Error)]
244pub enum SerfError {
245  /// Returned when the user event exceeds the configured limit.
246  #[error("user event exceeds configured limit of {0} bytes before encoding")]
247  UserEventLimitTooLarge(usize),
248  /// Returned when the user event exceeds the sane limit.
249  #[error("user event exceeds sane limit of {0} bytes before encoding")]
250  UserEventTooLarge(usize),
251  /// Returned when the join status is bad.
252  #[error("join called on {0} statues")]
253  BadJoinStatus(SerfState),
254  /// Returned when the leave status is bad.
255  #[error("leave called on {0} statues")]
256  BadLeaveStatus(SerfState),
257  /// Returned when the encoded user event exceeds the sane limit after encoding.
258  #[error("user event exceeds sane limit of {0} bytes after encoding")]
259  RawUserEventTooLarge(usize),
260  /// Returned when the query size exceeds the configured limit.
261  #[error("query exceeds limit of {0} bytes")]
262  QueryTooLarge(usize),
263  /// Returned when the query is timeout.
264  #[error("query response is past the deadline")]
265  QueryTimeout,
266  /// Returned when the query response is too large.
267  #[error("query response ({got} bytes) exceeds limit of {limit} bytes")]
268  QueryResponseTooLarge {
269    /// The query response size limit.
270    limit: usize,
271    /// The query response size.
272    got: usize,
273  },
274  /// Returned when the query has already been responded.
275  #[error("query response already sent")]
276  QueryAlreadyResponsed,
277  /// Returned when failed to truncate response so that it fits into message.
278  #[error("failed to truncate response so that it fits into message")]
279  FailTruncateResponse,
280  /// Returned when the tags too large.
281  #[error("encoded length of tags exceeds limit of {0} bytes")]
282  TagsTooLarge(usize),
283  /// Returned when the relayed response is too large.
284  #[error("relayed response exceeds limit of {0} bytes")]
285  RelayedResponseTooLarge(usize),
286  /// Returned when failed to deliver query response, dropping.
287  #[error("failed to deliver query response, dropping")]
288  QueryResponseDeliveryFailed,
289  /// Returned when the coordinates are disabled.
290  #[error("coordinates are disabled")]
291  CoordinatesDisabled,
292  /// Returned when snapshot error.
293  #[error(transparent)]
294  Snapshot(#[from] SnapshotError),
295  /// Returned when trying to decode a serf data
296  #[error(transparent)]
297  Decode(#[from] memberlist_core::proto::DecodeError),
298  /// Returned when trying to encode a serf data
299  #[error(transparent)]
300  Encode(#[from] memberlist_core::proto::EncodeError),
301  /// Returned when timed out broadcasting node removal.
302  #[error("timed out broadcasting node removal")]
303  RemovalBroadcastTimeout,
304  /// Returned when the timed out broadcasting channel closed.
305  #[error("timed out broadcasting channel closed")]
306  BroadcastChannelClosed,
307}
308
309/// Relay error from remote nodes.
310pub 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}