package app import ( "context" "github.com/gin-gonic/gin" log "github.com/sirupsen/logrus" "google.golang.org/grpc" "merch-parser-api/internal/interfaces" "net" "net/http" "time" ) type App struct { host string address string apiPrefix string modules []interfaces.Module routerHandler interfaces.Router router *gin.Engine grpcServer *grpc.Server grpcServerPort string grpcClientPort string } type Deps struct { Host string Port string ApiPrefix string Modules []interfaces.Module RouterHandler interfaces.Router GrpcServer *grpc.Server GrpcServerPort string GrpcClientPort string } func NewApp(deps Deps) *App { app := &App{ host: deps.Host, address: deps.Host + ":" + deps.Port, apiPrefix: deps.ApiPrefix, routerHandler: deps.RouterHandler, modules: deps.Modules, grpcServer: deps.GrpcServer, grpcServerPort: deps.GrpcServerPort, grpcClientPort: deps.GrpcClientPort, } app.router = app.routerHandler.Set() apiRoutes := app.router.Group(app.apiPrefix) apiRoutes.GET("/", func(c *gin.Context) { c.String(http.StatusOK, "API is ready") }) for _, m := range app.modules { if hasRoutes, ok := m.(interfaces.ModuleRoutes); ok { hasRoutes.RegisterRoutes(apiRoutes, app.routerHandler.AuthMW(), app.routerHandler.RefreshMW()) } } return app } func (a *App) Run(ctx context.Context) error { server := &http.Server{ Addr: a.address, Handler: a.router, } serverErr := make(chan error, 1) go func() { log.Info("Starting server on: ", a.address) serverErr <- server.ListenAndServe() }() go func() { listener, err := net.Listen("tcp", net.JoinHostPort(a.host, a.grpcServerPort)) if err != nil { log.WithField("err", err).Fatal("gRPC Server | Listener") } err = a.grpcServer.Serve(listener) if err != nil { log.WithField("err", err).Fatal("gRPC Server | Serve") } }() log.Info("Starting gRPC server on port: ", a.grpcServerPort) select { case <-ctx.Done(): log.Info("Shutting down server") shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() return server.Shutdown(shutdownCtx) case err := <-serverErr: return err } }