distributed 4.0.2

CQRS/ES framework for Rust using Plain Old Rust Structs — append-only events, replay, snapshots, outbox, service bus, and pluggable infrastructure
Documentation
//! The ergonomic bus surface: `send`/`listen` (point-to-point commands) and
//! `publish`/`subscribe` (fan-out events), mirroring the Node `servicebus`
//! family (`rabbitbus`/`kafkabus`/`knativebus`).
//!
//! The surface is split so producing (uniform across every transport) and
//! consuming (a `run_source` loop for pull transports, but generated manifests
//! for Knative) stay coherent:
//!
//! - [`Bus`] — produce: `send` a command, `publish` an event. Every transport.
//! - [`BusConsumer`] — consume: `listen` for commands (competing), `subscribe`
//!   to events (fan-out). Pull transports only (in-memory, NATS, RabbitMQ,
//!   Kafka, Postgres). Knative consumes via generated Triggers + the HTTP
//!   ingress, so it implements only [`Bus`].
//!
//! A concrete `*Bus` implements both, so `bus.send/listen/publish/subscribe` all
//! work on it. `send`/`publish` lower to the transport's [`MessagePublisher`];
//! `listen`/`subscribe` build the transport's [`MessageSource`] with the
//! right topology and run it through the shared [`run_source`](super::run_source).

use std::future::Future;
use std::sync::Arc;

use super::{Message, MessageKind, MessageRouter, RunOptions, TransportError};

/// Produce side of the bus — uniform across every transport.
pub trait Bus: Send + Sync {
    /// Send a point-to-point command (1:1, competing consumers).
    ///
    /// Provided: wraps the payload in a [`MessageKind::Command`] message and
    /// delegates to [`send_message`](Self::send_message).
    fn send(
        &self,
        name: &str,
        payload: Vec<u8>,
    ) -> impl Future<Output = Result<(), TransportError>> + Send {
        self.send_message(Message::new(name, MessageKind::Command, payload))
    }

    /// Publish a fan-out event (1:N).
    ///
    /// Provided: wraps the payload in a [`MessageKind::Event`] message and
    /// delegates to [`publish_message`](Self::publish_message).
    fn publish(
        &self,
        name: &str,
        payload: Vec<u8>,
    ) -> impl Future<Output = Result<(), TransportError>> + Send {
        self.publish_message(Message::new(name, MessageKind::Event, payload))
    }

    /// Send a fully-formed command message (explicit id/metadata/content-type).
    fn send_message(
        &self,
        message: Message,
    ) -> impl Future<Output = Result<(), TransportError>> + Send;

    /// Publish a fully-formed event message.
    fn publish_message(
        &self,
        message: Message,
    ) -> impl Future<Output = Result<(), TransportError>> + Send;
}

/// Consume side of the bus — pull transports that run a [`run_source`] loop.
///
/// `listen`/`subscribe` derive the message names from the router's registered
/// handlers ([`MessageRouter::subscription_plan`]) and use
/// [`MessageRouter::consumer_group`] as the default durable consumer identity
/// when the bus was not configured with an explicit group. They then build the
/// transport's source with the matching topology and run it. Both run until the
/// source drains/stops.
///
/// [`run_source`]: super::run_source
pub trait BusConsumer: Send + Sync {
    /// Run `router` as a command listener: consume its command names with
    /// competing-consumer (point-to-point) semantics.
    fn listen<R: MessageRouter>(
        &self,
        router: Arc<R>,
        options: RunOptions,
    ) -> impl Future<Output = Result<(), TransportError>> + Send;

    /// Run `router` as an event subscriber: consume its event names with
    /// fan-out semantics.
    fn subscribe<R: MessageRouter>(
        &self,
        router: Arc<R>,
        options: RunOptions,
    ) -> impl Future<Output = Result<(), TransportError>> + Send;
}