reliar_inbox/error.rs
1//! [`crate::InboxStore::process`]'s error.
2
3use core::fmt;
4
5use reliar_core::{Classify, FailureKind};
6
7/// Whose fault it was. Split so the caller can tell "my handler failed" (record it, `nak`) from
8/// "the inbox could not be read or written" (record nothing, `nak`).
9///
10/// ```
11/// use reliar_inbox::InboxProcessError;
12///
13/// #[derive(Debug)]
14/// struct StoreError;
15/// impl std::fmt::Display for StoreError {
16/// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17/// f.write_str("store unavailable")
18/// }
19/// }
20/// impl std::error::Error for StoreError {}
21///
22/// let err: InboxProcessError<StoreError, std::convert::Infallible> =
23/// InboxProcessError::Store(StoreError);
24/// assert_eq!(err.to_string(), "inbox store failed: store unavailable");
25/// ```
26#[derive(Debug)]
27#[non_exhaustive]
28pub enum InboxProcessError<S, H> {
29 /// [`crate::InboxStore::claim`] or [`crate::InboxStore::complete`] failed.
30 Store(S),
31
32 /// The [`crate::InboxHandler`] failed.
33 Handler(H),
34}
35
36impl<S, H> fmt::Display for InboxProcessError<S, H>
37where
38 S: std::error::Error,
39 H: std::error::Error,
40{
41 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42 match self {
43 Self::Store(err) => write!(f, "inbox store failed: {err}"),
44 Self::Handler(err) => write!(f, "inbox handler failed: {err}"),
45 }
46 }
47}
48
49impl<S, H> std::error::Error for InboxProcessError<S, H>
50where
51 S: std::error::Error + 'static,
52 H: std::error::Error + 'static,
53{
54 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
55 match self {
56 Self::Store(err) => Some(err),
57 Self::Handler(err) => Some(err),
58 }
59 }
60}
61
62/// Maps [`Self::Store`] to the store error's own [`FailureKind`] and [`Self::Handler`] to
63/// **[`FailureKind::Transient`]** — a handler failure is retried by the broker's redelivery, and
64/// the inbox has no authority to call a message permanently dead (ADR 0042 §4).
65///
66/// ```
67/// use reliar_core::{Classify, FailureKind};
68/// use reliar_inbox::InboxProcessError;
69///
70/// #[derive(Debug)]
71/// struct StoreError;
72/// impl Classify for StoreError {
73/// fn kind(&self) -> FailureKind {
74/// FailureKind::Permanent
75/// }
76/// }
77///
78/// #[derive(Debug)]
79/// struct HandlerError;
80///
81/// // A handler failure is always `Transient`, regardless of the store error's own kind.
82/// let err: InboxProcessError<StoreError, HandlerError> = InboxProcessError::Handler(HandlerError);
83/// assert_eq!(err.kind(), FailureKind::Transient);
84/// ```
85impl<S, H> Classify for InboxProcessError<S, H>
86where
87 S: Classify,
88{
89 fn kind(&self) -> FailureKind {
90 match self {
91 Self::Store(err) => err.kind(),
92 Self::Handler(_) => FailureKind::Transient,
93 }
94 }
95}