From 5a37903a72cab33c99401e7f51f29b1e1ac32729 Mon Sep 17 00:00:00 2001 From: Mohammad Mahdi Date: Wed, 11 Mar 2026 16:18:18 +0330 Subject: [PATCH] fix: rate limiter ticker leak and context cancellation bug - Stop ticker and signal goroutine exit in RegisterCleanup OnStop hook - Call cancel() explicitly after AuthStatus instead of defer to prevent premature context cancellation - Use consistent logger parameter in OnStop hook Co-authored-by: Qwen-Coder --- internal/server/http.go | 4 ++-- internal/server/ratelimiter.go | 27 +++++++++++++++++++++------ 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/internal/server/http.go b/internal/server/http.go index cd5ff2f..7fd2db8 100644 --- a/internal/server/http.go +++ b/internal/server/http.go @@ -55,9 +55,9 @@ func RegisterRoutes(params RouterParams) { // TODO: add gin level cache (look for higher limit) // TODO: image endpoint + hash and expiry authStatCtx, cancel := context.WithTimeout(context.Background(), config.AuthStatusTimeout) - defer cancel() - authStat, err := params.TgService.AuthStatus(authStatCtx) + cancel() + if err != nil { params.Logger.Fatal("Unable to get auth state from telegram", zap.Error(err)) } diff --git a/internal/server/ratelimiter.go b/internal/server/ratelimiter.go index 4275807..42064e1 100644 --- a/internal/server/ratelimiter.go +++ b/internal/server/ratelimiter.go @@ -55,21 +55,36 @@ func (r *RateLimiter) CleanupRateLimiter() { } func RegisterCleanup(lc fx.Lifecycle, logger *zap.Logger, r *RateLimiter) { + var ticker *time.Ticker + var stopChan chan struct{} + lc.Append(fx.Hook{ OnStart: func(ctx context.Context) error { logger.Info("Starting rate limiter cleanup task", zap.Duration("interval", 30*time.Minute)) - ticker := time.NewTicker(30 * time.Minute) + ticker = time.NewTicker(30 * time.Minute) + stopChan = make(chan struct{}) go func() { - for range ticker.C { - logger.Info("Running rate limiter cleanup") - r.CleanupRateLimiter() - logger.Info("Rate limiter cleanup completed") + for { + select { + case <-ticker.C: + logger.Info("Running rate limiter cleanup") + r.CleanupRateLimiter() + logger.Info("Rate limiter cleanup completed") + case <-stopChan: + return + } } }() return nil }, OnStop: func(ctx context.Context) error { - r.logger.Info("Stopping rate limiter cleanup task") + logger.Info("Stopping rate limiter cleanup task") + if ticker != nil { + ticker.Stop() + } + if stopChan != nil { + close(stopChan) + } return nil }, })