medi-rs 2.3.0

A lightweight async mediator library for Rust with dependency injection and derive macros
Documentation
#![cfg(feature = "tokio")]

use core::convert::Infallible;
use std::sync::Mutex;

use medi_rs::{DecoratorNext, MediCommand, medi_handler, medi_module, mediator};

static CALLS: Mutex<Vec<&str>> = Mutex::new(Vec::new());

async fn global_logging<Command, Next>(command: Command, next: Next) -> Result<Next::Response, Next::Error>
where
    Command: Send,
    Next: DecoratorNext<Command>,
{
    CALLS.lock().unwrap().push("global:before");
    let result = next.call(command).await;
    CALLS.lock().unwrap().push("global:after");
    result
}

async fn logging(
    command: DecoratedCommand,
    next: impl DecoratorNext<DecoratedCommand, Response = &'static str, Error = Infallible>,
) -> Result<&'static str, Infallible> {
    CALLS.lock().unwrap().push("logging:before");
    let result = next.call(command).await;
    CALLS.lock().unwrap().push("logging:after");
    result
}

async fn validation(
    command: DecoratedCommand,
    next: impl DecoratorNext<DecoratedCommand, Response = &'static str, Error = Infallible>,
) -> Result<&'static str, Infallible> {
    CALLS.lock().unwrap().push("validation:before");
    let result = next.call(command).await;
    CALLS.lock().unwrap().push("validation:after");
    result
}

#[derive(MediCommand)]
#[medi_command(return_type = &'static str)]
struct DecoratedCommand;

#[medi_handler(decorators = [logging, validation])]
async fn handle_decorated_command(_: DecoratedCommand) -> Result<&'static str, Infallible> {
    CALLS.lock().unwrap().push("handler");
    Ok("handled")
}

medi_module! {
    manifest decorated_manifest;
    commands { DecoratedCommand => handle_decorated_command; }
}

mediator! {
    struct DecoratedMediator {
        event_queue_capacity: 1;
        event_workers: 1;
        modules: [decorated_manifest];
        decorators: [global_logging];
    }
}

#[tokio::test]
async fn function_decorators_receive_and_forward_the_command() {
    CALLS.lock().unwrap().clear();

    assert_eq!(
        DecoratedMediator::new().send(DecoratedCommand).await.unwrap(),
        "handled"
    );
    assert_eq!(
        *CALLS.lock().unwrap(),
        [
            "global:before",
            "logging:before",
            "validation:before",
            "handler",
            "validation:after",
            "logging:after",
            "global:after"
        ]
    );
}