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

下面显示的是英文原文。

Publishing

Each pattern's Publish sends the three frames and nothing else; a send waits up to five seconds for a peer.

Each pattern ships one publish policy: ZmqQueuePublish, ZmqFanoutPublish and ZmqRpcPublish. The pattern's prelude offers it as Publish, and the crate prelude offers all three under their own names. A mount site names it wherever a registration publishes: .out_reply(Publish) for a reply, .out(Slot, Publish).build() for a slot, .out_retry(Publish) for retry copies. The policy holds no connection. At startup the runtime pairs it with the connected broker into a live publisher, such as ZmqQueuePublisher. To publish through another broker of the service, the mount site binds the policy to it with bindable() and .bind(Publish). Pipelines with PUSH/PULL publishes a worker's results to a sink this way.

A publish sends the message as the three frames: its name, its headers and the payload the codec wrote. The payload frame is the buffer the codec wrote, so a payload of any size is sent without a copy. A ZMTP send takes the frames and nothing else, so every publisher declares Options = (), and the publish builder carries the core's steps alone. A handler body therefore imports ruststream::prelude::* alone and bounds its publisher with the capability it needs.

A publisher on the bind side attaches its socket when the service starts, so a peer that dials it connects before the first message. A publisher that dials attaches on its first publish and waits for a peer. When no peer has completed the handshake within five seconds, the publish fails with ZmqError::Send, "no connected peer". The window is a constant of the crate.

Who receives the message is the pattern's rule. On ZmqQueue one peer takes it, in turn. On ZmqFanout every subscriber whose filter is a prefix of the name takes a copy, and a message no subscriber matches is dropped without an error. On ZmqRpc the publisher sends replies only, and a request goes through request. A publish is one send of one message, and a queue publish is safe to cancel, as Cancellation describes.

Example​

A worker announces each shipped order on a fan-out it binds itself. A peer that subscribes to orders.shipped, or to the prefix orders, receives every announcement.

/// The slot shipments leave through, and what it may publish.
#[derive(OutSlot)]
#[publishes(Shipped)]
struct Events;

#[subscriber("orders")]
async fn ship(order: &Order, Out(events): Out<impl Publisher, Events>) -> HandlerOutcome {
tracing::info!(order.id, "shipping");
// A send waits up to five seconds for a subscriber to attach, then fails.
if let Err(err) = events.message(&Shipped { id: order.id }).publish().await {
tracing::warn!(subscription = "orders", order.id, error = %err, "shipment not announced");
return HandlerOutcome::retry();
}
HandlerOutcome::ack()
}
#[ruststream::app]
fn app() -> impl App {
// No subscription of this service reads the fan-out, so its publisher binds the endpoint.
let events = ZmqFanout::new(ZmqEndpoint::bind("tcp://0.0.0.0:5556")).bindable();
let announce = events.bind(ZmqFanoutPublish);
RustStream::new(AppInfo::new("shipping", "0.1.0"))
.with_broker(
ZmqQueue::new(ZmqEndpoint::bind("tcp://0.0.0.0:5555")),
|b| {
b.include(ship).out(Events, announce).build();
},
)
.register_broker(events)
}