package app import ( "context" "github.com/gin-gonic/gin" "github.com/jackc/pgx/v5/pgxpool" log "github.com/sirupsen/logrus" "merch-api/config" "merch-api/internal/merch" "merch-api/internal/task" "merch-api/internal/user" "merch-api/pkg/dbase" "merch-api/pkg/router" "merch-api/pkg/utils" "time" ) const pkgLogHeader string = "Application |" type App struct { cfg config.Config router *router.Router modules []Module dbPool *pgxpool.Pool tasker *task.Handler } func New(ctx context.Context, cfg config.Config) *App { //providers u := utils.New() dbPool, err := dbase.ConnectPool(ctx, dbase.Deps{ Host: cfg.DBase.Host, Port: cfg.DBase.Port, Username: cfg.DBase.Username, Password: cfg.DBase.Password, DBName: cfg.DBase.DBName, }) if err != nil { log.WithError(err).Fatalf("%v failed to connect database", pkgLogHeader) } //providers with deps userProv := user.New(user.Deps{ DB: dbPool, Utils: u, }) r := router.NewRouter(router.Deps{ Host: cfg.Http.Host, Port: cfg.Http.Port, Prefix: cfg.Http.Prefix, GinMode: cfg.Http.GinMode, UserProvider: userProv, }) //modules var modules []Module m := merch.New(merch.Deps{ DB: dbPool, Utils: u, }) modules = append(modules, m) tasker := task.New(task.Deps{ Addr: "", MerchProvider: m, }) return &App{ cfg: cfg, router: r, modules: modules, dbPool: dbPool, tasker: tasker, } } func (app *App) Run(ctx context.Context) error { log.Infof("%v starting...", pkgLogHeader) baseGroup := app.router.BaseGroup() app.collectRoutes(baseGroup) errCh := make(chan error, 10) go func() { if err := app.router.Run(); err != nil { errCh <- err } }() go func() { if err := app.tasker.Serve(); err != nil { errCh <- err } }() select { case <-ctx.Done(): app.shutdown(ctx) case err := <-errCh: return err } return nil } func (app *App) shutdown(ctx context.Context) { log.Infof("%v shutting down...", pkgLogHeader) shutdownCtx, shutdownCancel := context.WithTimeout(ctx, 15*time.Second) defer shutdownCancel() app.dbPool.Close() if err := app.router.Shutdown(shutdownCtx); err != nil { log.WithError(err).Warnf("%v error shutting down application", pkgLogHeader) } app.tasker.Shutdown() log.Infof("%v shutdown complete", pkgLogHeader) } func (app *App) collectRoutes(group *gin.RouterGroup) { for _, m := range app.modules { m.RegisterRoutes(group) } log.Infof("%v routes registered", pkgLogHeader) }