package app import ( "context" "errors" "fmt" "net/http" "os" "os/signal" "syscall" "time" "github.com/rs/zerolog/log" "github.com/TelegramExchange/pkg/postgres" "github.com/TelegramExchange/pkg/telegram" "github.com/TelegramExchange/pkg/transaction" "github.com/TelegramExchange/tgex-backend/tg_parser/config" "github.com/TelegramExchange/tgex-backend/tg_parser/internal/adapter/database" tgadapter "github.com/TelegramExchange/tgex-backend/tg_parser/internal/adapter/telegram" "github.com/TelegramExchange/tgex-backend/tg_parser/internal/controller/httpserver" "github.com/TelegramExchange/tgex-backend/tg_parser/internal/controller/worker" "github.com/TelegramExchange/tgex-backend/tg_parser/internal/usecase" ) func Run(ctx context.Context, c config.Config) error { // Telegram client tgClient, err := telegram.New(c.Telegram) if err != nil { return fmt.Errorf("telegram.New: %w", err) } // PostgreSQL pgPool, err := postgres.New(ctx, c.Postgres) if err != nil { return fmt.Errorf("broker.New: %w", err) } defer pgPool.Close() transaction.Init(pgPool) // Adapters tg := tgadapter.New(tgClient) db := database.New() // UseCase uc := usecase.New(tg, db) // Controllers channelWorker := worker.NewChannelWorker(uc, c.ChannelWorker) viewsWorker := worker.NewViewsWorker(uc, c.ViewsWorker) httpServer := httpserver.New(uc, c.HTTP.Addr) serverErr := make(chan error, 1) go func() { err := httpServer.ListenAndServe() if err != nil && !errors.Is(err, http.ErrServerClosed) { serverErr <- err } }() log.Info().Str("addr", c.HTTP.Addr).Msg("HTTP server started") log.Info().Msg("App started") sig := make(chan os.Signal, 1) signal.Notify(sig, os.Interrupt, syscall.SIGTERM) select { case <-sig: case err := <-serverErr: return fmt.Errorf("http server: %w", err) } log.Info().Msg("App got signal to stop") // Controllers viewsWorker.Stop() channelWorker.Stop() ctxShutdown, cancel := context.WithTimeout(ctx, 5*time.Second) defer cancel() if err := httpServer.Shutdown(ctxShutdown); err != nil { log.Error().Err(err).Msg("HTTP server shutdown failed") } // Adapters tgClient.Close() log.Info().Msg("App stopped") return nil }