use std::{future::Future, sync::Arc};
use super::context::Context;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum HandlerResult {
Ack,
Nack {
requeue: bool,
},
}
impl HandlerResult {
#[must_use]
pub const fn retry() -> Self {
Self::Nack { requeue: true }
}
#[must_use]
pub const fn drop() -> Self {
Self::Nack { requeue: false }
}
}
pub trait IntoHandlerResult {
fn into_handler_result(self) -> HandlerResult;
}
impl IntoHandlerResult for HandlerResult {
fn into_handler_result(self) -> HandlerResult {
self
}
}
impl IntoHandlerResult for () {
fn into_handler_result(self) -> HandlerResult {
HandlerResult::Ack
}
}
impl<E> IntoHandlerResult for Result<(), E> {
fn into_handler_result(self) -> HandlerResult {
match self {
Ok(()) => HandlerResult::Ack,
Err(_) => HandlerResult::drop(),
}
}
}
impl<E> IntoHandlerResult for Result<HandlerResult, E> {
fn into_handler_result(self) -> HandlerResult {
self.unwrap_or_else(|_| HandlerResult::drop())
}
}
pub trait Handler<M>: Send + Sync {
fn handle(&self, msg: &M, ctx: &mut Context) -> impl Future<Output = HandlerResult> + Send;
}
impl<M, F, Fut> Handler<M> for F
where
F: Fn(&M, &mut Context) -> Fut + Send + Sync,
Fut: Future<Output = HandlerResult> + Send,
{
fn handle(&self, msg: &M, ctx: &mut Context) -> impl Future<Output = HandlerResult> + Send {
(self)(msg, ctx)
}
}
impl<M, H> Handler<M> for Arc<H>
where
H: Handler<M>,
{
fn handle(&self, msg: &M, ctx: &mut Context) -> impl Future<Output = HandlerResult> + Send {
(**self).handle(msg, ctx)
}
}