Skip to content

Commit

Permalink
Added switch to configure response timout on Redis
Browse files Browse the repository at this point in the history
  • Loading branch information
alexsnaps committed Mar 27, 2024
1 parent cb98725 commit 2f5e6cd
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 18 deletions.
1 change: 1 addition & 0 deletions limitador-server/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ pub struct RedisStorageCacheConfiguration {
pub max_ttl: u64,
pub ttl_ratio: u64,
pub max_counters: usize,
pub response_timeout: u64,
}

#[derive(PartialEq, Eq, Debug)]
Expand Down
34 changes: 21 additions & 13 deletions limitador-server/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use limitador::storage::disk::DiskStorage;
use limitador::storage::infinispan::{Consistency, InfinispanStorageBuilder};
use limitador::storage::redis::{
AsyncRedisStorage, CachedRedisStorage, CachedRedisStorageBuilder, DEFAULT_FLUSHING_PERIOD_SEC,
DEFAULT_MAX_CACHED_COUNTERS, DEFAULT_MAX_TTL_CACHED_COUNTERS_SEC,
DEFAULT_MAX_CACHED_COUNTERS, DEFAULT_MAX_TTL_CACHED_COUNTERS_SEC, DEFAULT_RESPONSE_TIMEOUT_MS,
DEFAULT_TTL_RATIO_CACHED_COUNTERS,
};
use limitador::storage::{AsyncCounterStorage, AsyncStorage, Storage};
Expand Down Expand Up @@ -147,19 +147,16 @@ impl Limiter {
))
}

cached_redis_storage =
cached_redis_storage.max_ttl_cached_counters(Duration::from_millis(cache_cfg.max_ttl));
cached_redis_storage = cached_redis_storage
.max_ttl_cached_counters(Duration::from_millis(cache_cfg.max_ttl))
.ttl_ratio_cached_counters(cache_cfg.ttl_ratio)
.max_cached_counters(cache_cfg.max_counters)
.response_timeout(Duration::from_millis(cache_cfg.response_timeout));

cached_redis_storage = cached_redis_storage.ttl_ratio_cached_counters(cache_cfg.ttl_ratio);
cached_redis_storage = cached_redis_storage.max_cached_counters(cache_cfg.max_counters);

match cached_redis_storage.build().await {
Ok(storage) => storage,
Err(err) => {
eprintln!("Failed to connect to Redis at {redis_url}: {err}");
process::exit(1)
}
}
cached_redis_storage.build().await.unwrap_or_else(|err| {
eprintln!("Failed to connect to Redis at {redis_url}: {err}");
process::exit(1)
})
}

#[cfg(feature = "infinispan")]
Expand Down Expand Up @@ -653,6 +650,15 @@ fn create_config() -> (Configuration, &'static str) {
.default_value(leak(DEFAULT_MAX_CACHED_COUNTERS))
.display_order(5)
.help("Maximum amount of counters cached"),
)
.arg(
Arg::new("timeout")
.long("response-timeout")
.action(ArgAction::Set)
.value_parser(clap::value_parser!(u64))
.default_value(leak(DEFAULT_RESPONSE_TIMEOUT_MS))
.display_order(6)
.help("Timeout for Redis commands in milliseconds"),
),
);

Expand Down Expand Up @@ -760,6 +766,7 @@ fn create_config() -> (Configuration, &'static str) {
max_ttl: *sub.get_one("TTL").unwrap(),
ttl_ratio: *sub.get_one("ratio").unwrap(),
max_counters: *sub.get_one("max").unwrap(),
response_timeout: *sub.get_one("timeout").unwrap(),
}),
}),
#[cfg(feature = "infinispan")]
Expand Down Expand Up @@ -851,6 +858,7 @@ fn storage_config_from_env() -> Result<StorageConfiguration, ()> {
.parse()
.expect("Expected an u64"),
max_counters: DEFAULT_MAX_CACHED_COUNTERS,
response_timeout: DEFAULT_RESPONSE_TIMEOUT_MS,
})
} else {
None
Expand Down
1 change: 1 addition & 0 deletions limitador/src/storage/redis/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ pub const DEFAULT_FLUSHING_PERIOD_SEC: u64 = 1;
pub const DEFAULT_MAX_CACHED_COUNTERS: usize = 10000;
pub const DEFAULT_MAX_TTL_CACHED_COUNTERS_SEC: u64 = 5;
pub const DEFAULT_TTL_RATIO_CACHED_COUNTERS: u64 = 10;
pub const DEFAULT_RESPONSE_TIMEOUT_MS: u64 = 350;

use crate::counter::Counter;
use crate::storage::{Authorization, StorageErr};
Expand Down
22 changes: 17 additions & 5 deletions limitador/src/storage/redis/redis_cached.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::storage::redis::redis_async::AsyncRedisStorage;
use crate::storage::redis::scripts::VALUES_AND_TTLS;
use crate::storage::redis::{
DEFAULT_FLUSHING_PERIOD_SEC, DEFAULT_MAX_CACHED_COUNTERS, DEFAULT_MAX_TTL_CACHED_COUNTERS_SEC,
DEFAULT_TTL_RATIO_CACHED_COUNTERS,
DEFAULT_RESPONSE_TIMEOUT_MS, DEFAULT_TTL_RATIO_CACHED_COUNTERS,
};
use crate::storage::{AsyncCounterStorage, Authorization, StorageErr};
use async_trait::async_trait;
Expand Down Expand Up @@ -212,6 +212,7 @@ impl CachedRedisStorage {
DEFAULT_MAX_CACHED_COUNTERS,
Duration::from_secs(DEFAULT_MAX_TTL_CACHED_COUNTERS_SEC),
DEFAULT_TTL_RATIO_CACHED_COUNTERS,
Duration::from_millis(DEFAULT_RESPONSE_TIMEOUT_MS),
)
.await
}
Expand All @@ -222,11 +223,17 @@ impl CachedRedisStorage {
max_cached_counters: usize,
ttl_cached_counters: Duration,
ttl_ratio_cached_counters: u64,
response_timeout: Duration,
) -> Result<Self, RedisError> {
let info = ConnectionInfo::from_str(redis_url)?;
let redis_conn_manager = ConnectionManager::new(
let redis_conn_manager = ConnectionManager::new_with_backoff_and_timeouts(
redis::Client::open(info)
.expect("This couldn't fail in the past, yet now it did somehow!"),
2,
100,
6,
response_timeout,
Duration::from_secs(5),
)
.await?;

Expand Down Expand Up @@ -292,9 +299,6 @@ impl CachedRedisStorage {
}

fn partitioned(&self, partition: bool) -> bool {
if partition {
println!("We are partitioned!");
}
self.partitioned
.compare_exchange(!partition, partition, Ordering::Release, Ordering::Acquire)
.is_ok()
Expand Down Expand Up @@ -372,6 +376,7 @@ pub struct CachedRedisStorageBuilder {
max_cached_counters: usize,
max_ttl_cached_counters: Duration,
ttl_ratio_cached_counters: u64,
response_timeout: Duration,
}

impl CachedRedisStorageBuilder {
Expand All @@ -382,6 +387,7 @@ impl CachedRedisStorageBuilder {
max_cached_counters: DEFAULT_MAX_CACHED_COUNTERS,
max_ttl_cached_counters: Duration::from_secs(DEFAULT_MAX_TTL_CACHED_COUNTERS_SEC),
ttl_ratio_cached_counters: DEFAULT_TTL_RATIO_CACHED_COUNTERS,
response_timeout: Duration::from_millis(DEFAULT_RESPONSE_TIMEOUT_MS),
}
}

Expand All @@ -405,13 +411,19 @@ impl CachedRedisStorageBuilder {
self
}

pub fn response_timeout(mut self, response_timeout: Duration) -> Self {
self.response_timeout = response_timeout;
self
}

pub async fn build(self) -> Result<CachedRedisStorage, RedisError> {
CachedRedisStorage::new_with_options(
&self.redis_url,
self.flushing_period,
self.max_cached_counters,
self.max_ttl_cached_counters,
self.ttl_ratio_cached_counters,
self.response_timeout,
)
.await
}
Expand Down

0 comments on commit 2f5e6cd

Please sign in to comment.