package app import ( "context" "fmt" "net/http" "os" "os/signal" "syscall" "time" "git.linuxforward.com/byop/byop-engine/auth" "git.linuxforward.com/byop/byop-engine/config" "git.linuxforward.com/byop/byop-engine/dbmanager" "git.linuxforward.com/byop/byop-engine/dbstore" "git.linuxforward.com/byop/byop-engine/handlers" mw "git.linuxforward.com/byop/byop-engine/middleware" "git.linuxforward.com/byop/byop-engine/services" "github.com/gin-gonic/gin" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) type App struct { entry *logrus.Entry cnf *config.Config ctx context.Context cancelFunc context.CancelFunc rtr *gin.Engine // Database dbManager dbmanager.DbManager // Services authService auth.Service tokenStore auth.TokenStore // Modules authHandler *handlers.AuthHandler userModule *UserModule clientModule *ClientModule componentModule *ComponentModule // Renamed from appModule appModule *AppModule // Renamed from templateModule deploymentModule *DeploymentModule // Resource Handlers providerHandler *handlers.ProviderHandler // ticketHandler *handlers.TicketHandler // monitoringHandler *handlers.MonitoringHandler } type UserModule struct { Store *dbstore.UserStore Service *services.UserService Handler *handlers.UserHandler } type ClientModule struct { Store *dbstore.ClientStore Service *services.ClientService Handler *handlers.ClientHandler } type ComponentModule struct { Store *dbstore.ComponentStore // Renamed from AppStore Service *services.ComponentService // Renamed from AppService Handler *handlers.ComponentHandler // Renamed from AppHandler } type AppModule struct { Store *dbstore.AppStore // Renamed from TemplateStore Service *services.AppService // Renamed from TemplateService Handler *handlers.AppsHandler // Renamed from TemplateHandler } type DeploymentModule struct { Store *dbstore.DeploymentStore Service *services.DeploymentService Handler *handlers.DeploymentHandler } func NewApp(cnf *config.Config) (*App, error) { ctx, cancelFunc := context.WithCancel(context.Background()) app := &App{ entry: logrus.WithField("component", "app"), cnf: cnf, ctx: ctx, cancelFunc: cancelFunc, } // Initialize router first if cnf.Debug { gin.SetMode(gin.DebugMode) } else { // Set gin to release mode for production // This will disable debug logs and enable performance optimizations gin.SetMode(gin.ReleaseMode) } app.rtr = gin.New() app.rtr.Use(gin.Recovery()) app.rtr.Use(mw.Logger) // Initialize services and handlers if err := app.initCommonServices(); err != nil { return nil, errors.Wrap(err, "initialize services") } if err := app.initHandlers(); err != nil { return nil, errors.Wrap(err, "initialize handlers") } // Set up routes after all handlers are initialized app.setupRoutes() return app, nil } func (a *App) Run() error { srv := &http.Server{ Addr: fmt.Sprintf(":443"), Handler: a.rtr, } go func() { a.entry.WithField("address", srv.Addr).Info("Starting server on port 443 ") // Handle TLS if configured if a.cnf.Server.Tls.Enabled { a.entry.Info("Starting server with TLS...") err := srv.ListenAndServeTLS(a.cnf.Server.Tls.CertFile, a.cnf.Server.Tls.KeyFile) if err != nil && err != http.ErrServerClosed { a.entry.WithError(err).Fatal("Failed to start server") } } else { err := srv.ListenAndServe() if err != nil && err != http.ErrServerClosed { a.entry.WithError(err).Fatal("Failed to start server") } } a.entry.Info("Server stopped") }() quit := make(chan os.Signal, 1) signal.Notify(quit, os.Interrupt, syscall.SIGTERM) <-quit a.entry.Info("Stopping server...") ctxTimeout, cancelFunc := context.WithTimeout(context.Background(), 30*time.Second) defer cancelFunc() err := srv.Shutdown(ctxTimeout) if err != nil { return fmt.Errorf("shutdown server: %w", err) } a.entry.Info("Server stopped successfully") return nil }