Skip to content

Commit

Permalink
Parse Limit's Predicates on creation
Browse files Browse the repository at this point in the history
Signed-off-by: Alex Snaps <[email protected]>
  • Loading branch information
alexsnaps committed Nov 27, 2024
1 parent 8bb6203 commit 9edeb4e
Show file tree
Hide file tree
Showing 12 changed files with 330 additions and 301 deletions.
40 changes: 28 additions & 12 deletions limitador-server/src/envoy_rls/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,10 +253,9 @@ mod tests {
namespace,
1,
60,
vec!["req_method == 'GET'".to_string()],
vec!["req_method == 'GET'".try_into().expect("failed parsing!")],
vec!["app_id"],
)
.expect("This must be a valid limit!");
);

let limiter = RateLimiter::new(10_000);
limiter.add_limit(limit);
Expand Down Expand Up @@ -395,16 +394,23 @@ mod tests {
let namespace = "test_namespace";

vec![
Limit::new(namespace, 10, 60, vec!["x == '1'".to_string()], vec!["z"])
.expect("This must be a valid limit!"),
Limit::new(
namespace,
10,
60,
vec!["x == '1'".try_into().expect("failed parsing!")],
vec!["z"],
),
Limit::new(
namespace,
0,
60,
vec!["x == '1'".to_string(), "y == '2'".to_string()],
vec![
"x == '1'".try_into().expect("failed parsing!"),
"y == '2'".try_into().expect("failed parsing!"),
],
vec!["z"],
)
.expect("This must be a valid limit!"),
),
]
.into_iter()
.for_each(|limit| {
Expand Down Expand Up @@ -468,8 +474,13 @@ mod tests {
#[tokio::test]
async fn test_takes_into_account_the_hits_addend_param() {
let namespace = "test_namespace";
let limit = Limit::new(namespace, 10, 60, vec!["x == '1'".to_string()], vec!["y"])
.expect("This must be a valid limit!");
let limit = Limit::new(
namespace,
10,
60,
vec!["x == '1'".try_into().expect("failed parsing!")],
vec!["y"],
);

let limiter = RateLimiter::new(10_000);
limiter.add_limit(limit);
Expand Down Expand Up @@ -538,8 +549,13 @@ mod tests {
// "hits_addend" is optional according to the spec, and should default
// to 1, However, with the autogenerated structs it defaults to 0.
let namespace = "test_namespace";
let limit = Limit::new(namespace, 1, 60, vec!["x == '1'".to_string()], vec!["y"])
.expect("This must be a valid limit!");
let limit = Limit::new(
namespace,
1,
60,
vec!["x == '1'".try_into().expect("failed parsing!")],
vec!["y"],
);

let limiter = RateLimiter::new(10_000);
limiter.add_limit(limit);
Expand Down
13 changes: 8 additions & 5 deletions limitador-server/src/http_api/request_types.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use limitador::counter::Counter as LimitadorCounter;
use limitador::limit::{Limit as LimitadorLimit, ParseError};
use limitador::limit::{Limit as LimitadorLimit, ParseError, Predicate};
use paperclip::actix::Apiv2Schema;
use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, HashMap};
Expand Down Expand Up @@ -44,23 +44,26 @@ impl TryFrom<Limit> for LimitadorLimit {
type Error = ParseError;

fn try_from(limit: Limit) -> Result<Self, Self::Error> {
let conditions: Result<Vec<Predicate>, ParseError> =
limit.conditions.into_iter().map(|p| p.try_into()).collect();

let mut limitador_limit = if let Some(id) = limit.id {
Self::with_id(
id,
limit.namespace,
limit.max_value,
limit.seconds,
limit.conditions,
conditions?,
limit.variables,
)?
)
} else {
Self::new(
limit.namespace,
limit.max_value,
limit.seconds,
limit.conditions,
conditions?,
limit.variables,
)?
)
};

if let Some(name) = limit.name {
Expand Down
5 changes: 2 additions & 3 deletions limitador-server/src/http_api/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -553,10 +553,9 @@ mod tests {
namespace,
max,
60,
vec!["req_method == 'GET'"],
vec!["req_method == 'GET'".try_into().expect("failed parsing!")],
vec!["app_id"],
)
.expect("This must be a valid limit!");
);

match &limiter {
Limiter::Blocking(limiter) => limiter.add_limit(limit.clone()),
Expand Down
23 changes: 12 additions & 11 deletions limitador/benches/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -529,7 +529,11 @@ fn generate_test_limits(scenario: &TestScenario) -> (Vec<Limit>, Vec<TestCallPar
let mut conditions = vec![];
for idx_cond in 0..scenario.n_conds_per_limit {
let cond_name = format!("cond_{idx_cond}");
conditions.push(format!("{cond_name} == '1'"));
conditions.push(
format!("{cond_name} == '1'")
.try_into()
.expect("failed parsing!"),
);
test_values.insert(cond_name, "1".into());
}

Expand All @@ -547,16 +551,13 @@ fn generate_test_limits(scenario: &TestScenario) -> (Vec<Limit>, Vec<TestCallPar
let namespace = idx_namespace.to_string();

for limit_idx in 0..scenario.n_limits_per_ns {
test_limits.push(
Limit::new(
namespace.clone(),
u64::MAX,
((limit_idx * 60) + 10) as u64,
conditions.clone(),
variables.clone(),
)
.expect("This must be a valid limit!"),
)
test_limits.push(Limit::new(
namespace.clone(),
u64::MAX,
((limit_idx * 60) + 10) as u64,
conditions.clone(),
variables.clone(),
))
}

call_params.push(TestCallParams {
Expand Down
23 changes: 8 additions & 15 deletions limitador/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
//! "my_namespace",
//! 10,
//! 60,
//! vec!["req_method == 'GET'"],
//! vec!["req_method == 'GET'".try_into().expect("failed parsing!")],
//! vec!["user_id"],
//! );
//! ```
Expand All @@ -71,9 +71,9 @@
//! "my_namespace",
//! 10,
//! 60,
//! vec!["req_method == 'GET'"],
//! vec!["req_method == 'GET'".try_into().expect("failed parsing!")],
//! vec!["user_id"],
//! ).unwrap();
//! );
//! let mut rate_limiter = RateLimiter::new(1000);
//!
//! // Add a limit
Expand Down Expand Up @@ -103,9 +103,9 @@
//! "my_namespace",
//! 2,
//! 60,
//! vec!["req_method == 'GET'"],
//! vec!["req_method == 'GET'".try_into().expect("failed parsing!")],
//! vec!["user_id"],
//! ).unwrap();
//! );
//! rate_limiter.add_limit(limit);
//!
//! // We've defined a limit of 2. So we can report 2 times before being
Expand Down Expand Up @@ -167,9 +167,9 @@
//! "my_namespace",
//! 10,
//! 60,
//! vec!["req_method == 'GET'"],
//! vec!["req_method == 'GET'".try_into().expect("failed parsing!")],
//! vec!["user_id"],
//! ).unwrap();
//! );
//!
//! async {
//! let rate_limiter = AsyncRateLimiter::new_with_storage(
Expand Down Expand Up @@ -702,14 +702,7 @@ mod test {
let rl = RateLimiter::new(100);
let namespace = "foo";

let l = Limit::new::<_, String>(
namespace,
42,
100,
Vec::<String>::default(),
Vec::<String>::default(),
)
.expect("This must be a valid limit!");
let l = Limit::new(namespace, 42, 100, vec![], Vec::<String>::default());
rl.add_limit(l.clone());
let limits = rl.get_limits(&namespace.into());
assert_eq!(limits.len(), 1);
Expand Down
Loading

0 comments on commit 9edeb4e

Please sign in to comment.