Fix tg bot graceful shutdown

This commit is contained in:
2025-08-14 10:46:06 +03:00
parent a284e3ef29
commit 85db17b131
2 changed files with 40 additions and 12 deletions

View File

@@ -5,7 +5,6 @@ import (
"io"
"log/slog"
"net/http"
"os"
"strings"
"time"
@@ -15,14 +14,27 @@ import (
)
type TelegramController struct {
// deps
bot *tgbotapi.BotAPI
transcribeService *service.TranscribeService
jobRepo contract.TranscriptJobRepository
logger *slog.Logger
// params
updateTimeout int
}
func NewTelegramController(transcribeService *service.TranscribeService, jobRepo contract.TranscriptJobRepository, logger *slog.Logger) (*TelegramController, error) {
botToken := os.Getenv("TELEGRAM_BOT_TOKEN")
type TelegramConfig struct {
BotToken string
UpdateTimeout int
}
func NewTelegramController(
config TelegramConfig,
transcribeService *service.TranscribeService,
jobRepo contract.TranscriptJobRepository,
logger *slog.Logger,
) (*TelegramController, error) {
botToken := config.BotToken
if botToken == "" {
return nil, &EmptyBotTokenError{}
}
@@ -37,6 +49,7 @@ func NewTelegramController(transcribeService *service.TranscribeService, jobRepo
transcribeService: transcribeService,
jobRepo: jobRepo,
logger: logger,
updateTimeout: config.UpdateTimeout,
}
return controller, nil
@@ -46,7 +59,7 @@ func (c *TelegramController) Start() {
c.logger.Info("Telegram bot started", "username", c.bot.Self.UserName)
u := tgbotapi.NewUpdate(0)
u.Timeout = 60
u.Timeout = c.updateTimeout
updates := c.bot.GetUpdatesChan(u)
@@ -79,7 +92,7 @@ func (c *TelegramController) Start() {
}
func (c *TelegramController) Stop() {
c.logger.Info("Telegram bot stopped")
c.bot.StopReceivingUpdates()
}
func (c *TelegramController) handleStartCommand(message *tgbotapi.Message) {

29
main.go
View File

@@ -30,6 +30,13 @@ import (
sloggin "github.com/samber/slog-gin"
)
const (
TelegramUpdateTimeout = 10
ServerShutdownTimeout = 5
ForceShutdownTimeout = 20
)
func main() {
// Создаем структурированный логгер
logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
@@ -101,8 +108,13 @@ func main() {
// Создаем WaitGroup для ожидания завершения всех воркеров
var wg sync.WaitGroup
tgConfig := tgcontroller.TelegramConfig{
BotToken: os.Getenv("TELEGRAM_BOT_TOKEN"),
UpdateTimeout: TelegramUpdateTimeout,
}
// Создаем Telegram бот
tgController, err := tgcontroller.NewTelegramController(transcribeService, jobRepo, logger)
tgController, err := tgcontroller.NewTelegramController(tgConfig, transcribeService, jobRepo, logger)
if err != nil {
logger.Error("Failed to create Telegram controller", "error", err)
// Не останавливаем приложение, если Telegram бот не создан
@@ -113,10 +125,8 @@ func main() {
defer wg.Done()
logger.Info("Starting Telegram bot")
tgController.Start()
logger.Info("Telegram bot stopped")
}()
// Добавляем функцию остановки бота в контекст завершения
defer tgController.Stop()
}
// Создаем воркеры
@@ -198,8 +208,13 @@ func main() {
<-sigChan
logger.Info("Received shutdown signal, initiating graceful shutdown...")
if tgController != nil {
logger.Info("Shutting down Telegram bot...")
tgController.Stop()
}
// Создаем контекст с таймаутом для graceful shutdown HTTP сервера
shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 5*time.Second)
shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), ServerShutdownTimeout*time.Second)
defer shutdownCancel()
// Останавливаем HTTP сервер
@@ -220,11 +235,11 @@ func main() {
close(done)
}()
// Ждем завершения всех воркеров или таймаута в 10 секунд
// Ждем завершения всех воркеров или таймаута
select {
case <-done:
logger.Info("All workers stopped gracefully")
case <-time.After(10 * time.Second):
case <-time.After(ForceShutdownTimeout * time.Second):
logger.Warn("Timeout reached, forcing shutdown")
}