mirror of
https://github.com/logos-messaging/logos-delivery.git
synced 2026-07-20 03:30:22 +00:00
admit now meters each transmission against messagesPerEpoch and rolls the epoch window when epochPeriodSec elapses, instead of admitting every call. This is the client-side rate gate the SendService already calls into. Drop the unused queue field and dequeueReady: the SendService owns the pending work as DeliveryTasks and re-offers parked ones each loop tick, so the manager needs no queue of its own. admit keeps its signature so both call sites stay untouched. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
36 lines
1.2 KiB
Nim
36 lines
1.2 KiB
Nim
{.used.}
|
|
|
|
import chronos, testutils/unittests, stew/byteutils
|
|
|
|
import logos_delivery/messaging/rate_limit_manager/rate_limit_manager
|
|
|
|
suite "RateLimitManager - admission":
|
|
asyncTest "admit is a pass-through when disabled":
|
|
let rl = RateLimitManager.new(
|
|
RateLimitConfig(enabled: false, epochPeriodSec: 600, messagesPerEpoch: 1)
|
|
)
|
|
for _ in 0 ..< 10:
|
|
let res = await rl.admit("payload".toBytes())
|
|
check res.isOk()
|
|
|
|
asyncTest "admit enforces the per-epoch budget when enabled":
|
|
let rl = RateLimitManager.new(
|
|
RateLimitConfig(enabled: true, epochPeriodSec: 600, messagesPerEpoch: 1)
|
|
)
|
|
check (await rl.admit("first".toBytes())).isOk()
|
|
|
|
let overBudget = await rl.admit("second".toBytes())
|
|
check overBudget.isErr()
|
|
check overBudget.error == RateLimitError.OverBudget
|
|
|
|
asyncTest "admit reopens the budget after the epoch rolls over":
|
|
let rl = RateLimitManager.new(
|
|
RateLimitConfig(enabled: true, epochPeriodSec: 600, messagesPerEpoch: 1)
|
|
)
|
|
check (await rl.admit("first".toBytes())).isOk()
|
|
check (await rl.admit("second".toBytes())).isErr()
|
|
|
|
# Simulate the epoch window elapsing; the next call must be admitted again.
|
|
rl.resetEpoch()
|
|
check (await rl.admit("third".toBytes())).isOk()
|