From 59643b6a0a719f43d153dac6b2a35d3bf3f9909b Mon Sep 17 00:00:00 2001 From: eleksir Date: Mon, 30 Mar 2026 16:34:18 +0300 Subject: [PATCH] Add cancellable context for Redis operation to prevent hanging redis ops on shutdown - Rename Ctx to RedisCtx with CancelRedisCtx function - Signal handler now cancels context before closing Redis --- cmd/aleesa-misc-go/main.go | 8 ++++---- internal/misc/globals.go | 12 ++++++++++-- internal/misc/sigHandler.go | 5 ++++- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/cmd/aleesa-misc-go/main.go b/cmd/aleesa-misc-go/main.go index 9f53a74..9afac62 100644 --- a/cmd/aleesa-misc-go/main.go +++ b/cmd/aleesa-misc-go/main.go @@ -40,11 +40,11 @@ func main() { MaxRetries: -1, MinRetryBackoff: time.Second, MaxRetryBackoff: 30 * time.Second, - }).WithContext(misc.Ctx).WithTimeout(time.Duration(misc.Config.Timeout) * time.Second) + }).WithContext(misc.RedisCtx).WithTimeout(time.Duration(misc.Config.Timeout) * time.Second) // Проверим, что редиска доступна. Повторяем попытки, пока не подключится. for { - if err := misc.RedisClient.Ping(misc.Ctx).Err(); err == nil { + if err := misc.RedisClient.Ping(misc.RedisCtx).Err(); err == nil { break } @@ -53,7 +53,7 @@ func main() { } // Обозначим, что хотим после соединения подписаться на события из канала config.Channel. - misc.Subscriber = misc.RedisClient.Subscribe(misc.Ctx, misc.Config.Channel) + misc.Subscriber = misc.RedisClient.Subscribe(misc.RedisCtx, misc.Config.Channel) // Самое время поставить траппер сигналов. signal.Notify(misc.SigChan, @@ -69,7 +69,7 @@ func main() { log.Info("Aleesa-misc-go started") for msg := range ch { - misc.MsgParser(misc.Ctx, msg.Payload) + misc.MsgParser(misc.RedisCtx, msg.Payload) } } diff --git a/internal/misc/globals.go b/internal/misc/globals.go index 605201b..e333c2b 100644 --- a/internal/misc/globals.go +++ b/internal/misc/globals.go @@ -3,6 +3,7 @@ package misc import ( "context" "os" + "sync" "github.com/go-redis/redis/v8" ) @@ -20,7 +21,14 @@ var Subscriber *redis.PubSub // Канал, в который приходят уведомления для хэндлера сигналов от траппера сигналов. var SigChan = make(chan os.Signal, 1) -// Main context. -var Ctx = context.Background() +// RedisCtx - контекст для операций с редиской. Отменяется при завершении. +var RedisCtx context.Context +var CancelRedisCtx context.CancelFunc + +var once sync.Once + +func init() { + RedisCtx, CancelRedisCtx = context.WithCancel(context.Background()) +} /* vim: set ft=go noet ai ts=4 sw=4 sts=4: */ diff --git a/internal/misc/sigHandler.go b/internal/misc/sigHandler.go index 5f21d6e..8b26eca 100644 --- a/internal/misc/sigHandler.go +++ b/internal/misc/sigHandler.go @@ -28,8 +28,11 @@ func SigHandler() { continue } + // Отменяем контекст редиски, чтобы все ожидающие операции завершились. + CancelRedisCtx() + // Отпишемся от всех каналов и закроем коннект к редиске. - if err = Subscriber.Unsubscribe(Ctx); err != nil { + if err = Subscriber.Unsubscribe(RedisCtx); err != nil { log.Errorf("Unable to unsubscribe from redis channels cleanly: %s", err) }