From 8029d6051f60d8b56374e2bb4e030ddfbdc294ea Mon Sep 17 00:00:00 2001 From: Wez Furlong Date: Mon, 6 Jan 2025 08:39:08 -0700 Subject: [PATCH] throttle: more redis limit diagnostics --- crates/mod-redis/src/test.rs | 2 +- crates/throttle/src/limit.rs | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/crates/mod-redis/src/test.rs b/crates/mod-redis/src/test.rs index 7dc16ed4..4fdd098b 100644 --- a/crates/mod-redis/src/test.rs +++ b/crates/mod-redis/src/test.rs @@ -70,7 +70,7 @@ impl RedisServer { // Generate configuration if let Some(mut stdin) = daemon.stdin.take() { stdin - .write_all(b"bind 127.0.0.1\nlogfile /dev/stdout\n") + .write_all(b"bind 127.0.0.1\nlogfile /dev/stdout\nloglevel debug\n") .await?; stdin.write_all(format!("port {port}\n").as_bytes()).await?; stdin diff --git a/crates/throttle/src/limit.rs b/crates/throttle/src/limit.rs index 2afe154d..f01ccaf5 100644 --- a/crates/throttle/src/limit.rs +++ b/crates/throttle/src/limit.rs @@ -18,12 +18,16 @@ local expires_ts = math.ceil(tonumber(ARGV[2])) local limit = tonumber(ARGV[3]) local uuid = ARGV[4] +redis.log(redis.LOG_DEBUG, "limiter: going to call ZREMRANGEBYSCORE", KEYS[1], now_ts-1) + -- prune expired values redis.call("ZREMRANGEBYSCORE", KEYS[1], "-inf", now_ts-1) +redis.log(redis.LOG_DEBUG, "limiter: going to call ZCARD", KEYS[1]) local count = redis.call("ZCARD", KEYS[1]) if count + 1 > limit then -- find the next expiration time + redis.log(redis.LOG_DEBUG, "limiter: going to call ZRANGE", KEYS[1]) local smallest = redis.call("ZRANGE", KEYS[1], "-inf", "+inf", "BYSCORE", "LIMIT", 0, 1, "WITHSCORES") -- smallest holds the uuid and its expiration time; -- we want to just return the remaining time interval @@ -32,6 +36,7 @@ if count + 1 > limit then end return math.ceil(smallest[2] - now_ts) end +redis.log(redis.LOG_DEBUG, "limiter: going to call ZADD", KEYS[1], expires_ts, uuid) redis.call("ZADD", KEYS[1], "NX", expires_ts, uuid) return redis.status_reply('OK') "#, @@ -123,6 +128,15 @@ impl LimitSpecWithDuration { tokio::time::sleep(Duration::from_secs(3)).await; } + mod_redis::RedisValue::Double(next_expiration_interval) => { + if Instant::now() >= deadline { + return Err(Error::TooManyLeases(Duration::from_secs( + next_expiration_interval as u64, + ))); + } + + tokio::time::sleep(Duration::from_secs(3)).await; + } value => { return Err(anyhow!("acquire script succeeded but returned {value:?}").into()); }