use std::future::Future;
use crate::IncomingMessage;
use super::handler::{Handler, HandlerResult};
pub trait Layer<H> {
type Handler;
fn layer(&self, inner: H) -> Self::Handler;
}
pub trait HandlerExt<M>: Handler<M> + Sized
where
M: IncomingMessage,
{
fn with<L>(self, layer: L) -> L::Handler
where
L: Layer<Self>,
{
layer.layer(self)
}
}
impl<M, H> HandlerExt<M> for H
where
M: IncomingMessage,
H: Handler<M>,
{
}
pub mod layers {
use tracing::{debug, info, instrument, warn};
use super::{Future, Handler, HandlerResult, IncomingMessage, Layer};
#[derive(Debug, Clone, Default)]
pub struct TracingLayer {
target: Option<&'static str>,
}
impl TracingLayer {
#[must_use]
pub const fn with_target(target: &'static str) -> Self {
Self {
target: Some(target),
}
}
}
impl<H> Layer<H> for TracingLayer {
type Handler = TracingHandler<H>;
fn layer(&self, inner: H) -> Self::Handler {
TracingHandler {
inner,
target: self.target,
}
}
}
#[derive(Debug, Clone)]
pub struct TracingHandler<H> {
inner: H,
target: Option<&'static str>,
}
impl<M, H> Handler<M> for TracingHandler<H>
where
M: IncomingMessage,
H: Handler<M>,
{
#[instrument(level = "trace", skip(self, msg), fields(target = self.target))]
fn handle(&self, msg: &M) -> impl Future<Output = HandlerResult> + Send {
async move {
debug!(target: "ruststream::dispatch", "delivery received");
let result = self.inner.handle(msg).await;
match result {
HandlerResult::Ack => {
info!(target: "ruststream::dispatch", "handler ack");
}
HandlerResult::Nack { requeue } => {
warn!(target: "ruststream::dispatch", requeue, "handler nack");
}
}
result
}
}
}
}