carapax/ratelimit/predicate/direct/
mod.rs1use std::sync::Arc;
2
3pub use governor::{Jitter, Quota};
4use governor::{
5 RateLimiter,
6 clock::DefaultClock,
7 middleware::NoOpMiddleware,
8 state::{InMemoryState, NotKeyed},
9};
10pub use nonzero_ext::nonzero;
11
12use crate::{
13 core::{Handler, PredicateResult},
14 ratelimit::{
15 jitter::NoJitter,
16 method::{MethodDiscard, MethodWait},
17 },
18};
19
20#[cfg(test)]
21mod tests;
22
23#[derive(Clone)]
27pub struct DirectRateLimitPredicate<J, M> {
28 limiter: Arc<RateLimiter<NotKeyed, InMemoryState, DefaultClock, NoOpMiddleware>>,
29 jitter: J,
30 _method: M,
31}
32
33impl DirectRateLimitPredicate<NoJitter, MethodDiscard> {
34 pub fn discard(quota: Quota) -> Self {
42 Self {
43 limiter: Arc::new(RateLimiter::direct(quota)),
44 jitter: NoJitter,
45 _method: MethodDiscard,
46 }
47 }
48}
49
50impl DirectRateLimitPredicate<NoJitter, MethodWait> {
51 pub fn wait(quota: Quota) -> Self {
59 Self {
60 limiter: Arc::new(RateLimiter::direct(quota)),
61 jitter: NoJitter,
62 _method: MethodWait,
63 }
64 }
65}
66
67impl DirectRateLimitPredicate<Jitter, MethodWait> {
68 pub fn wait_with_jitter(quota: Quota, jitter: Jitter) -> Self {
77 Self {
78 limiter: Arc::new(RateLimiter::direct(quota)),
79 jitter,
80 _method: MethodWait,
81 }
82 }
83}
84
85impl Handler<()> for DirectRateLimitPredicate<NoJitter, MethodDiscard> {
86 type Output = PredicateResult;
87
88 async fn handle(&self, (): ()) -> Self::Output {
89 match self.limiter.check() {
90 Ok(_) => PredicateResult::True,
91 Err(_) => {
92 log::info!("DirectRateLimitPredicate: update discarded");
93 PredicateResult::False
94 }
95 }
96 }
97}
98
99impl Handler<()> for DirectRateLimitPredicate<NoJitter, MethodWait> {
100 type Output = PredicateResult;
101
102 async fn handle(&self, (): ()) -> Self::Output {
103 self.limiter.until_ready().await;
104 PredicateResult::True
105 }
106}
107
108impl Handler<()> for DirectRateLimitPredicate<Jitter, MethodWait> {
109 type Output = PredicateResult;
110
111 async fn handle(&self, (): ()) -> Self::Output {
112 self.limiter.until_ready_with_jitter(self.jitter).await;
113 PredicateResult::True
114 }
115}