0

3 Commits
v1.0 ... v1.2

3 changed files with 94 additions and 12 deletions

22
Makefile Normal file
View File

@@ -0,0 +1,22 @@
#!/usr/bin/env gmake -f
GOOPTS=CGO_ENABLED=0
BUILDOPTS=-ldflags="-s -w" -a -gcflags=all=-l
all: clean build
build:
${GOOPTS} go build ${BUILDOPTS}
clean:
go clean
wipe:
go clean
rm -rf go.{mod,sum}
prep:
go mod init main
go mod tidy -compat=1.17
# vim: set ft=make noet ai ts=4 sw=4 sts=4:

81
main.go
View File

@@ -6,8 +6,10 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"os" "os"
"os/signal"
"path/filepath" "path/filepath"
"strings" "strings"
"syscall"
"time" "time"
"github.com/go-redis/redis/v8" "github.com/go-redis/redis/v8"
@@ -35,8 +37,8 @@ type myConfig struct {
// Входящее сообщение из pubsub-канала redis-ки // Входящее сообщение из pubsub-канала redis-ки
type rMsg struct { type rMsg struct {
From string `json:"from,omitempty"` From string `json:"from,omitempty"`
Chatid int64 `json:"chatid,omitempty"` Chatid string `json:"chatid,omitempty"`
Userid int64 `json:"userid,omitempty"` Userid string `json:"userid,omitempty"`
Message string `json:"message,omitempty"` Message string `json:"message,omitempty"`
Plugin string `json:"plugin,omitempty"` Plugin string `json:"plugin,omitempty"`
Mode string `json:"mode,omitempty"` Mode string `json:"mode,omitempty"`
@@ -54,8 +56,8 @@ type rMsg struct {
// Исходящее сообщение в pubsub-канал redis-ки // Исходящее сообщение в pubsub-канал redis-ки
type sMsg struct { type sMsg struct {
From string `json:"from"` From string `json:"from"`
Chatid int64 `json:"chatid"` Chatid string `json:"chatid"`
Userid int64 `json:"userid"` Userid string `json:"userid"`
Message string `json:"message"` Message string `json:"message"`
Plugin string `json:"plugin"` Plugin string `json:"plugin"`
Mode string `json:"mode"` Mode string `json:"mode"`
@@ -76,8 +78,18 @@ var config myConfig
// To break circular message forwarding we must set some sane default, it can be overridden via config // To break circular message forwarding we must set some sane default, it can be overridden via config
var forwardMax int64 = 5 var forwardMax int64 = 5
// Дефолтный конфиг клиента-редиски // Объектики клиента-редиски
var redisClient *redis.Client 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-ки // Горутинка, которая парсит json-чики прилетевшие из REDIS-ки
func msgParser(ctx context.Context, msg string) { func msgParser(ctx context.Context, msg string) {
@@ -97,12 +109,12 @@ func msgParser(ctx context.Context, msg string) {
return return
} }
if exist := j.Chatid; exist == 0 { if exist := j.Chatid; exist == "" {
log.Warnf("Incorrect msg from redis, no chatid field: %s", msg) log.Warnf("Incorrect msg from redis, no chatid field: %s", msg)
return return
} }
if exist := j.Userid; exist == 0 { if exist := j.Userid; exist == "" {
log.Warnf("Incorrect msg from redis, no userid field: %s", msg) log.Warnf("Incorrect msg from redis, no userid field: %s", msg)
return return
} }
@@ -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() // Производит некоторую инициализацию перед запуском main()
func init() { func init() {
log.SetFormatter(&log.TextFormatter{ log.SetFormatter(&log.TextFormatter{
@@ -440,14 +487,30 @@ func main() {
}) })
log.Debugf("Lazy connect() to redis at %s:%d", config.Server, config.Port) 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 { for {
if shutdown {
time.Sleep(1 * time.Second)
continue
}
msg, err := subscriber.ReceiveMessage(ctx) msg, err := subscriber.ReceiveMessage(ctx)
if err != nil { 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) time.Sleep(1 * time.Second)
continue continue
} }

View File

@@ -1,3 +0,0 @@
#!/bin/bash
CGO_ENABLED=0 go build -ldflags="-s -w" -a -gcflags=all=-l