reliar-core 0.4.1

Pure envelope/message model shared by every Reliar crate — no storage or transport dependency.
Documentation
//! Failure classification shared by [`crate::Publisher`] and `OutboxStore` (`reliar-outbox`)
//! (ADR 0008, ADR 0032).

/// Implemented by every [`crate::Publisher::Error`] and `OutboxStore::Error`
/// (`reliar-outbox`) so a dispatcher can decide retry vs. dead without a downcast. Carried **by
/// the error type**, not by the publisher: the error value is what crosses a `JoinSet` boundary
/// into the dispatcher, so it must carry its own verdict (ADR 0008).
///
/// ```
/// use reliar_core::{Classify, FailureKind};
///
/// #[derive(Debug)]
/// enum MyPublishError {
///     Timeout,
///     PayloadTooLarge,
/// }
///
/// impl Classify for MyPublishError {
///     fn kind(&self) -> FailureKind {
///         match self {
///             Self::Timeout => FailureKind::Transient,
///             Self::PayloadTooLarge => FailureKind::Permanent,
///         }
///     }
/// }
///
/// assert_eq!(MyPublishError::Timeout.kind(), FailureKind::Transient);
/// ```
pub trait Classify {
    /// Whether the failure this error represents can succeed on retry.
    ///
    /// ```
    /// use reliar_core::{Classify, FailureKind};
    ///
    /// #[derive(Debug)]
    /// struct TimedOut;
    ///
    /// impl Classify for TimedOut {
    ///     fn kind(&self) -> FailureKind {
    ///         FailureKind::Transient
    ///     }
    /// }
    ///
    /// assert_eq!(TimedOut.kind(), FailureKind::Transient);
    /// ```
    fn kind(&self) -> FailureKind;
}

/// Whether a failure is worth retrying.
///
/// ```
/// use reliar_core::FailureKind;
///
/// assert_ne!(FailureKind::Transient, FailureKind::Permanent);
/// ```
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum FailureKind {
    /// May succeed if retried (a timeout, a connection blip, a lock conflict).
    Transient,

    /// No retry can fix it (an oversized payload, an unresolvable schema).
    Permanent,
}