pub struct Workers { /* private fields */ }Expand description
Concurrency policy for one subscriber’s dispatch loop, declared with the workers(..) or
threads(..) macro argument (or Workers::sequential by default).
workers(n):nlong-lived workers, tasks of the runtime the app runs on, process up tondeliveries of the subscriber concurrently; a free worker takes the next one. Back-pressure holds: the stream is not polled whilendeliveries are in flight. Global processing order is lost by design.workers(n, by_key): the samenworkers as sequential lanes; a delivery goes to the lane picked by hashing itspartition_key, so per-key ordering is preserved. Messages without a key rotate over the lanes.threads(n):ndedicated threads of the subscription’s own, each with a current-thread runtime, for a handler that computes. The subscription’s loop stays on the app’s runtime and spreads deliveries over the threads round-robin; decoding, the handler and settling run on the thread a delivery was handed to, and only there. The app’s runtime stays free for I/O, timers and the other subscriptions.threads(n, by_key): the same threads as sequential lanes by partition key.
The workers or threads and the queues that feed them are made when the subscription starts: handing a delivery to one allocates nothing.
The default is sequential dispatch (workers(1)).
Implementations§
Source§impl Workers
impl Workers
Sourcepub const fn sequential() -> Workers
pub const fn sequential() -> Workers
Sequential dispatch: one delivery at a time, in stream order. The default.
Sourcepub const fn pool(count: NonZero<usize>) -> Workers
pub const fn pool(count: NonZero<usize>) -> Workers
A pool of up to count concurrent deliveries. One behaves like sequential dispatch.
Sourcepub const fn keyed(count: NonZero<usize>) -> Workers
pub const fn keyed(count: NonZero<usize>) -> Workers
count sequential lanes keyed by the message
partition_key: per-key ordering is preserved.
One lane behaves like sequential dispatch.
Sourcepub const fn threads(count: NonZero<usize>) -> Workers
pub const fn threads(count: NonZero<usize>) -> Workers
count dedicated threads for a CPU-bound handler: the subscription’s deliveries are
handled on threads of its own, each running a current-thread runtime, so the handler’s
computation holds up none of the app runtime’s threads. The router-chain spelling of
threads(n).
§Examples
use ruststream::memory::prelude::*;
use serde::Deserialize;
#[derive(Deserialize)]
struct Image {
id: u64,
}
#[subscriber("images.resize")]
async fn resize(image: &Image) -> HandlerOutcome {
tracing::info!(image.id, "resized");
HandlerOutcome::ack()
}
fn images() -> Router<MemoryBroker, impl RouterDef<MemoryBroker>> {
// Resizing computes, so it runs on eight threads of its own.
Router::new()
.include(resize)
.workers(Workers::threads(nonzero!(8)))
}
fn app() -> RustStream {
RustStream::new(AppInfo::new("images", "0.1.0")).with_broker(MemoryBroker::new(), |b| {
b.include_router(images());
})
}Sourcepub const fn threads_keyed(count: NonZero<usize>) -> Workers
pub const fn threads_keyed(count: NonZero<usize>) -> Workers
count dedicated threads as sequential lanes keyed by the message
partition_key: a key always lands on the same
thread, so per-key ordering is preserved. The router-chain spelling of
threads(n, by_key).
§Examples
use ruststream::memory::prelude::*;
use serde::Deserialize;
#[derive(Deserialize)]
struct Image {
id: u64,
}
#[subscriber("images.resize")]
async fn resize(image: &Image) -> HandlerOutcome {
tracing::info!(image.id, "resized");
HandlerOutcome::ack()
}
fn images() -> Router<MemoryBroker, impl RouterDef<MemoryBroker>> {
// One tenant's images stay in order: a key always lands on the same thread.
Router::new()
.include(resize)
.workers(Workers::threads_keyed(nonzero!(4)))
}
fn app() -> RustStream {
RustStream::new(AppInfo::new("images", "0.1.0")).with_broker(MemoryBroker::new(), |b| {
b.include_router(images());
})
}Trait Implementations§
impl Copy for Workers
impl Eq for Workers
impl StructuralPartialEq for Workers
Auto Trait Implementations§
impl Freeze for Workers
impl RefUnwindSafe for Workers
impl Send for Workers
impl Sync for Workers
impl Unpin for Workers
impl UnsafeUnpin for Workers
impl UnwindSafe for Workers
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> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.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