From faeeeea9f59c7aeb80f5ad3f43652d4e1f418017 Mon Sep 17 00:00:00 2001 From: eleksir Date: Sat, 21 May 2022 14:40:48 +0300 Subject: [PATCH] =?UTF-8?q?=D0=98=D1=81=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7?= =?UTF-8?q?=D1=83=D0=B5=D0=BC=20=D0=BE=D0=B1=D1=80=D0=B0=D0=B1=D0=BE=D1=82?= =?UTF-8?q?=D1=87=D0=B8=D0=BA=20=D1=81=D0=B8=D0=B3=D0=BD=D0=B0=D0=BB=D0=BE?= =?UTF-8?q?=D0=B2,=20=D1=87=D1=82=D0=BE=D0=B1=D1=8B=20=D0=BA=D0=BE=D1=80?= =?UTF-8?q?=D1=80=D0=B5=D0=BA=D1=82=D0=BD=D0=BE=20=D0=B7=D0=B0=D0=B2=D0=B5?= =?UTF-8?q?=D1=80=D1=88=D0=B0=D1=82=D1=8C=20=D1=81=D0=BE=D0=B5=D0=B4=D0=B8?= =?UTF-8?q?=D0=BD=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=81=20redis-=D0=BA=D0=BE?= =?UTF-8?q?=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main.go | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 66 insertions(+), 3 deletions(-) diff --git a/main.go b/main.go index e2c0bb7..dafd716 100644 --- a/main.go +++ b/main.go @@ -6,8 +6,10 @@ import ( "fmt" "io/ioutil" "os" + "os/signal" "path/filepath" "strings" + "syscall" "time" "github.com/go-redis/redis/v8" @@ -76,8 +78,18 @@ var config myConfig // To break circular message forwarding we must set some sane default, it can be overridden via config var forwardMax int64 = 5 -// Дефолтный конфиг клиента-редиски +// Объектики клиента-редиски var redisClient *redis.Client +var subscriber *redis.PubSub + +// Main context +var ctx = context.Background() + +// Ставится в true, если мы получили сигнал на выключение +var shutdown = false + +// Канал, в который приходят уведомления для хэндлера сигналов от траппера сигналов +var sigChan = make(chan os.Signal, 1) // Горутинка, которая парсит json-чики прилетевшие из REDIS-ки func msgParser(ctx context.Context, msg string) { @@ -389,6 +401,41 @@ func readConfig() { } } +// Хэндлер сигналов закрывает все бд и сваливает из приложения +func sigHandler() { + var err error + + for { + var s = <-sigChan + switch s { + case syscall.SIGINT: + log.Infoln("Got SIGINT, quitting") + case syscall.SIGTERM: + log.Infoln("Got SIGTERM, quitting") + case syscall.SIGQUIT: + log.Infoln("Got SIGQUIT, quitting") + + // Заходим на новую итерацию, если у нас "неинтересный" сигнал + default: + continue + } + + // Чтобы не срать в логи ошибками от редиски, проставим shutdown state приложения в true + shutdown = true + + // Отпишемся от всех каналов и закроем коннект к редиске + if err = subscriber.Unsubscribe(ctx); err != nil { + log.Errorf("Unable to unsubscribe from redis channels cleanly: %s", err) + } + + if err = subscriber.Close(); err != nil { + log.Errorf("Unable to close redis connection cleanly: %s", err) + } + + os.Exit(0) + } +} + // Производит некоторую инициализацию перед запуском main() func init() { log.SetFormatter(&log.TextFormatter{ @@ -440,14 +487,30 @@ func main() { }) log.Debugf("Lazy connect() to redis at %s:%d", config.Server, config.Port) - subscriber := redisClient.Subscribe(ctx, config.Channel) + subscriber = redisClient.Subscribe(ctx, config.Channel) + + // Самое время поставить траппер сигналов + signal.Notify(sigChan, + syscall.SIGINT, + syscall.SIGTERM, + syscall.SIGQUIT) + + go sigHandler() // Обработчик событий от редиски for { + if shutdown { + time.Sleep(1 * time.Second) + continue + } + msg, err := subscriber.ReceiveMessage(ctx) if err != nil { - log.Warnf("Unable to connect to redis at %s:%d: %s", config.Server, config.Port, err) + if !shutdown { + log.Warnf("Unable to connect to redis at %s:%d: %s", config.Server, config.Port, err) + } + time.Sleep(1 * time.Second) continue }