pub struct Out<P, M = DefaultSlot, Body = ()>(/* private fields */);Expand description
The marker a handler signature uses to receive an injected publisher:
Out(out): Out<impl Publisher> binds out to a live publisher inside the body.
The publisher type is not named in the signature: the handler states the broker capability it
needs (impl Publisher, impl TransactionalPublisher, impl OwnedTransactions,
impl RequestReply, or a broker-defined trait) and the concrete type is inferred from the
policy attached at the include site (b.include(f).out(marker, policy)), so the same handler mounts
on a production broker and on its in-process test transport unchanged. A handler taking
several publishers names a slot marker per parameter (Out<impl Publisher, MySlot>, see
OutSlot) and the include site binds each with .out(marker, policy),
in any order.
An optional third position declares the message set the handler publishes, which the publish
builder (message, destinations from each type’s
#[derive(Outgoing)] declaration) is checked against:
Out<impl Publisher>/Out<impl Publisher, Events>/Out<impl Publisher, Events, ()>- unrestricted: any declared message the handler names;
Out<impl Publisher, Events, ChunkDone>- one declared type (a#[derive(Outgoing)]type declares itself);Out<impl Publisher, Events, (ChunkDone, Progress)>- a list of declared types;Out<impl Publisher, Events, SendSet>- a#[derive(OutMessages)]enum whose variants’ models are the declared set.
The value the body receives is the arena entry for the parameter’s marker
(Slot), paired by the runtime at startup, so it is live by construction;
handlers never see a “not connected” state. The type itself is pure signature vocabulary:
the #[subscriber] expansion reads the declaration and binds the entry, and no value of
this type is ever constructed.
§Examples
use ruststream::runtime::{HandlerOutcome, Out};
use ruststream::{Outgoing, Publisher, subscriber};
#[derive(Outgoing, serde::Serialize)]
#[outgoing(name = "out")]
struct Forwarded {
id: u64,
}
#[subscriber("ingress")]
async fn forward(event: &Event, Out(out): Out<impl Publisher>) -> HandlerOutcome {
if out.message(&Forwarded { id: event.id }).publish().await.is_err() {
return HandlerOutcome::retry();
}
HandlerOutcome::ack()
}A handler with two publishers names a slot marker for each, and the mount site binds both:
use ruststream::memory::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize, Outgoing)]
#[outgoing(name = "orders.confirmed")]
struct Confirmed {
id: u64,
}
#[derive(Serialize, Outgoing)]
struct Audit {
id: u64,
}
#[derive(OutSlot)]
#[publishes(Confirmed)]
struct Orders;
#[derive(OutSlot)]
#[publishes(Audit)]
struct Trail;
#[subscriber("orders.incoming")]
async fn route(
event: &Confirmed,
Out(orders): Out<impl Publisher, Orders>,
Out(trail): Out<impl Publisher, Trail>,
) -> HandlerOutcome {
// `Confirmed` fixes its destination; `Audit` leaves it to the call.
if orders.message(event).publish().await.is_err()
|| trail
.message(&Audit { id: event.id })
.to("audit")
.publish()
.await
.is_err()
{
return HandlerOutcome::retry();
}
HandlerOutcome::ack()
}
fn app() -> RustStream {
RustStream::new(AppInfo::new("orders", "0.1.0")).with_broker(MemoryBroker::new(), |b| {
b.include(route)
.out(Orders, Publish)
.out(Trail, Publish)
.build();
})
}Trait Implementations§
Auto Trait Implementations§
impl<P, M, Body> Freeze for Out<P, M, Body>
impl<P, M, Body> RefUnwindSafe for Out<P, M, Body>
impl<P, M, Body> Send for Out<P, M, Body>
impl<P, M, Body> Sync for Out<P, M, Body>
impl<P, M, Body> Unpin for Out<P, M, Body>
impl<P, M, Body> UnsafeUnpin for Out<P, M, Body>
impl<P, M, Body> UnwindSafe for Out<P, M, Body>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more