diff --git a/internal/controller/tg/tg.go b/internal/controller/tg/tg.go index a7f613d..86ca06e 100644 --- a/internal/controller/tg/tg.go +++ b/internal/controller/tg/tg.go @@ -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) { diff --git a/main.go b/main.go index a8e4326..24f8fa0 100644 --- a/main.go +++ b/main.go @@ -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") }