Skip to main content

Eviction

Struct Eviction 

Source
pub struct Eviction { /* private fields */ }
Available on crate feature std only.
Expand description

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

A limiter that keeps 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, and two independent bounds compose:

  • Capacity — a hard ceiling on live keys. Inserting a new key past the ceiling evicts the least-recently-seen one. This 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 runs while inserting a new key, touches only the one shard being written, and never sweeps the whole store or blocks the steady-state path. The capacity is enforced per shard, so the live-key count stays within a small factor of the cap.

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

§Examples

use std::time::Duration;
use throttle_net::Eviction;

// 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 throttle_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.

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

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 std::time::Duration;
use throttle_net::Eviction;

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 throttle_net::Eviction;

let policy = Eviction::unbounded();
assert_eq!(policy.max_keys(), 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 std::time::Duration;
use throttle_net::Eviction;

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 std::time::Duration;
use throttle_net::Eviction;

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 throttle_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 Copy for Eviction

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 Eq for Eviction

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 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<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> 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> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
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> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

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<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more