Skip to main content

Random

Struct Random 

Source
pub struct Random { /* private fields */ }
Expand description

Uniform (optionally weight-biased) random backend selection.

The RNG is seeded once, at construction, and never from an ambient source on the selection hot path — but, unlike Rendezvous/Maglev, it is NOT seeded from the shared DEFAULT_HASH_SEED constant. Rendezvous/Maglev feed their seed into a pure, stateless hash function (hash_backend): same (seed, key, addr) in, same score out, independent of call history, so sharing the seed fleet-wide is exactly the point — it is what makes the same affinity key land on the same backend across workers and restarts. Random feeds its seed into a stateful, advancing StdRng, where the n-th pick depends on the whole call history. Seeding that from a shared compile-time constant would make every worker, on every cold start, with an identically-ordered backend list, draw from a bit-for-bit identical keystream — so every fresh worker’s first pick over N equal-weight backends would be the same backend index, fleet-wide, on every restart: exactly the correlated-load event uniform selection exists to prevent, arriving at the worst possible moment (a synchronised redeploy, when every worker’s call counter resets together and initial load is otherwise indistinguishable). So the seed is the caller’s, and the production caller draws it from an OS-seeded generator: BackendMap::new seeds its own generator from the OS once, at construction, and hands every cluster’s policy a seed drawn from it (crate::backends::BackendMap, #1684). Each worker’s keystream is therefore independent, as with the thread-local rng() this replaced, while a simulator that builds the map with BackendMap::with_seed gets a fixed, reproducible sequence (mirrors quinn-proto’s rng_seed construction shape).

This does NOT make Random return a fixed backend: next_available_backend advances the internal RNG on every call, so a sequence of calls still draws a well-distributed spread of backends. “Random” here means “statistically spread, and — given with_seed — reproducible for a fixed seed and exact call sequence” — not “constant”. Two instances built with with_seed on the same seed and driven through the same sequence of backend sets reproduce the same sequence of picks (what makes this testable); a single instance called repeatedly keeps drawing fresh values from its advancing RNG state, exactly like a real RNG would; two lists of one map, or two maps, draw from independent keystreams.

Implementations§

Source§

impl Random

Source

pub fn with_seed(seed: u64) -> Self

A policy whose draws are the keystream of seed. Never DEFAULT_HASH_SEED in production — see the struct docs for why a shared compile-time constant would correlate every worker’s picks.

Trait Implementations§

Source§

impl Debug for Random

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl LoadBalancingAlgorithm for Random

Source§

fn next_available_backend( &mut self, _key: Option<u64>, backends: Candidates<'_>, ) -> Option<Rc<RefCell<Backend>>>

Select the next backend among candidates. Read more
Source§

fn rebuild(&mut self, _backends: &[Rc<RefCell<Backend>>])

Called by the control plane when the live backend set for a cluster changes, so table-based policies (Maglev) can recompute their lookup table off the datapath. The default is a no-op; Maglev rebuilds its table, and RoundRobin (with the round-robin fallback of Rendezvous and Maglev) resets its running weights.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<'a, T, E> AsTaggedExplicit<'a, E> for T
where T: 'a,

Source§

fn explicit(self, class: Class, tag: u32) -> TaggedParser<'a, Explicit, Self, E>

Source§

impl<'a, T, E> AsTaggedImplicit<'a, E> for T
where T: 'a,

Source§

fn implicit( self, class: Class, constructed: bool, tag: u32, ) -> TaggedParser<'a, Implicit, Self, E>

Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.