mirror of
https://github.com/logos-messaging/logos-delivery.git
synced 2026-03-17 14:33:11 +00:00
* Adapt using chronos' TokenBucket. Removed TokenBucket and test. bump nim-chronos -> nim-libp2p/nim-lsquic/nim-jwt -> adapt to latest libp2p changes * Fix libp2p/utility reports unlisted exception can occure from close of socket in waitForService - -d:ssl compile flag caused it * Adapt request_limiter to new chronos' TokenBucket replenish algorithm to keep original intent of use * Fix filter dos protection test * Fix peer manager tests due change caused by new libp2p * Adjust store test rate limit to eliminate CI test flakyness of timing * Adjust store test rate limit to eliminate CI test flakyness of timing - lightpush/legacy_lightpush/filter * Rework filter dos protection test to avoid CI crazy timing causing flakyness in test results compared to local runs * Rework lightpush dos protection test to avoid CI crazy timing causing flakyness in test results compared to local runs * Rework lightpush and legacy lightpush rate limit tests to eliminate timing effect in CI that cause longer awaits thus result in minting new tokens unlike local runs
70 lines
1.8 KiB
Nim
70 lines
1.8 KiB
Nim
## This module add usage check helpers for simple rate limiting with the use of TokenBucket.
|
|
|
|
{.push raises: [].}
|
|
|
|
import std/[options], chronos/timer, libp2p/stream/connection, libp2p/utility
|
|
|
|
import std/times except TimeInterval, Duration
|
|
|
|
import chronos/ratelimit as token_bucket
|
|
|
|
import ./[setting, service_metrics]
|
|
export token_bucket, setting, service_metrics
|
|
|
|
proc newTokenBucket*(
|
|
setting: Option[RateLimitSetting],
|
|
replenishMode: static[ReplenishMode] = ReplenishMode.Continuous,
|
|
startTime: Moment = Moment.now(),
|
|
): Option[TokenBucket] =
|
|
if setting.isNone():
|
|
return none[TokenBucket]()
|
|
|
|
if setting.get().isUnlimited():
|
|
return none[TokenBucket]()
|
|
|
|
return some(
|
|
TokenBucket.new(
|
|
capacity = setting.get().volume,
|
|
fillDuration = setting.get().period,
|
|
startTime = startTime,
|
|
mode = replenishMode,
|
|
)
|
|
)
|
|
|
|
proc checkUsage(
|
|
t: var TokenBucket, proto: string, now = Moment.now()
|
|
): bool {.raises: [].} =
|
|
if not t.tryConsume(1, now):
|
|
return false
|
|
|
|
return true
|
|
|
|
proc checkUsage(
|
|
t: var Option[TokenBucket], proto: string, now = Moment.now()
|
|
): bool {.raises: [].} =
|
|
if t.isNone():
|
|
return true
|
|
|
|
var tokenBucket = t.get()
|
|
return checkUsage(tokenBucket, proto, now)
|
|
|
|
template checkUsageLimit*(
|
|
t: var Option[TokenBucket] | var TokenBucket,
|
|
proto: string,
|
|
conn: Connection,
|
|
bodyWithinLimit, bodyRejected: untyped,
|
|
) =
|
|
if t.checkUsage(proto):
|
|
let requestStartTime = Moment.now()
|
|
waku_service_requests.inc(labelValues = [proto, "served"])
|
|
|
|
bodyWithinLimit
|
|
|
|
let requestDuration = Moment.now() - requestStartTime
|
|
waku_service_request_handling_duration_seconds.observe(
|
|
requestDuration.milliseconds.float / 1000, labelValues = [proto]
|
|
)
|
|
else:
|
|
waku_service_requests.inc(labelValues = [proto, "rejected"])
|
|
bodyRejected
|