Skip to content

Commit

Permalink
[feature] Getting updated counters from redis
Browse files Browse the repository at this point in the history
  • Loading branch information
didierofrivia committed Apr 15, 2024
1 parent d277e52 commit 3ade8cf
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 5 deletions.
19 changes: 16 additions & 3 deletions limitador/src/storage/redis/redis_async.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,25 +238,38 @@ impl AsyncRedisStorage {
pub async fn update_counters(
&self,
counters_and_deltas: HashMap<Counter, AtomicExpiringValue>,
) -> Result<(), StorageErr> {
) -> Result<HashMap<Counter, i64>, StorageErr> {
let mut con = self.conn_manager.clone();
let span = trace_span!("datastore");

let redis_script = redis::Script::new(BATCH_UPDATE_COUNTERS);
let mut script_invocation = redis_script.prepare_invoke();

// TODO: Fix calculating delta value greater than zero at _now_ and return the right AtomicExpiringValue
for (counter, delta) in counters_and_deltas {
script_invocation.key(key_for_counter(&counter));
script_invocation.key(key_for_counters_of_limit(counter.limit()));
script_invocation.arg(counter.seconds());
script_invocation.arg(delta);
}

async { script_invocation.invoke_async::<_, _>(&mut con).await }
let script_res: Vec<Option<(String, i64)>> = script_invocation
.invoke_async::<_, _>(&mut con)
.instrument(span)
.await?;

Ok(())
let counter_value_map: HashMap<Counter, i64> = script_res
.iter()
.filter_map(|counter_value| match counter_value {
Some((raw_counter_key, val)) => {
let counter = partial_counter_from_counter_key(raw_counter_key);
Some((counter, *val))
}
None => None,
})
.collect();

Ok(counter_value_map)
}
}

Expand Down
4 changes: 2 additions & 2 deletions limitador/src/storage/redis/redis_cached.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,13 +250,13 @@ impl CachedRedisStorage {
};

// TODO: After rebase, the code needs to be refactored to use delta.value_at(SystemTime::now()) and compare delta is greater than 0 after adding the key to update in update_counters
storage
let _updated_counters = storage
.update_counters(counters)
.await
.or_else(|err| {
if err.is_transient() {
p.store(true, Ordering::Release);
Ok(())
Ok(HashMap::default())
} else {
Err(err)
}
Expand Down
3 changes: 3 additions & 0 deletions limitador/src/storage/redis/scripts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pub const SCRIPT_UPDATE_COUNTER: &str = "
// ARGV[i]: TTLs
// ARGV[i+1]: Deltas
pub const BATCH_UPDATE_COUNTERS: &str = "
local res = {}
for i = 1, #KEYS, 2 do
local counter_key = KEYS[i]
local limit_key = KEYS[i+1]
Expand All @@ -35,7 +36,9 @@ pub const BATCH_UPDATE_COUNTERS: &str = "
redis.call('expire', counter_key, ttl)
redis.call('sadd', limit_key, counter_key)
end
table.insert(res, { counter_key, c })
end
return res
";

// KEYS: the function returns the value and TTL (in ms) for these keys
Expand Down

0 comments on commit 3ade8cf

Please sign in to comment.