feature/epic1-core-infrastructure #2
@@ -7,15 +7,24 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
|
|
||||||
"git.dcentral.systems/toolz/goplt/internal/di"
|
"git.dcentral.systems/toolz/goplt/internal/di"
|
||||||
|
"git.dcentral.systems/toolz/goplt/internal/infra/database"
|
||||||
|
"git.dcentral.systems/toolz/goplt/internal/server"
|
||||||
"git.dcentral.systems/toolz/goplt/pkg/logger"
|
"git.dcentral.systems/toolz/goplt/pkg/logger"
|
||||||
"go.uber.org/fx"
|
"go.uber.org/fx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// Create DI container with lifecycle hooks
|
// Create DI container with lifecycle hooks
|
||||||
|
// We need to invoke the HTTP server to ensure all providers execute
|
||||||
container := di.NewContainer(
|
container := di.NewContainer(
|
||||||
// Invoke lifecycle hooks
|
// Invoke lifecycle hooks
|
||||||
fx.Invoke(di.RegisterLifecycleHooks),
|
fx.Invoke(di.RegisterLifecycleHooks),
|
||||||
|
// Force HTTP server to be created (which triggers all dependencies)
|
||||||
|
// This ensures database, health, metrics, etc. are all created
|
||||||
|
fx.Invoke(func(srv *server.Server, dbClient *database.Client) {
|
||||||
|
// Both server and database are created, hooks are registered
|
||||||
|
// This ensures all providers execute
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
// Create root context
|
// Create root context
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
environment: development
|
environment: development
|
||||||
|
|
||||||
server:
|
server:
|
||||||
port: 8080
|
port: 3000
|
||||||
host: "0.0.0.0"
|
host: "0.0.0.0"
|
||||||
read_timeout: 30s
|
read_timeout: 30s
|
||||||
write_timeout: 30s
|
write_timeout: 30s
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ func ProvideDatabase() fx.Option {
|
|||||||
return fx.Provide(func(cfg config.ConfigProvider, log logger.Logger, lc fx.Lifecycle) (*database.Client, error) {
|
return fx.Provide(func(cfg config.ConfigProvider, log logger.Logger, lc fx.Lifecycle) (*database.Client, error) {
|
||||||
dsn := cfg.GetString("database.dsn")
|
dsn := cfg.GetString("database.dsn")
|
||||||
if dsn == "" {
|
if dsn == "" {
|
||||||
|
log.Error("ProvideDatabase: DSN is empty")
|
||||||
return nil, fmt.Errorf("database DSN is not configured")
|
return nil, fmt.Errorf("database DSN is not configured")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,6 +94,12 @@ func ProvideDatabase() fx.Option {
|
|||||||
connMaxIdleTime = 10 * time.Minute
|
connMaxIdleTime = 10 * time.Minute
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Info("Preparing database connection",
|
||||||
|
logger.String("dsn_mask", maskDSN(dsn)),
|
||||||
|
logger.Int("max_connections", maxConns),
|
||||||
|
)
|
||||||
|
|
||||||
|
log.Info("Connecting to database...")
|
||||||
dbClient, err := database.NewClient(database.Config{
|
dbClient, err := database.NewClient(database.Config{
|
||||||
DSN: dsn,
|
DSN: dsn,
|
||||||
MaxConnections: maxConns,
|
MaxConnections: maxConns,
|
||||||
@@ -101,14 +108,19 @@ func ProvideDatabase() fx.Option {
|
|||||||
ConnMaxIdleTime: connMaxIdleTime,
|
ConnMaxIdleTime: connMaxIdleTime,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Error("Failed to create database client",
|
||||||
|
logger.Error(err),
|
||||||
|
)
|
||||||
return nil, fmt.Errorf("failed to create database client: %w", err)
|
return nil, fmt.Errorf("failed to create database client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Info("Database client created successfully")
|
||||||
|
|
||||||
// Register lifecycle hooks
|
// Register lifecycle hooks
|
||||||
lc.Append(fx.Hook{
|
lc.Append(fx.Hook{
|
||||||
OnStart: func(ctx context.Context) error {
|
OnStart: func(ctx context.Context) error {
|
||||||
// Run migrations on startup
|
|
||||||
log.Info("Running database migrations...")
|
log.Info("Running database migrations...")
|
||||||
|
// Run migrations on startup
|
||||||
if err := dbClient.Migrate(ctx); err != nil {
|
if err := dbClient.Migrate(ctx); err != nil {
|
||||||
log.Error("Database migrations failed",
|
log.Error("Database migrations failed",
|
||||||
logger.Error(err),
|
logger.Error(err),
|
||||||
@@ -222,16 +234,22 @@ func ProvideHTTPServer() fx.Option {
|
|||||||
tracer trace.TracerProvider,
|
tracer trace.TracerProvider,
|
||||||
lc fx.Lifecycle,
|
lc fx.Lifecycle,
|
||||||
) (*server.Server, error) {
|
) (*server.Server, error) {
|
||||||
|
log.Info("Creating HTTP server...")
|
||||||
|
|
||||||
srv, err := server.NewServer(cfg, log, healthRegistry, metricsRegistry, errorBus, tracer)
|
srv, err := server.NewServer(cfg, log, healthRegistry, metricsRegistry, errorBus, tracer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Error("Failed to create HTTP server",
|
||||||
|
logger.Error(err),
|
||||||
|
)
|
||||||
return nil, fmt.Errorf("failed to create HTTP server: %w", err)
|
return nil, fmt.Errorf("failed to create HTTP server: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Info("HTTP server created, registering lifecycle hooks...")
|
||||||
|
|
||||||
// Register lifecycle hooks
|
// Register lifecycle hooks
|
||||||
lc.Append(fx.Hook{
|
lc.Append(fx.Hook{
|
||||||
OnStart: func(ctx context.Context) error {
|
OnStart: func(ctx context.Context) error {
|
||||||
log.Info("HTTP server OnStart hook called")
|
|
||||||
|
|
||||||
// Get server address from config
|
// Get server address from config
|
||||||
port := cfg.GetInt("server.port")
|
port := cfg.GetInt("server.port")
|
||||||
if port == 0 {
|
if port == 0 {
|
||||||
|
|||||||
Reference in New Issue
Block a user