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
impl Limiter
Sourcepub fn at_most(
self,
event_id: impl EventId,
limit: u32,
window: impl Into<TimeWindow>,
) -> Self
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::Daysmeans 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());Sourcepub fn at_least(
self,
event_id: impl EventId,
count: u32,
window: impl Into<TimeWindow>,
) -> Self
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::Daysmeans 1 day)(usize, TimeUnit)- explicit count (e.g.,(7, TimeUnit::Days)means 7 days)Duration- converted to best matching TimeUnit
Sourcepub fn cooldown(self, event_id: impl EventId, duration: Duration) -> Self
pub fn cooldown(self, event_id: impl EventId, duration: Duration) -> Self
Add a cooldown constraint: event must wait duration since last occurrence.
Sourcepub fn within(
self,
prerequisite_event: impl EventId,
duration: Duration,
) -> Self
pub fn within( self, prerequisite_event: impl EventId, duration: Duration, ) -> Self
Add a “within” constraint: prerequisite must have occurred within duration.
Sourcepub fn during(self, schedule: Schedule) -> Self
pub fn during(self, schedule: Schedule) -> Self
Add a “during” constraint: event must occur within schedule.
Sourcepub fn outside_of(self, schedule: Schedule) -> Self
pub fn outside_of(self, schedule: Schedule) -> Self
Add an “outside of” constraint: event must occur outside schedule.
Sourcepub fn check(self, event_id: impl EventId) -> Result<()>
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());Sourcepub fn check_and_record(self, event_id: impl EventId) -> Result<()>
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());Sourcepub fn reserve(self, event_id: impl EventId) -> Result<Reservation>
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();
}
}Sourcepub fn allowed(self, event_id: impl EventId) -> bool
pub fn allowed(self, event_id: impl EventId) -> bool
Check if all constraints would pass (convenience method).
Sourcepub fn usage(self, event_id: impl EventId) -> Result<LimitUsage>
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.