ruststream 0.1.0

Async messaging framework for Rust: broker-agnostic traits, router, codecs, and a conformance harness for broker authors.
Documentation
//! Handler abstraction and the [`HandlerResult`] enum returned to the router.

use std::{future::Future, sync::Arc};

use crate::IncomingMessage;

/// What the router should do with the message after the handler returns.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum HandlerResult {
    /// Acknowledge the message; the broker will remove it from the queue.
    Ack,
    /// Negatively acknowledge the message; `requeue = true` asks the broker to redeliver.
    Nack {
        /// Whether the broker should redeliver the message.
        requeue: bool,
    },
}

impl HandlerResult {
    /// Convenience constructor for `Nack { requeue: true }`.
    #[must_use]
    pub const fn retry() -> Self {
        Self::Nack { requeue: true }
    }

    /// Convenience constructor for `Nack { requeue: false }`.
    #[must_use]
    pub const fn drop() -> Self {
        Self::Nack { requeue: false }
    }
}

/// Per-message handler invoked by the router on every delivery.
///
/// Implementations are `Send + Sync` so the router can share a single handler across many
/// concurrent deliveries.
///
/// # Examples
///
/// Closures implement `Handler` automatically:
///
/// ```
/// use ruststream::IncomingMessage;
/// use ruststream::runtime::{Handler, HandlerResult};
///
/// fn assert_handler<M, H>(_: H)
/// where
///     M: IncomingMessage,
///     H: Handler<M>,
/// {
/// }
///
/// fn use_closure<M: IncomingMessage + 'static>() {
///     assert_handler::<M, _>(|_msg: &M| async { HandlerResult::Ack });
/// }
/// ```
pub trait Handler<M>: Send + Sync
where
    M: IncomingMessage,
{
    /// Handle one delivery.
    fn handle(&self, msg: &M) -> impl Future<Output = HandlerResult> + Send;
}

impl<M, F, Fut> Handler<M> for F
where
    M: IncomingMessage,
    F: Fn(&M) -> Fut + Send + Sync,
    Fut: Future<Output = HandlerResult> + Send,
{
    fn handle(&self, msg: &M) -> impl Future<Output = HandlerResult> + Send {
        (self)(msg)
    }
}

impl<M, H> Handler<M> for Arc<H>
where
    M: IncomingMessage,
    H: Handler<M>,
{
    fn handle(&self, msg: &M) -> impl Future<Output = HandlerResult> + Send {
        (**self).handle(msg)
    }
}