diff --git a/internal/app/app.go b/internal/app/app.go new file mode 100644 index 0000000..1d685af --- /dev/null +++ b/internal/app/app.go @@ -0,0 +1,19 @@ +package app + +import ( + "mal/internal/database" + "mal/internal/server" + + "github.com/gin-gonic/gin" + "go.uber.org/fx" +) + +func NewApp() *fx.App { + return fx.New( + database.Module, + server.Module, + fx.Invoke(func(r *gin.Engine, registers []server.RouteRegister) { + server.RegisterRoutes(r, registers) + }), + ) +} diff --git a/internal/server/server.go b/internal/server/server.go new file mode 100644 index 0000000..42ddbaa --- /dev/null +++ b/internal/server/server.go @@ -0,0 +1,74 @@ +package server + +import ( + "context" + "fmt" + "log" + "net/http" + "os" + + "github.com/gin-gonic/gin" + "go.uber.org/fx" +) + +var Module = fx.Options( + fx.Provide(ProvideRouter), + fx.Invoke(RunServer), +) + +func ProvideRouter() *gin.Engine { + if os.Getenv("GIN_MODE") == "" { + gin.SetMode(gin.ReleaseMode) + } + r := gin.New() + r.Use(gin.Logger(), gin.Recovery()) + return r +} + +func RunServer(lifecycle fx.Lifecycle, r *gin.Engine) { + port := os.Getenv("PORT") + if port == "" { + port = "3000" + } + + srv := &http.Server{ + Addr: ":" + port, + Handler: r, + } + + lifecycle.Append(fx.Hook{ + OnStart: func(context.Context) error { + log.Printf("Starting server on http://localhost:%s", port) + go func() { + if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { + log.Fatalf("listen: %s\n", err) + } + }() + return nil + }, + OnStop: func(ctx context.Context) error { + log.Println("Shutting down server...") + return srv.Shutdown(ctx) + }, + }) +} + +// RouteRegister is an interface that modules can implement to register their routes. +type RouteRegister interface { + Register(r *gin.Engine) +} + +func RegisterRoutes(r *gin.Engine, registers []RouteRegister) { + for _, reg := range registers { + reg.Register(r) + } +} + +// AsRouteRegister is a helper to provide a RouteRegister to the fx group. +func AsRouteRegister(f any) any { + return fx.Annotate( + f, + fx.As(new(RouteRegister)), + fx.ResultTags(`group:"routes"`), + ) +}