Skip to main content

Eviction

Struct Eviction 

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

How the limiter bounds the memory its per-key state can occupy.

A rate limiter that tracks state per key is a denial-of-service vector against itself if that state can grow without limit: a flood of unique keys would exhaust memory. Eviction is the defense. Two independent bounds compose:

  • Capacity — a hard ceiling on the number of live keys. When inserting a new key would exceed it, the least-recently-seen key is evicted. This is what caps a unique-key flood.
  • Idle TTL — keys not seen for longer than the TTL become evictable, so long-idle state is reclaimed rather than held forever.

Eviction is lazy and incremental: it happens while inserting a new key, touches only the one shard being written, and never sweeps the whole store or blocks the steady-state check path. The capacity is enforced approximately per shard, so the live-key count stays within a small factor of the cap.

The Default is safe: a DEFAULT_MAX_KEYS capacity cap and no TTL — memory is bounded out of the box. Opt into unbounded growth explicitly with unbounded, understanding the risk.

§Examples

use rate_net::Eviction;
use std::time::Duration;

// Cap at 100k keys and reclaim anything idle for five minutes.
let policy = Eviction::capacity(100_000).with_idle(Duration::from_secs(300));
assert_eq!(policy.max_keys(), Some(100_000));
assert_eq!(policy.idle_ttl(), Some(Duration::from_secs(300)));

Implementations§

Source§

impl Eviction

Source

pub const fn capacity(max_keys: usize) -> Self

A hard cap of max_keys live keys, with no idle expiry.

A max_keys of 0 is treated as 1 (the store always holds at least one key per shard).

§Examples
use rate_net::Eviction;

let policy = Eviction::capacity(50_000);
assert_eq!(policy.max_keys(), Some(50_000));
assert_eq!(policy.idle_ttl(), None);
Source

pub const fn idle(ttl: Duration) -> Self

Reclaim keys idle for longer than ttl, keeping the default capacity cap.

Idle expiry alone does not bound a unique-key flood — flooded keys are not idle — so this keeps the DEFAULT_MAX_KEYS cap as the flood defense and layers the TTL on top. Use capacity plus with_idle to choose both bounds explicitly.

§Examples
use rate_net::{Eviction, DEFAULT_MAX_KEYS};
use std::time::Duration;

let policy = Eviction::idle(Duration::from_secs(300));
assert_eq!(policy.idle_ttl(), Some(Duration::from_secs(300)));
assert_eq!(policy.max_keys(), Some(DEFAULT_MAX_KEYS));
Source

pub const fn new(max_keys: usize, ttl: Duration) -> Self

Both bounds at once: a max_keys cap and an idle ttl.

§Examples
use rate_net::Eviction;
use std::time::Duration;

let policy = Eviction::new(10_000, Duration::from_secs(60));
assert_eq!(policy.max_keys(), Some(10_000));
assert_eq!(policy.idle_ttl(), Some(Duration::from_secs(60)));
Source

pub const fn unbounded() -> Self

No bounds at all — the store grows without limit.

Only safe when the key space is intrinsically bounded (a fixed set of tenants, say). Against untrusted keys this is a self-inflicted denial-of-service: prefer capacity.

§Examples
use rate_net::Eviction;

let policy = Eviction::unbounded();
assert_eq!(policy.max_keys(), None);
assert_eq!(policy.idle_ttl(), None);
Source

pub const fn with_capacity(self, max_keys: usize) -> Self

Returns a copy with the capacity cap set to max_keys.

§Examples
use rate_net::Eviction;
use std::time::Duration;

let policy = Eviction::idle(Duration::from_secs(30)).with_capacity(1_000);
assert_eq!(policy.max_keys(), Some(1_000));
Source

pub const fn with_idle(self, ttl: Duration) -> Self

Returns a copy with idle expiry set to ttl.

§Examples
use rate_net::Eviction;
use std::time::Duration;

let policy = Eviction::capacity(1_000).with_idle(Duration::from_secs(30));
assert_eq!(policy.idle_ttl(), Some(Duration::from_secs(30)));
Source

pub const fn without_capacity(self) -> Self

Returns a copy with the capacity cap removed (unbounded key count).

§Examples
use rate_net::Eviction;

let policy = Eviction::default().without_capacity();
assert_eq!(policy.max_keys(), None);
Source

pub const fn max_keys(&self) -> Option<usize>

The configured capacity cap, if any.

Source

pub const fn idle_ttl(&self) -> Option<Duration>

The configured idle TTL, if any.

Trait Implementations§

Source§

impl Clone for Eviction

Source§

fn clone(&self) -> Eviction

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Eviction

Source§

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

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

impl Default for Eviction

Source§

fn default() -> Self

A DEFAULT_MAX_KEYS capacity cap and no idle TTL — bounded memory out of the box.

Source§

impl PartialEq for Eviction

Source§

fn eq(&self, other: &Eviction) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Copy for Eviction

Source§

impl Eq for Eviction

Source§

impl StructuralPartialEq for Eviction

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<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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. 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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

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

Source§

type Error = Infallible

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

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

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.
Source§

impl<E> WithErrorCode<E> for E

Source§

fn with_code(self, code: impl Into<String>) -> CodedError<E>

Attach an error code to an error
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,