Fix tg bot graceful shutdown
This commit is contained in:
@@ -5,7 +5,6 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -15,14 +14,27 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type TelegramController struct {
|
type TelegramController struct {
|
||||||
|
// deps
|
||||||
bot *tgbotapi.BotAPI
|
bot *tgbotapi.BotAPI
|
||||||
transcribeService *service.TranscribeService
|
transcribeService *service.TranscribeService
|
||||||
jobRepo contract.TranscriptJobRepository
|
jobRepo contract.TranscriptJobRepository
|
||||||
logger *slog.Logger
|
logger *slog.Logger
|
||||||
|
// params
|
||||||
|
updateTimeout int
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTelegramController(transcribeService *service.TranscribeService, jobRepo contract.TranscriptJobRepository, logger *slog.Logger) (*TelegramController, error) {
|
type TelegramConfig struct {
|
||||||
botToken := os.Getenv("TELEGRAM_BOT_TOKEN")
|
BotToken string
|
||||||
|
UpdateTimeout int
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTelegramController(
|
||||||
|
config TelegramConfig,
|
||||||
|
transcribeService *service.TranscribeService,
|
||||||
|
jobRepo contract.TranscriptJobRepository,
|
||||||
|
logger *slog.Logger,
|
||||||
|
) (*TelegramController, error) {
|
||||||
|
botToken := config.BotToken
|
||||||
if botToken == "" {
|
if botToken == "" {
|
||||||
return nil, &EmptyBotTokenError{}
|
return nil, &EmptyBotTokenError{}
|
||||||
}
|
}
|
||||||
@@ -37,6 +49,7 @@ func NewTelegramController(transcribeService *service.TranscribeService, jobRepo
|
|||||||
transcribeService: transcribeService,
|
transcribeService: transcribeService,
|
||||||
jobRepo: jobRepo,
|
jobRepo: jobRepo,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
|
updateTimeout: config.UpdateTimeout,
|
||||||
}
|
}
|
||||||
|
|
||||||
return controller, nil
|
return controller, nil
|
||||||
@@ -46,7 +59,7 @@ func (c *TelegramController) Start() {
|
|||||||
c.logger.Info("Telegram bot started", "username", c.bot.Self.UserName)
|
c.logger.Info("Telegram bot started", "username", c.bot.Self.UserName)
|
||||||
|
|
||||||
u := tgbotapi.NewUpdate(0)
|
u := tgbotapi.NewUpdate(0)
|
||||||
u.Timeout = 60
|
u.Timeout = c.updateTimeout
|
||||||
|
|
||||||
updates := c.bot.GetUpdatesChan(u)
|
updates := c.bot.GetUpdatesChan(u)
|
||||||
|
|
||||||
@@ -79,7 +92,7 @@ func (c *TelegramController) Start() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *TelegramController) Stop() {
|
func (c *TelegramController) Stop() {
|
||||||
c.logger.Info("Telegram bot stopped")
|
c.bot.StopReceivingUpdates()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *TelegramController) handleStartCommand(message *tgbotapi.Message) {
|
func (c *TelegramController) handleStartCommand(message *tgbotapi.Message) {
|
||||||
|
29
main.go
29
main.go
@@ -30,6 +30,13 @@ import (
|
|||||||
sloggin "github.com/samber/slog-gin"
|
sloggin "github.com/samber/slog-gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
TelegramUpdateTimeout = 10
|
||||||
|
ServerShutdownTimeout = 5
|
||||||
|
|
||||||
|
ForceShutdownTimeout = 20
|
||||||
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// Создаем структурированный логгер
|
// Создаем структурированный логгер
|
||||||
logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
|
logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
|
||||||
@@ -101,8 +108,13 @@ func main() {
|
|||||||
// Создаем WaitGroup для ожидания завершения всех воркеров
|
// Создаем WaitGroup для ожидания завершения всех воркеров
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
|
tgConfig := tgcontroller.TelegramConfig{
|
||||||
|
BotToken: os.Getenv("TELEGRAM_BOT_TOKEN"),
|
||||||
|
UpdateTimeout: TelegramUpdateTimeout,
|
||||||
|
}
|
||||||
|
|
||||||
// Создаем Telegram бот
|
// Создаем Telegram бот
|
||||||
tgController, err := tgcontroller.NewTelegramController(transcribeService, jobRepo, logger)
|
tgController, err := tgcontroller.NewTelegramController(tgConfig, transcribeService, jobRepo, logger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("Failed to create Telegram controller", "error", err)
|
logger.Error("Failed to create Telegram controller", "error", err)
|
||||||
// Не останавливаем приложение, если Telegram бот не создан
|
// Не останавливаем приложение, если Telegram бот не создан
|
||||||
@@ -113,10 +125,8 @@ func main() {
|
|||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
logger.Info("Starting Telegram bot")
|
logger.Info("Starting Telegram bot")
|
||||||
tgController.Start()
|
tgController.Start()
|
||||||
|
logger.Info("Telegram bot stopped")
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Добавляем функцию остановки бота в контекст завершения
|
|
||||||
defer tgController.Stop()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Создаем воркеры
|
// Создаем воркеры
|
||||||
@@ -198,8 +208,13 @@ func main() {
|
|||||||
<-sigChan
|
<-sigChan
|
||||||
logger.Info("Received shutdown signal, initiating graceful shutdown...")
|
logger.Info("Received shutdown signal, initiating graceful shutdown...")
|
||||||
|
|
||||||
|
if tgController != nil {
|
||||||
|
logger.Info("Shutting down Telegram bot...")
|
||||||
|
tgController.Stop()
|
||||||
|
}
|
||||||
|
|
||||||
// Создаем контекст с таймаутом для graceful shutdown HTTP сервера
|
// Создаем контекст с таймаутом для graceful shutdown HTTP сервера
|
||||||
shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 5*time.Second)
|
shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), ServerShutdownTimeout*time.Second)
|
||||||
defer shutdownCancel()
|
defer shutdownCancel()
|
||||||
|
|
||||||
// Останавливаем HTTP сервер
|
// Останавливаем HTTP сервер
|
||||||
@@ -220,11 +235,11 @@ func main() {
|
|||||||
close(done)
|
close(done)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Ждем завершения всех воркеров или таймаута в 10 секунд
|
// Ждем завершения всех воркеров или таймаута
|
||||||
select {
|
select {
|
||||||
case <-done:
|
case <-done:
|
||||||
logger.Info("All workers stopped gracefully")
|
logger.Info("All workers stopped gracefully")
|
||||||
case <-time.After(10 * time.Second):
|
case <-time.After(ForceShutdownTimeout * time.Second):
|
||||||
logger.Warn("Timeout reached, forcing shutdown")
|
logger.Warn("Timeout reached, forcing shutdown")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user