Limiter

Struct Limiter 

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

Fluent builder for rate limiting with multiple constraints.

Created by EventStore::limit(), this allows chaining multiple constraints that must all pass before an event can be recorded.

Implementations§

Source§

impl Limiter

Source

pub fn at_most( self, event_id: impl EventId, limit: u32, window: impl Into<TimeWindow>, ) -> Self

Add an “at most” constraint: event cannot exceed limit within time window.

Accepts flexible time window specifications:

  • TimeUnit - defaults to 1 unit (e.g., TimeUnit::Days means 1 day)
  • (usize, TimeUnit) - explicit count (e.g., (7, TimeUnit::Days) means 7 days)
  • Duration - converted to best matching TimeUnit
§Examples
use tiny_counter::{EventStore, TimeUnit};
use chrono::Duration;

let mut store = EventStore::new();

// Single time unit (backward compatible)
let result = store
    .limit()
    .at_most("api_call", 10, TimeUnit::Minutes)
    .check_and_record("api_call");
assert!(result.is_ok());

// Multiple time units with tuple
let result = store
    .limit()
    .at_most("api_call", 100, (7, TimeUnit::Days))
    .check("api_call");
assert!(result.is_ok());

// Duration syntax
let result = store
    .limit()
    .at_most("api_call", 100, Duration::days(7))
    .check("api_call");
assert!(result.is_ok());
Source

pub fn at_least( self, event_id: impl EventId, count: u32, window: impl Into<TimeWindow>, ) -> Self

Add an “at least” constraint: prerequisite must occur at least count times within time window.

Accepts flexible time window specifications:

  • TimeUnit - defaults to 1 unit (e.g., TimeUnit::Days means 1 day)
  • (usize, TimeUnit) - explicit count (e.g., (7, TimeUnit::Days) means 7 days)
  • Duration - converted to best matching TimeUnit
Source

pub fn cooldown(self, event_id: impl EventId, duration: Duration) -> Self

Add a cooldown constraint: event must wait duration since last occurrence.

Source

pub fn within( self, prerequisite_event: impl EventId, duration: Duration, ) -> Self

Add a “within” constraint: prerequisite must have occurred within duration.

Source

pub fn during(self, schedule: Schedule) -> Self

Add a “during” constraint: event must occur within schedule.

Source

pub fn outside_of(self, schedule: Schedule) -> Self

Add an “outside of” constraint: event must occur outside schedule.

Source

pub fn check(self, event_id: impl EventId) -> Result<()>

Check if all constraints pass without recording the event.

§Examples
use tiny_counter::{EventStore, TimeUnit};

let store = EventStore::new();

let result = store
    .limit()
    .at_most("action", 5, TimeUnit::Minutes)
    .check("action");

assert!(result.is_ok());
Source

pub fn check_and_record(self, event_id: impl EventId) -> Result<()>

Check if all constraints pass, and if so, record the event.

This operation is atomic: the event is recorded only if all constraints pass.

§Examples
use tiny_counter::{EventStore, TimeUnit};

let store = EventStore::new();

// First call succeeds and records the event
let result = store
    .limit()
    .at_most("limited_action", 1, TimeUnit::Minutes)
    .check_and_record("limited_action");
assert!(result.is_ok());

// Second call fails because limit is reached
let result = store
    .limit()
    .at_most("limited_action", 1, TimeUnit::Minutes)
    .check_and_record("limited_action");
assert!(result.is_err());
Source

pub fn reserve(self, event_id: impl EventId) -> Result<Reservation>

Reserve a slot if all constraints pass, returning a Reservation.

This atomically checks rate limits including pending reservations, preventing race conditions. The reservation must be explicitly committed to record the event, or it will auto-cancel on drop.

§Examples
use tiny_counter::{EventStore, TimeUnit};

let store = EventStore::new();

// Reserve a slot (atomically checks and reserves)
let reservation = store.limit()
    .at_most("api_call", 10, TimeUnit::Hours)
    .reserve("api_call").unwrap();

// Do work (e.g., make API call)
// ...

// Commit if successful
reservation.commit();
§Transactional Pattern
use tiny_counter::{EventStore, TimeUnit};

fn make_api_call() -> Result<(), Box<dyn std::error::Error>> {
    // ... API call logic
    Ok(())
}

let store = EventStore::new();

let reservation = store.limit()
    .at_most("api_call", 10, TimeUnit::Hours)
    .reserve("api_call").unwrap();

match make_api_call() {
    Ok(_) => reservation.commit(),  // Record on success
    Err(_) => {
        // Reservation auto-cancels on drop
        // Or explicitly: reservation.cancel();
    }
}
Source

pub fn allowed(self, event_id: impl EventId) -> bool

Check if all constraints would pass (convenience method).

Source

pub fn usage(self, event_id: impl EventId) -> Result<LimitUsage>

Get usage information for an “at most” constraint.

Returns usage data for the first AtMost constraint that matches the event_id.

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> 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, 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.