haste_rate_limit/lib.rs
1use std::pin::Pin;
2
3pub enum RateLimitError {
4 Error(String),
5 Exceeded,
6}
7
8pub trait RateLimit: Sync + Send {
9 /// Spends `points` against `rate_key` and returns the running total, or
10 /// [`RateLimitError::Exceeded`] once it would pass `max`. May be served
11 /// from a short-lived in-memory cache, so concurrent callers can each read
12 /// the same pre-spend total and slip past the cap by a small margin before
13 /// the backing store catches up.
14 fn check<'a>(
15 &'a self,
16 rate_key: &'a str,
17 max: i32,
18 points: i32,
19 window_in_seconds: i32,
20 ) -> Pin<Box<dyn Future<Output = Result<i32, RateLimitError>> + Send + 'a>>;
21
22 /// Like [`RateLimit::check`], but always consults the backing store rather
23 /// than any in-memory cache, so every concurrent call is counted exactly.
24 /// Use it to gate security-sensitive actions where the cache's slack would
25 /// let parallel requests exceed the cap, such as verification-code guesses.
26 /// The default delegates to [`RateLimit::check`]; back it with a serialized
27 /// store operation in real implementations.
28 fn check_uncached<'a>(
29 &'a self,
30 rate_key: &'a str,
31 max: i32,
32 points: i32,
33 window_in_seconds: i32,
34 ) -> Pin<Box<dyn Future<Output = Result<i32, RateLimitError>> + Send + 'a>> {
35 self.check(rate_key, max, points, window_in_seconds)
36 }
37}