跳到主要内容
本页尚未翻译

下面显示的是英文原文。

Slots

An Out slot hands a handler a live publisher as a parameter: one marker per slot, bound to a publish policy at the mount site.

A slot is for a destination chosen at run time, or for several destinations at once, another broker's included. Out(out): Out<impl Publisher> names a capability, never a broker's publisher type, so the same handler mounts on a production broker and on its in-process test transport. The capability is Publisher, or a narrower one: TransactionalPublisher, OwnedTransactions or RequestReply. A single unnamed slot is DefaultSlot. A handler with several slots names a marker per parameter: a unit struct that derives OutSlot. Its #[publishes(..)] list is what may leave through the slot, and what the generated AsyncAPI document reports for it. An optional third position, Out<impl Publisher, Marker, (A, B)>, narrows what this handler publishes through the slot.

The mount site binds each marker with .out(marker, policy), in any order, and commits the chain with .build(). A transform written after an .out(..) belongs to that slot. A slot that is never bound, a marker the handler does not declare, and a publish of a type outside the list do not compile. A body publishes through the slot with the publish builder. A slot may also take a reply: one handler returns its answer and publishes through slots beside it. The runtime's own retry copies leave through one more slot, Retry.

Example​

One unnamed slot.

/// One unnamed slot: the publisher arrives live, and `Event` leaves the destination to the call.
#[subscriber("ingress")]
async fn forward(event: &Event, Out(out): Out<impl Publisher>) -> HandlerOutcome {
if out.message(event).to("egress").publish().await.is_err() {
return HandlerOutcome::retry();
}
HandlerOutcome::ack()
}

Two named slots, each with what it may publish.

#[derive(Debug, PartialEq, Deserialize, Serialize, Outgoing)]
#[outgoing(name = "orders.confirmed")]
struct Confirmed {
id: u64,
}

#[derive(Debug, PartialEq, Deserialize, Serialize, Outgoing)]
struct Audit {
id: u64,
}

/// A slot marker lists what may leave through the slot.
#[derive(OutSlot)]
#[publishes(Confirmed)]
struct Orders;

#[derive(OutSlot)]
#[publishes(Audit)]
struct Trail;

#[subscriber("orders.incoming")]
async fn confirm(
event: &Event,
Out(orders): Out<impl Publisher, Orders>,
Out(trail): Out<impl Publisher, Trail>,
) -> HandlerOutcome {
if orders
.message(&Confirmed { id: event.id })
.publish()
.await
.is_err()
|| trail
.message(&Audit { id: event.id })
.to("audit")
.publish()
.await
.is_err()
{
return HandlerOutcome::retry();
}
HandlerOutcome::ack()
}
fn app() -> impl App {
RustStream::new(AppInfo::new("orders", "0.1.0")).with_broker(MemoryBroker::new(), |b| {
b.include(forward).out(DefaultSlot, Publish).build();
// Each marker binds its own policy, in any order.
b.include(confirm)
.out(Orders, Publish)
.out(Trail, Publish)
.build();
})
}