start with 1 token in rate limiter rather than a full bucket (per/min providers only
All checks were successful
Generic zig build / build (push) Successful in 27s

This commit is contained in:
Emil Lerch 2026-03-12 15:28:23 -07:00
parent 7fabc794c1
commit 3e13faa66f
Signed by: lobo
GPG key ID: A7B62D657EF764F8

View file

@ -29,9 +29,12 @@ pub fn init(max_per_window: u32, window_ns: u64) RateLimiter {
}; };
} }
/// Convenience: N requests per minute /// Convenience: N requests per minute.
/// Starts with 1 token (no burst) to stay within provider sliding-window limits.
pub fn perMinute(n: u32) RateLimiter { pub fn perMinute(n: u32) RateLimiter {
return init(n, std.time.ns_per_min); var rl = init(n, std.time.ns_per_min);
rl.tokens = 1.0;
return rl;
} }
/// Convenience: N requests per day /// Convenience: N requests per day
@ -87,8 +90,19 @@ fn refill(self: *RateLimiter) void {
test "rate limiter basic" { test "rate limiter basic" {
var rl = RateLimiter.perMinute(60); var rl = RateLimiter.perMinute(60);
// Should have full bucket initially // perMinute starts with 1 token (no burst)
try std.testing.expect(rl.tryAcquire()); try std.testing.expect(rl.tryAcquire());
// Second call should be rate-limited immediately
try std.testing.expect(!rl.tryAcquire());
}
test "rate limiter perDay keeps full burst" {
var rl = RateLimiter.perDay(25);
// perDay starts with full bucket
for (0..25) |_| {
try std.testing.expect(rl.tryAcquire());
}
try std.testing.expect(!rl.tryAcquire());
} }
test "rate limiter exhaustion" { test "rate limiter exhaustion" {