pub struct Router<W: Work, C: Clock = SystemClock, const CLASSES: usize = 2> { /* private fields */ }Implementations§
Source§impl<W, R, C, const CLASSES: usize> Router<Call<W, R>, C, CLASSES>
impl<W, R, C, const CLASSES: usize> Router<Call<W, R>, C, CLASSES>
Sourcepub async fn call(&self, work: W) -> Result<R, CallError<W>>
pub async fn call(&self, work: W) -> Result<R, CallError<W>>
Submit and await the response, waiting on backpressure if the target shard’s mailbox is full.
Sourcepub fn try_call(&self, work: W) -> Result<Answer<R>, SubmitError<W>>
pub fn try_call(&self, work: W) -> Result<Answer<R>, SubmitError<W>>
Submit without waiting, reporting a full mailbox immediately and returning the response as a separate future.
Rejection is synchronous and the answer is not, which is exactly the shape a load-shedding caller needs: it can give up before committing to an await.
Source§impl<W: Work, C: Clock, const CLASSES: usize> Router<W, C, CLASSES>
impl<W: Work, C: Clock, const CLASSES: usize> Router<W, C, CLASSES>
pub fn new(shards: Vec<Mailbox<Envelope<W>>>, clock: C) -> Self
Sourcepub fn with_options(
shards: Vec<Mailbox<Envelope<W>>>,
clock: C,
stamp_arrival: bool,
) -> Self
pub fn with_options( shards: Vec<Mailbox<Envelope<W>>>, clock: C, stamp_arrival: bool, ) -> Self
stamp_arrival records a submission timestamp on every item, which
powers queue-wait metrics and deadlines. Turning it off saves a clock
read per submission: worth roughly a few percent of a core at millions
of items per second: at the cost of both features.
pub fn shards(&self) -> usize
Sourcepub fn shard_index(&self, key: W::Key) -> usize
pub fn shard_index(&self, key: W::Key) -> usize
Which shard owns key. Stable for the lifetime of the router.
Sourcepub async fn submit(&self, work: W) -> Result<(), SubmitError<W>>
pub async fn submit(&self, work: W) -> Result<(), SubmitError<W>>
Submit, waiting if the target shard’s mailbox is full.
That wait is the system’s backpressure: when a shard is saturated it stops admitting, its mailbox fills, and this call suspends the caller rather than growing an unbounded queue.
Sourcepub fn try_submit(&self, work: W) -> Result<(), SubmitError<W>>
pub fn try_submit(&self, work: W) -> Result<(), SubmitError<W>>
Submit without ever waiting, reporting a full mailbox instead.
Use this when shedding load is better than queueing it, which is often true under a latency objective.
Sourcepub async fn submit_batch<I>(&self, work: I) -> Result<(), BatchError<W>>where
I: IntoIterator<Item = W>,
pub async fn submit_batch<I>(&self, work: I) -> Result<(), BatchError<W>>where
I: IntoIterator<Item = W>,
Submit many items, waiting on backpressure, and report everything that did not land.
Every item is attempted. One shard being unreachable does not stop items bound for the others, so a batch spanning shards is not held hostage by the worst of them.
The whole batch shares one arrival stamp. That is not an approximation: the caller held these items at one instant and handed them over at one instant, so that instant is when they arrived. Queue-wait is measured from it, and a deadline runs from it: including across a wait for mailbox space, because that wait is queueing, which is exactly what a deadline is meant to account for.
§Errors
BatchError carries every rejected item back with its reason, so a
caller can answer, retry or shed each one. Items not named there were
accepted.
Sourcepub fn try_submit_batch<I>(&self, work: I) -> Result<(), BatchError<W>>where
I: IntoIterator<Item = W>,
pub fn try_submit_batch<I>(&self, work: I) -> Result<(), BatchError<W>>where
I: IntoIterator<Item = W>,
Submit many items without ever waiting, reporting everything that did not land.
The shedding counterpart of submit_batch, and the one to reach for
under a latency objective: a full mailbox rejects that item and the
batch carries on rather than blocking behind it.