pub struct ThreeLayerRateLimiter { /* private fields */ }Expand description
Three-layer rate limiter for inbound authenticated per-request traffic.
Methods are &self — concurrent admission decisions don’t take a write
lock. Each layer uses its own governor limiter and the
Result<(), RejectLayer> short-circuits at the first rejection.
Keyspace bound (#645). The two keyed layers carry per-layer
cap_per_{ip,peer} and pruning_per_{ip,peer} fields. The flags are
deliberately split (not one shared) so a slow per-IP retain_recent sweep
does not block a concurrent per-peer sweep — and vice versa.
Implementations§
Source§impl ThreeLayerRateLimiter
impl ThreeLayerRateLimiter
Sourcepub fn new(
cfg: &RateLimitConfig,
metrics: Arc<dyn RateLimitMetricsSink>,
) -> Self
pub fn new( cfg: &RateLimitConfig, metrics: Arc<dyn RateLimitMetricsSink>, ) -> Self
Build a limiter from the resolved config snapshot and a metrics sink.
Sourcepub fn check(
&self,
peer_node_id: &NodeId,
peer_ip: Option<IpAddr>,
) -> Result<(), RejectLayer>
pub fn check( &self, peer_node_id: &NodeId, peer_ip: Option<IpAddr>, ) -> Result<(), RejectLayer>
Try to admit one inbound request. peer_ip == None for relay-only
connections — the per-IP layer is skipped (no key to charge), matching
the ConnectionLimiter precedent at
crate::dispatch::ConnectionLimiter::acquire.
On rejection, calls RateLimitMetricsSink::rejected with the layer
that fired and returns it. No sink call on the success path.
Cheapest-first ordering (global → per-IP → per-peer): the first layer
to reject short-circuits, so a per-peer-flooded request that would also
have failed the global cap counts as global (the layer that actually
drained the budget).
Sourcepub fn admit_batch_extra(
&self,
peer_node_id: &NodeId,
peer_ip: Option<IpAddr>,
extra: usize,
) -> usize
pub fn admit_batch_extra( &self, peer_node_id: &NodeId, peer_ip: Option<IpAddr>, extra: usize, ) -> usize
Stage 2 of the two-stage batch admission (ADR 022 §Batch token
accounting). After Self::check has charged the stage-1 frame token,
this consumes up to extra (= n - 1 for a batch of n hashes) more
units cheapest-first, each unit identical to what one separate
StoreRequest admission would charge — so the per-second work ceiling
is the same whether the publisher sends n separate Stores or one
BatchStore of size n (ADR 022 AC 17).
Returns the number of extra units granted; the first 1 + returned
hashes of the batch pass through per-hash processing, the remainder are
acked false. Returns 0 when extra == 0 or the budget is already
exhausted.
No rejection counter is bumped: the inbound frame was already admitted
at stage 1, and the over-budget tail is deferred work the publisher
retries, not a rejected request. Because the per-unit charge
short-circuits cheapest-first, the terminating unit may consume a global
(and per-IP) token without a per-peer token — byte-for-byte what the
(k+1)-th separate Store would have done.
Sourcepub fn gc_per_ip(&self) -> Option<(usize, usize)>
pub fn gc_per_ip(&self) -> Option<(usize, usize)>
Periodic GC sweep for the per-IP keyed map (#645). Returns
Some((before, after)) on a sweep that actually ran, or None when the
per-IP layer is disabled or the single-flight CAS was lost to a
concurrent prune (lazy or another GC tick). Mirrors
crate::dispatch::ConnectionLimiter::gc_per_source.
Sourcepub fn gc_per_peer(&self) -> Option<(usize, usize)>
pub fn gc_per_peer(&self) -> Option<(usize, usize)>
Periodic GC sweep for the per-peer keyed map (#645). Sibling of
Self::gc_per_ip.
Sourcepub fn per_ip_tracked(&self) -> usize
pub fn per_ip_tracked(&self) -> usize
Current tracked-key count for the per-IP keyed map (#645). 0 when the
layer is disabled.
Sourcepub fn per_peer_tracked(&self) -> usize
pub fn per_peer_tracked(&self) -> usize
Current tracked-key count for the per-peer keyed map (#645).
Auto Trait Implementations§
impl !Freeze for ThreeLayerRateLimiter
impl !RefUnwindSafe for ThreeLayerRateLimiter
impl !UnwindSafe for ThreeLayerRateLimiter
impl Send for ThreeLayerRateLimiter
impl Sync for ThreeLayerRateLimiter
impl Unpin for ThreeLayerRateLimiter
impl UnsafeUnpin for ThreeLayerRateLimiter
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