pub struct PoolCensus {
pub workers_in_pool: usize,
pub workers_serving_activity: usize,
pub compatible_workers: usize,
pub eligible_compatible_workers: usize,
pub compatible_workers_reachability_lost: usize,
pub compatible_workers_at_capacity: usize,
pub compatible_workers_capacity_unannounced: usize,
pub last_compatible_poller_age: Option<Duration>,
}Expand description
What the connected-worker registry holds for one
(namespace, task_queue, activity_type[, node]) address.
Fields§
§workers_in_pool: usizeWorkers connected for (namespace, task_queue), whatever they serve.
workers_serving_activity: usizeOf those, workers advertising this activity type.
compatible_workers: usizeOf those, workers that also satisfy the dispatch’s node pin. Equal to
Self::workers_serving_activity for an unpinned dispatch.
Deliberately NOT filtered by dispatch eligibility, so
classify can tell an empty pool from an excluded one (#197 R3).
eligible_compatible_workers: usizeOf Self::compatible_workers, those a dispatch could actually be
handed to right now — the rest are excluded by the liveness verdict.
compatible_workers_reachability_lost: usizeOf the excluded compatible workers, those excluded by
DispatchExclusion::ReachabilityLost rather than by an opening
probation.
🔴 The whole point of the distinction. An opening probation clears itself in seconds, so parking silently through one is correct and announcing it would be noise on every healthy connect. A lost reachability does NOT clear on its own, so a dispatch parked on one waits indefinitely — and must say so, or it is a silent stall.
compatible_workers_at_capacity: usizeOf Self::compatible_workers, those already holding every dispatch
they advertised they would run at once.
🔴 A THIRD condition, and the reason classify needs a third answer.
An at-capacity pool is neither empty nor unreachable: its workers are
connected, serving this activity, and working. The remedy is the
OPPOSITE of the unreachable one — starting another worker helps here and
does not help there — so reporting either existing reason for it would
send an operator the wrong way.
compatible_workers_capacity_unannounced: usizeOf Self::compatible_workers, those that have registered but have not
yet announced how much work they can take.
🔴 DISJOINT from Self::compatible_workers_at_capacity, and counted
apart from it on purpose. Selection excludes both, by the same test —
unknown capacity is treated as full — so a census that folded them
together would be arithmetically fine and operationally a lie: it would
report a pool of idle, mute workers as a pool of busy ones, and attach
the advice for a busy pool (“start another worker”) to a condition
another worker of the same build cannot fix.
Only the liminal transport can produce it, and normally only for the one round trip between a worker’s registration and its capacity announcement.
last_compatible_poller_age: Option<Duration>How long ago a compatible worker was last in service, or None when
none has ever been seen for this address in this server’s life.
Zero while a compatible worker is connected right now.
Implementations§
Source§impl PoolCensus
impl PoolCensus
Sourcepub const fn is_served(&self) -> bool
pub const fn is_served(&self) -> bool
Whether the address currently has a compatible worker REGISTERED, whatever its dispatch eligibility.
A field-level fact, not a decision. It stays deliberately blind to
eligibility because classify needs the blind count to tell an empty
pool from an excluded one (#197 R3). Callers asking “will a dispatch
aimed here actually proceed?” want Self::will_be_served.
Sourcepub const fn will_be_served(&self) -> bool
pub const fn will_be_served(&self) -> bool
Whether a dispatch aimed here can be expected to proceed without an operator doing something first.
🔴 The distinction Self::is_served cannot draw. A pool whose workers
are all serving an opening probation is not dispatchable this instant
but will be within seconds, so it answers true — waiting is the
correct outcome and the caller should not be warned. A pool whose
workers have all LOST reachability answers false: nothing about it
improves on its own, so a caller told “served” would be told a run is
about to proceed when it is about to park indefinitely.
A pool whose workers are all AT CAPACITY answers true for the same
reason as the probation case: it is not dispatchable this instant and
needs nobody to do anything — a running activity finishes, a slot frees,
and the parked dispatch is selected. Waiting is the correct outcome.
A pool whose workers have NOT ANNOUNCED their capacity answers false,
and is the reason this is no longer two clauses. Nothing about that pool
improves on its own: the announcement either already arrived — in which
case these workers are not in this bucket — or it never will, because the
worker is a build that does not send one or its publish was lost. Saying
“will be served” of a fleet that is registered, idle, mute and
permanently unselectable is the most expensive kind of wrong answer,
because the whole point of this predicate is to tell a caller whether
waiting is enough.
Trait Implementations§
Source§impl Clone for PoolCensus
impl Clone for PoolCensus
Source§fn clone(&self) -> PoolCensus
fn clone(&self) -> PoolCensus
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreimpl Copy for PoolCensus
Source§impl Debug for PoolCensus
impl Debug for PoolCensus
Source§impl Default for PoolCensus
impl Default for PoolCensus
Source§fn default() -> PoolCensus
fn default() -> PoolCensus
impl Eq for PoolCensus
Source§impl PartialEq for PoolCensus
impl PartialEq for PoolCensus
impl StructuralPartialEq for PoolCensus
Auto Trait Implementations§
impl Freeze for PoolCensus
impl RefUnwindSafe for PoolCensus
impl Send for PoolCensus
impl Sync for PoolCensus
impl Unpin for PoolCensus
impl UnsafeUnpin for PoolCensus
impl UnwindSafe for PoolCensus
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§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
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> IntoMaybeUndefined<T> for T
impl<T> IntoMaybeUndefined<T> for T
Source§fn into_maybe_undefined(self) -> MaybeUndefined<T>
fn into_maybe_undefined(self) -> MaybeUndefined<T>
Source§impl<T> IntoOption<T> for T
impl<T> IntoOption<T> for T
Source§fn into_option(self) -> Option<T>
fn into_option(self) -> Option<T>
Source§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request