(new): rich message support
Golang lint / lint (pull_request) Successful in 1m20s
Golang lint / lint (push) Successful in 4m8s

(fix): runtime reliability
(tests): regression coverage
(doc): v1.1 release notes
This commit is contained in:
2026-08-12 16:34:44 +03:00
parent 48ddf66540
commit f03a081ed6
83 changed files with 6122 additions and 1925 deletions
+20 -9
View File
@@ -157,9 +157,8 @@ func (rl *RateLimiter) GlobalAllow() bool {
return limiter.Allow()
}
// Allow checks if a request for the given chat can be made without blocking.
// Returns false if: global cooldown, chat cooldown, global limiter, or chat limiter denies.
// Note: Global limiter is checked before chat limiter — upstream limits take priority.
// Allow checks whether a request for the given chat can be made without blocking.
// A rejected chat reservation does not consume global capacity.
func (rl *RateLimiter) Allow(chatID int64) bool {
// Check global cooldown
rl.globalMu.RLock()
@@ -177,15 +176,27 @@ func (rl *RateLimiter) Allow(chatID int64) bool {
return false
}
// Check global token bucket
limiter := rl.getGlobalLimiter()
if limiter != nil && !limiter.Allow() {
return false
now := time.Now()
globalLimiter := rl.getGlobalLimiter()
var globalReservation *rate.Reservation
if globalLimiter != nil {
globalReservation = globalLimiter.ReserveN(now, 1)
if !globalReservation.OK() || globalReservation.DelayFrom(now) > 0 {
globalReservation.CancelAt(now)
return false
}
}
// Check chat token bucket
chatLimiter := rl.getChatLimiter(chatID)
return chatLimiter.Allow()
chatReservation := chatLimiter.ReserveN(now, 1)
if !chatReservation.OK() || chatReservation.DelayFrom(now) > 0 {
chatReservation.CancelAt(now)
if globalReservation != nil {
globalReservation.CancelAt(now)
}
return false
}
return true
}
// Check applies rate limiting based on configuration.