package app import ( "context" "errors" "gitea.pena/SQuiz/storer/internal/initialize" "gitea.pena/SQuiz/storer/internal/server/http" "gitea.pena/SQuiz/storer/pkg/closer" "github.com/gofiber/fiber/v2/log" "go.uber.org/zap" "time" ) var zapOptions = []zap.Option{ zap.AddCaller(), zap.AddCallerSkip(2), zap.AddStacktrace(zap.ErrorLevel), } func Run(ctx context.Context, cfg initialize.Config) error { var ( err error zapLogger *zap.Logger ) defer func() { if r := recover(); r != nil { log.Error("Recovered from a panic", zap.Any("error", r)) } }() ctx, cancel := context.WithCancel(ctx) defer cancel() if cfg.LoggerProdMode { zapLogger, err = zap.NewProduction(zapOptions...) if err != nil { return err } } else { zapLogger, err = zap.NewDevelopment(zapOptions...) if err != nil { return err } } shutdownGroup := closer.NewCloserGroup() minioClient, err := initialize.NewMinio(cfg) if err != nil { zapLogger.Error("Error initializing minio", zap.Error(err)) return err } dalS, err := initialize.NewDALs(ctx, cfg, minioClient) if err != nil { zapLogger.Error("Error initializing dals", zap.Error(err)) } controllers := initialize.NewControllers(initialize.ControllerDeps{ DALs: dalS, }) srv := http.NewServer(http.ServerConfig{ Logger: zapLogger, Controllers: []http.Controller{controllers.HttpControllers.QuizFiles}, }) go func() { if err := srv.Start(cfg.ClientHttpURL); err != nil { zapLogger.Error("HTTP server startup error", zap.Error(err)) cancel() } }() srv.ListRoutes() shutdownGroup.Add(closer.CloserFunc(srv.Shutdown)) shutdownGroup.Add(closer.CloserFunc(dalS.PgDAL.Close)) <-ctx.Done() timeoutCtx, timeoutCancel := context.WithTimeout(context.Background(), 10*time.Second) defer timeoutCancel() if err := shutdownGroup.Call(timeoutCtx); err != nil { if errors.Is(err, context.DeadlineExceeded) { zapLogger.Error("Shutdown timed out", zap.Error(err)) } else { zapLogger.Error("Failed to shutdown services gracefully", zap.Error(err)) } return err } zapLogger.Info("Application has stopped") return nil }