pub struct ZmqRpc { /* private fields */ }Expand description
The DEALER/ROUTER request-reply pattern.
The endpoint may take either side, and the pattern answers the same on both: a copy of a request has no address of its own, so every responder registration names where its retry copies go.
§Examples
A queue worker that asks a model service for a score before it finishes each job:
use std::error::Error;
use std::time::Duration;
use ruststream::OutgoingMessage;
use ruststream::codec::{Codec, JsonCodec};
use ruststream_zeromq::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize)]
struct Job {
id: u64,
}
#[derive(Deserialize)]
struct Score {
value: f64,
}
#[subscriber("jobs")]
async fn rate(
job: &Job,
Out(model): Out<impl RequestReply>,
) -> Result<(), Box<dyn Error + Send + Sync>> {
let request = JsonCodec.encode(job)?;
let reply = model
.request(OutgoingMessage::new("score", request.as_ref()), Duration::from_secs(5))
.await?;
let score: Score = JsonCodec.decode(reply.payload())?;
tracing::info!(job.id, score = score.value, "scored");
Ok(())
}
#[ruststream::app]
fn app() -> impl App {
let model = ZmqRpc::new(ZmqEndpoint::connect("tcp://model:5557")).bindable();
let ask = model.bind(ZmqRpcPublish);
RustStream::new(AppInfo::new("scorer", "0.1.0"))
.with_broker(ZmqQueue::new(ZmqEndpoint::bind("tcp://0.0.0.0:5555")), |b| {
b.include(rate).out(DefaultSlot, ask).build();
})
.register_broker(model)
}Implementations§
Source§impl ZmqRpc
impl ZmqRpc
Sourcepub fn new<Role: EndpointRole>(endpoint: ZmqEndpoint<Role>) -> Self
pub fn new<Role: EndpointRole>(endpoint: ZmqEndpoint<Role>) -> Self
Records the endpoint, on either side. No I/O.
§Examples
A model service that answers each score request at the peer that sent it:
use ruststream_zeromq::rpc::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Deserialize)]
struct Features {
values: Vec<f64>,
}
#[derive(Serialize, Outgoing)]
struct Score {
value: f64,
}
#[subscriber("score", reply("reply"))]
async fn score(request: &Features) -> Score {
Score {
value: request.values.iter().sum(),
}
}
// Answers at the request's `reply-to` address; the `ZmqRpcPublisher` documentation shows it
// in full.
#[ruststream::app]
fn app() -> impl App {
RustStream::new(AppInfo::new("model", "0.1.0")).with_broker(
ZmqRpc::new(ZmqEndpoint::bind("tcp://0.0.0.0:5557")),
|b| {
b.include(score)
.out_reply(Publish)
.transform(ReplyToRequester)
.out_retry(Publish)
.to("score.retry");
},
)
}Sourcepub const fn read_ahead(self, read_ahead: NonZeroUsize) -> Self
pub const fn read_ahead(self, read_ahead: NonZeroUsize) -> Self
How many deliveries a subscription reads off its socket ahead of the handler; 1000 unless
set, the receive high-water mark ZeroMQ itself gives a socket.
Past this bound the subscription stops reading, the socket’s buffers fill, and the sender waits: a handler slower than the wire slows the sender down rather than growing this process’s memory.
§Examples
A responder whose answers take a database round trip holds 64 requests ahead, and the requesters wait beyond that:
use ruststream_zeromq::rpc::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Deserialize)]
struct Lookup {
customer: u64,
}
#[derive(Serialize, Outgoing)]
struct Customer {
name: String,
}
#[subscriber("customers", reply("reply"))]
async fn lookup(request: &Lookup) -> Customer {
Customer {
name: format!("customer {}", request.customer),
}
}
// Answers at the request's `reply-to` address; the `ZmqRpcPublisher` documentation shows it
// in full.
#[ruststream::app]
fn app() -> impl App {
let requests = ZmqRpc::new(ZmqEndpoint::bind("tcp://0.0.0.0:5557"))
.read_ahead(nonzero!(64_usize));
RustStream::new(AppInfo::new("customers", "0.1.0")).with_broker(requests, |b| {
b.include(lookup)
.out_reply(Publish)
.transform(ReplyToRequester)
.out_retry(Publish)
.to("customers.retry");
})
}Sourcepub fn publisher(&self) -> ZmqRpcPublisher
pub fn publisher(&self) -> ZmqRpcPublisher
A publisher sharing this pattern’s state; buildable before connect.
Trait Implementations§
Source§impl Broker for ZmqRpc
impl Broker for ZmqRpc
Source§impl DescribeServer for ZmqRpc
impl DescribeServer for ZmqRpc
Source§fn describe_server(&self) -> ServerSpec
fn describe_server(&self) -> ServerSpec
Auto Trait Implementations§
impl !RefUnwindSafe for ZmqRpc
impl !UnwindSafe for ZmqRpc
impl Freeze for ZmqRpc
impl Send for ZmqRpc
impl Sync for ZmqRpc
impl Unpin for ZmqRpc
impl UnsafeUnpin for ZmqRpc
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
Source§impl<B> BrokerRegistration for Bwhere
B: Broker + 'static,
impl<B> BrokerRegistration for Bwhere
B: Broker + 'static,
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
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