noema-actix-webapi 0.1.0

Actix-web backend runtime on Noema (modules, sqlx, UoW, swagger, WebSocket dispatch)
use std::sync::Arc;

use noema::core::{Container, Injectable};
use noema::events::{BackgroundErrorHandler, BackgroundSpawner, BoxDynError, DispatchContext};

/// Spawns handler futures on the Actix / tokio runtime.
#[derive(Clone, Copy, Default)]
pub struct ActixSpawner;

impl BackgroundSpawner for ActixSpawner {
    fn spawn(
        &self,
        fut: std::pin::Pin<Box<dyn std::future::Future<Output = ()> + Send + 'static>>,
    ) {
        let _ = actix_web::rt::spawn(fut);
    }
}

impl Injectable<Container> for ActixSpawner {
    fn inject(_: &Container) -> Self {
        ActixSpawner
    }
}

/// Logs dispatch / listener errors with `tracing`.
#[derive(Clone, Copy, Default)]
pub struct ActixErrorHandler;

#[async_trait::async_trait]
impl BackgroundErrorHandler for ActixErrorHandler {
    async fn handle(&self, error: BoxDynError, event_name: &str, handler_name: String) {
        tracing::error!(event_name, handler_name, error = %error, "event dispatch error");
    }
}

impl Injectable<Container> for ActixErrorHandler {
    fn inject(_: &Container) -> Self {
        ActixErrorHandler
    }
}

/// `DispatchContext` with Actix spawner/error handler and [`noema::events::InvokeMode::Await`].
pub fn dispatch_context() -> DispatchContext {
    DispatchContext::new(Arc::new(ActixSpawner), Arc::new(ActixErrorHandler))
        .with_invoke_mode(noema::events::InvokeMode::Await)
}

/// Same as [`dispatch_context`] but `Spawn` (background handlers).
pub fn dispatch_context_spawn() -> DispatchContext {
    DispatchContext::new(Arc::new(ActixSpawner), Arc::new(ActixErrorHandler))
}