pub struct PositiveProbeCache { /* private fields */ }Expand description
Bounded LRU cache of hash → Vec<(NodeId, rate_per_mb, rtt)>.
Implementations§
Source§impl PositiveProbeCache
impl PositiveProbeCache
Sourcepub fn new() -> Self
pub fn new() -> Self
Build a cache with the ADR 001 §Probe cache defaults (1024 hashes, 15s TTL, ≤10 providers per hash).
Sourcepub fn with_capacity_and_ttl(cap: usize, ttl: Duration) -> Self
pub fn with_capacity_and_ttl(cap: usize, ttl: Duration) -> Self
Build a cache with an explicit capacity and TTL.
Production code uses Self::new; this is the test / tuning seam, for
the same reason
super::negative_cache::NegativeProbeCache::with_capacity_and_ttl is:
the TTL is anchored on Instant, so tokio::time pause / advance has
no effect on it, and 15s of wall clock per assertion is not a test suite.
cap is clamped to ≥ 1.
A ttl of Duration::ZERO disables the cache behaviourally: every
entry is already expired the instant it is read, so Self::get always
misses. That is the supported way to opt out of positive caching — there
is deliberately no disabled() constructor, because a constructor that
turns off an ADR-mandated behaviour is a thing production code will
eventually call.
Sourcepub fn get(&self, hash: &Hash) -> Option<Vec<ProbedProvider>>
pub fn get(&self, hash: &Hash) -> Option<Vec<ProbedProvider>>
The cached providers for hash, best-first, iff an entry exists and its
TTL hasn’t elapsed.
A live hit bumps the entry to the front of the LRU ordering (index 0)
without refreshing its expiry — TTL is anchored at insertion per
ADR 001 §Probe cache. An expired entry is evicted before returning
None.
Returns a clone rather than a guard-scoped borrow on purpose: the caller
rebuilds Candidates from this, which means an await on region_of(..)
per provider, and holding a std::sync::Mutex guard across an await is
exactly the hazard clippy::await_holding_lock exists for. At ≤10 small
providers — each a triple plus a coverage bitmap sized to the blob’s
block count — the clone is not worth arguing about.
Sourcepub fn insert(&self, hash: Hash, providers: Vec<ProbedProvider>)
pub fn insert(&self, hash: Hash, providers: Vec<ProbedProvider>)
Insert / replace the entry for hash with now + TTL expiry, moving it
to the front of the LRU ordering. Evicts the least-recently-used hash on
cap overflow.
providers MUST already be in selection order, best-first: this keeps the
first MAX_PROVIDERS_PER_HASH, which is ADR 001’s “top 10 by selection
score” only if the caller ranked first. The cache cannot rank them itself
— the selection score needs reputation, which is precisely the field
this cache refuses to store.
An empty providers is a no-op. An empty entry is strictly worse than no
entry: it would occupy an LRU slot, hit on every read, and yield nothing
— a cache of “we found nobody”, which is the negative cache’s job and not
on the negative cache’s terms.
Sourcepub fn invalidate(&self, hash: &Hash)
pub fn invalidate(&self, hash: &Hash)
Drop the entry for hash, if any.
ADR 001 §Probe cache: “if all fail, run a fresh DHT lookup + probe.” A hit whose every BUDGETED provider failed to deliver has been disproved by the only evidence that outranks a probe — actual pulls — so it is removed rather than left to keep hitting for the rest of its TTL. The caller may not have tried the entry’s whole list (the attempt budget can be smaller than the list); the top-ranked members failing is disproof enough.
Trait Implementations§
Source§impl Debug for PositiveProbeCache
impl Debug for PositiveProbeCache
Auto Trait Implementations§
impl !Freeze for PositiveProbeCache
impl RefUnwindSafe for PositiveProbeCache
impl Send for PositiveProbeCache
impl Sync for PositiveProbeCache
impl Unpin for PositiveProbeCache
impl UnsafeUnpin for PositiveProbeCache
impl UnwindSafe for PositiveProbeCache
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<T> FutureExt for T
impl<T> FutureExt for T
Source§fn with_context(self, otel_cx: Context) -> WithContext<Self> ⓘ
fn with_context(self, otel_cx: Context) -> WithContext<Self> ⓘ
Source§fn with_current_context(self) -> WithContext<Self> ⓘ
fn with_current_context(self) -> WithContext<Self> ⓘ
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 moreSource§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