diff --git a/BACKEND_BLUEPRINT.md b/BACKEND_BLUEPRINT.md index 52245a9..e84f04c 100644 --- a/BACKEND_BLUEPRINT.md +++ b/BACKEND_BLUEPRINT.md @@ -98,11 +98,17 @@ - `emit_interface: true` (generated `Querier` interface) - `emit_json_tags: false` (can be revisited if API structs are returned directly) - Initial queries implemented for users: `GetUser`, `CreateUser`, `DeleteUser` -- **Goose startup migrations** have been wired into `cmd/api/main.go`, utilizing the `embed.FS` strategy and logging via Zap adapter. -- DB pool is successfully wired in `cmd/api`. -- Environment-aware Zap logger is configured (development vs production). -- **fx DI wiring** is being introduced to replace manual dependency injection in `main.go`. HTTP layer will use domain handlers structured by route hierarchy (`internal/http/api/...`). -- **Next Planned:** Implement fx providers for Gin server and DB pool, build `internal/http/server.go`, `internal/http/router.go`, and initial domain handlers (`health`, `auth`). +- **Goose startup migrations** wired into `db.ProvidePool`, utilizing the `embed.FS` strategy. +- **fx DI fully implemented.** All dependencies are provided via `fx.Provide` constructors: + - `config.Provide` → `*Config` + - `logger.NewFromConfig` → `*zap.SugaredLogger` + - `db.ProvidePool` → `*pgxpool.Pool` (lifecycle hooks for graceful shutdown) + - `http.NewServer` → `*gin.Engine` (lifecycle hooks for startup/shutdown) + - `health.NewHandler` → `*health.Handler` +- **HTTP route hierarchy** via `internal/http/router.go` (`GlueRoutes`): + - `GET /api/health/live` - process is alive + - `GET /api/health/ready` - DB ping succeeds +- **Next Planned:** Auth handler (`/api/auth/login`, `/api/auth/register`), JWT middleware, service layer. --- diff --git a/cmd/api/main.go b/cmd/api/main.go index 55d5bc0..edf5219 100644 --- a/cmd/api/main.go +++ b/cmd/api/main.go @@ -7,13 +7,15 @@ import ( "git.kanopo.dev/rhythm/rhythm-backend/internal/http/api/health" "git.kanopo.dev/rhythm/rhythm-backend/internal/logger" "go.uber.org/fx" + "go.uber.org/fx/fxevent" + "go.uber.org/zap" ) func main() { fx.New( fx.Provide( config.Provide, - logger.NewFromConfig, + logger.ProvideLogger, db.ProvidePool, http.NewServer, health.NewHandler, @@ -21,5 +23,8 @@ func main() { fx.Invoke( http.GlueRoutes, ), + fx.WithLogger(func(logger *zap.Logger) fxevent.Logger { + return &fxevent.ZapLogger{Logger: logger} + }), ).Run() } diff --git a/internal/logger/logger.go b/internal/logger/logger.go index f9e53b0..42aa18f 100644 --- a/internal/logger/logger.go +++ b/internal/logger/logger.go @@ -1,13 +1,14 @@ package logger import ( - "go.uber.org/zap" "log" + "go.uber.org/zap" + "git.kanopo.dev/rhythm/rhythm-backend/internal/config" ) -func New(env string) *zap.SugaredLogger { +func New(env string) (*zap.Logger, *zap.SugaredLogger) { var zapLogger *zap.Logger var err error @@ -21,10 +22,10 @@ func New(env string) *zap.SugaredLogger { log.Fatalf("failed to initialize zap logger: %v", err) } - return zapLogger.Sugar() + return zapLogger, zapLogger.Sugar() } -func NewFromConfig(cfg *config.Config) *zap.SugaredLogger { +func ProvideLogger(cfg *config.Config) (*zap.Logger, *zap.SugaredLogger) { return New(cfg.AppEnv) }