pub struct ZmqQueue<Role = Bind> { /* private fields */ }Expand description
The PUSH/PULL queue: each message reaches one of the competing consumers.
Role is the side of the endpoint this process takes, fixed by the endpoint’s constructor:
Bind for ZmqEndpoint::bind, Connect for ZmqEndpoint::connect. It decides where a
retry copy goes. A subscription that binds takes a copy published to its own listener, so a
mount site names no destination; one that dials reads from a PUSH peer that takes nothing, so
a mount site names where its copies go.
§Examples
A worker that binds its queue retries on it. The copy goes back into the queue, whichever worker is free takes it, and the framework’s retry-count header caps the deliveries at five:
use std::time::Duration;
use ruststream_zeromq::queue::prelude::*;
use serde::Deserialize;
#[derive(Deserialize)]
struct Job {
id: u64,
}
#[subscriber("jobs")]
async fn handle(job: &Job) -> HandlerOutcome {
if job.id == 0 {
return HandlerOutcome::retry_after(Duration::from_secs(30));
}
HandlerOutcome::ack()
}
#[ruststream::app]
fn app() -> impl App {
RustStream::new(AppInfo::new("worker", "0.1.0")).with_broker(
ZmqQueue::new(ZmqEndpoint::bind("tcp://0.0.0.0:5555")),
|b| {
b.include(handle)
.max_attempts(nonzero!(5u32))
.out_retry(Publish);
},
)
}One of several workers that dial the same ventilator and compete for its jobs. The ventilator takes nothing back, so the retry copies go to a queue the worker binds itself, where the same handler takes them. The copies carry the framework’s counter, so the cap holds across both subscriptions:
use std::time::Duration;
use ruststream_zeromq::queue::prelude::*;
use serde::Deserialize;
#[derive(Deserialize)]
struct Job {
id: u64,
}
#[subscriber("jobs")]
async fn work(job: &Job) -> HandlerOutcome {
if job.id == 0 {
return HandlerOutcome::retry_after(Duration::from_secs(30));
}
HandlerOutcome::ack()
}
#[ruststream::app]
fn app() -> impl App {
let retries = ZmqQueue::new(ZmqEndpoint::bind("tcp://0.0.0.0:5560")).bindable();
let copies = retries.bind(Publish);
RustStream::new(AppInfo::new("worker", "0.1.0"))
.with_broker(ZmqQueue::new(ZmqEndpoint::connect("tcp://ventilator:5555")), |b| {
b.include(work)
.max_attempts(nonzero!(5u32))
.out_retry(copies)
.to("jobs");
})
.with_broker(retries, |b| {
b.include(work).max_attempts(nonzero!(5u32));
})
}Implementations§
Source§impl<Role: EndpointRole> ZmqQueue<Role>
impl<Role: EndpointRole> ZmqQueue<Role>
Sourcepub fn new(endpoint: ZmqEndpoint<Role>) -> Self
pub fn new(endpoint: ZmqEndpoint<Role>) -> Self
Records the endpoint. No I/O.
§Examples
A worker that listens for the jobs its producers push:
use ruststream_zeromq::queue::prelude::*;
use serde::Deserialize;
#[derive(Deserialize)]
struct Job {
id: u64,
}
#[subscriber("jobs")]
async fn work(job: &Job) -> HandlerOutcome {
tracing::info!(job.id, "working on the job");
HandlerOutcome::ack()
}
#[ruststream::app]
fn app() -> impl App {
RustStream::new(AppInfo::new("worker", "0.1.0")).with_broker(
ZmqQueue::new(ZmqEndpoint::bind("tcp://0.0.0.0:5555")),
|b| {
b.include(work);
},
)
}Source§impl<Role> ZmqQueue<Role>
impl<Role> ZmqQueue<Role>
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 worker whose renders take seconds holds 64 jobs ahead, and the producers wait beyond that:
use ruststream_zeromq::queue::prelude::*;
use serde::Deserialize;
#[derive(Deserialize)]
struct Render {
scene: String,
}
#[subscriber("renders")]
async fn render(job: &Render) -> HandlerOutcome {
tracing::info!(scene = %job.scene, "rendering");
HandlerOutcome::ack()
}
#[ruststream::app]
fn app() -> impl App {
let renders = ZmqQueue::new(ZmqEndpoint::bind("tcp://0.0.0.0:5555"))
.read_ahead(nonzero!(64_usize));
RustStream::new(AppInfo::new("renderer", "0.1.0")).with_broker(renders, |b| {
b.include(render);
})
}Sourcepub fn publisher(&self) -> ZmqQueuePublisher
pub fn publisher(&self) -> ZmqQueuePublisher
A publisher sharing this queue’s state; buildable before connect.
Trait Implementations§
Source§impl<Role: EndpointRole> Broker for ZmqQueue<Role>
impl<Role: EndpointRole> Broker for ZmqQueue<Role>
Source§impl<Role: EndpointRole> DescribeServer for ZmqQueue<Role>
impl<Role: EndpointRole> DescribeServer for ZmqQueue<Role>
Source§fn describe_server(&self) -> ServerSpec
fn describe_server(&self) -> ServerSpec
Auto Trait Implementations§
impl<Role = Bind> !RefUnwindSafe for ZmqQueue<Role>
impl<Role = Bind> !UnwindSafe for ZmqQueue<Role>
impl<Role> Freeze for ZmqQueue<Role>
impl<Role> Send for ZmqQueue<Role>
impl<Role> Sync for ZmqQueue<Role>
impl<Role> Unpin for ZmqQueue<Role>
impl<Role> UnsafeUnpin for ZmqQueue<Role>
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