pub struct NegativeProbeCache { /* private fields */ }Expand description
Bounded LRU cache of (NodeId, hash) pairs returned
has_blob: false within the TTL window.
Implementations§
Source§impl NegativeProbeCache
impl NegativeProbeCache
Sourcepub fn new() -> Self
pub fn new() -> Self
Build a cache with the ADR 001 § Probe cache defaults (1024 entries, 5- minute TTL).
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 (the ADR 001 § Probe cache
1024-entry, 5-minute defaults); this constructor is the test /
tuning seam. The TTL is anchored on std::time::Instant, so
tokio::time pause / advance has no effect on it, and a short
injected TTL is how a test exercises expiry without a
multi-minute wall-clock wait. Two kinds of test want that:
- One whose subject is TTL SEMANTICS — that expiry sweeps on read, that a read-hit does not re-stamp the window, that a re-record does. This module’s own unit tests are those, and their wall-clock sleeps are the measurement, not overhead.
- One whose subject is the CACHE-WIDE TTL as a quantity.
node_origin’s refusal suite is that case: it shrinks the cache TTL belownode_origin::REFUSAL_SUPPRESSION_TTLto invert the production order, which is the only arrangement in which the two suppression arms have visibly different lifetimes.
A test that needs one ENTRY expired as a precondition — rather
than as its subject — wants neither. Entries hold an absolute
expiry, so Self::record_failure_with_ttl with
Duration::ZERO stamps an already-elapsed expiry on a single
key, Self::contains_active sweeps it on the next read, and
the rest of the cache keeps production behaviour.
cap is clamped to ≥ 1.
Sourcepub fn contains_active(&self, node_id: &NodeId, hash: &Hash) -> bool
pub fn contains_active(&self, node_id: &NodeId, hash: &Hash) -> bool
Filter 3 (ADR 022 § Lookup integrity): returns true iff
(node_id, hash) is in the cache and its TTL hasn’t elapsed.
A live hit bumps the entry to the front of the LRU ordering
(index 0) without refreshing the entry’s expiry — TTL is
anchored at insertion per ADR 001 § Probe cache, not at read. An
expired entry is evicted before returning false.
Sourcepub fn record_failure(&self, node_id: NodeId, hash: Hash)
pub fn record_failure(&self, node_id: NodeId, hash: Hash)
Insert / refresh (node_id, hash) with now + TTL expiry,
moving the entry to the front of the LRU ordering. Evicts the
least-recently-used entry on cap overflow. Producer-side hook
for the outbound probe client; the lookup module never calls
this directly.
Uses the cache-wide TTL, which suits an AUTHORITATIVE negative:
a probe’s has_blob: false is the peer having just looked. For
a weaker signal, pass its own TTL — see
Self::record_failure_with_ttl.
Sourcepub fn record_failure_with_ttl(
&self,
node_id: NodeId,
hash: Hash,
ttl: Duration,
)
pub fn record_failure_with_ttl( &self, node_id: NodeId, hash: Hash, ttl: Duration, )
Self::record_failure with an explicit TTL, for a negative
that is weaker than a probe’s.
Entries store an absolute expiry, so mixing TTLs is free: a
short-lived entry simply falls out sooner, and
Self::contains_active cannot tell the two apart (nor does it
need to). The caller owns the judgement of how much its evidence
is worth — see node_origin::REFUSAL_SUPPRESSION_TTL, which is
far shorter because a delivery refusal, unlike a probe answer,
may not be about the peer at all.
Sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Current entry count. Includes expired entries that haven’t
been swept yet — call Self::contains_active first if a
precise live count is needed.
Trait Implementations§
Source§impl Debug for NegativeProbeCache
impl Debug for NegativeProbeCache
Auto Trait Implementations§
impl !Freeze for NegativeProbeCache
impl RefUnwindSafe for NegativeProbeCache
impl Send for NegativeProbeCache
impl Sync for NegativeProbeCache
impl Unpin for NegativeProbeCache
impl UnsafeUnpin for NegativeProbeCache
impl UnwindSafe for NegativeProbeCache
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