123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- package app
- import (
- "context"
- "fmt"
- "net/http"
- "os"
- "os/signal"
- "strconv"
- "sync"
- "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 // formerly appModule
- blueprintModule *BlueprintModule // formerly templateModule
- deploymentModule *DeploymentModule
- // Resource Handlers
- providerHandler *handlers.ProviderHandler
- // ticketHandler *handlers.TicketHandler
- stopped bool
- wg sync.WaitGroup
- // 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
- Service *services.ComponentService
- Handler *handlers.ComponentHandler
- }
- type BlueprintModule struct {
- Store *dbstore.BlueprintStore
- Service *services.BlueprintService
- Handler *handlers.BlueprintHandler
- }
- 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()
- // Disable automatic redirection of trailing slashes
- // This prevents 301 redirects that can cause CORS issues
- app.rtr.RedirectTrailingSlash = false
- app.rtr.RedirectFixedPath = false
- app.rtr.Use(gin.Recovery())
- app.rtr.Use(mw.Logger)
- // Add CORS middleware to handle cross-origin requests
- app.rtr.Use(mw.CORS())
- // 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(":%s", strconv.Itoa(a.cnf.Server.Port)),
- Handler: a.rtr,
- }
- go func() {
- a.entry.WithField("address", srv.Addr).Info("Starting server on port " + strconv.Itoa(a.cnf.Server.Port))
- // 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
- }
|