Initial commit: Basic project structure and dependencies
This commit is contained in:
441
internal/container/container.go
Normal file
441
internal/container/container.go
Normal file
@@ -0,0 +1,441 @@
|
||||
package container
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/redis/go-redis/v9"
|
||||
"go.uber.org/fx"
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"tyapi-server/internal/config"
|
||||
"tyapi-server/internal/domains/user/handlers"
|
||||
"tyapi-server/internal/domains/user/repositories"
|
||||
"tyapi-server/internal/domains/user/routes"
|
||||
"tyapi-server/internal/domains/user/services"
|
||||
"tyapi-server/internal/shared/cache"
|
||||
"tyapi-server/internal/shared/database"
|
||||
"tyapi-server/internal/shared/events"
|
||||
"tyapi-server/internal/shared/health"
|
||||
"tyapi-server/internal/shared/http"
|
||||
"tyapi-server/internal/shared/interfaces"
|
||||
"tyapi-server/internal/shared/middleware"
|
||||
)
|
||||
|
||||
// Container 应用容器
|
||||
type Container struct {
|
||||
App *fx.App
|
||||
}
|
||||
|
||||
// NewContainer 创建新的应用容器
|
||||
func NewContainer() *Container {
|
||||
app := fx.New(
|
||||
// 配置模块
|
||||
fx.Provide(
|
||||
config.LoadConfig,
|
||||
),
|
||||
|
||||
// 基础设施模块
|
||||
fx.Provide(
|
||||
NewLogger,
|
||||
NewDatabase,
|
||||
NewRedisClient,
|
||||
NewRedisCache,
|
||||
NewEventBus,
|
||||
NewHealthChecker,
|
||||
),
|
||||
|
||||
// HTTP基础组件
|
||||
fx.Provide(
|
||||
NewResponseBuilder,
|
||||
NewRequestValidator,
|
||||
NewGinRouter,
|
||||
),
|
||||
|
||||
// 中间件组件
|
||||
fx.Provide(
|
||||
NewRequestIDMiddleware,
|
||||
NewSecurityHeadersMiddleware,
|
||||
NewResponseTimeMiddleware,
|
||||
NewCORSMiddleware,
|
||||
NewRateLimitMiddleware,
|
||||
NewRequestLoggerMiddleware,
|
||||
NewJWTAuthMiddleware,
|
||||
NewOptionalAuthMiddleware,
|
||||
),
|
||||
|
||||
// 用户域组件
|
||||
fx.Provide(
|
||||
NewUserRepository,
|
||||
NewUserService,
|
||||
NewUserHandler,
|
||||
NewUserRoutes,
|
||||
),
|
||||
|
||||
// 应用生命周期
|
||||
fx.Invoke(
|
||||
RegisterLifecycleHooks,
|
||||
RegisterMiddlewares,
|
||||
RegisterRoutes,
|
||||
),
|
||||
)
|
||||
|
||||
return &Container{App: app}
|
||||
}
|
||||
|
||||
// Start 启动容器
|
||||
func (c *Container) Start() error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
return c.App.Start(ctx)
|
||||
}
|
||||
|
||||
// Stop 停止容器
|
||||
func (c *Container) Stop() error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
return c.App.Stop(ctx)
|
||||
}
|
||||
|
||||
// 基础设施构造函数
|
||||
|
||||
// NewLogger 创建日志器
|
||||
func NewLogger(cfg *config.Config) (*zap.Logger, error) {
|
||||
level, err := zap.ParseAtomicLevel(cfg.Logger.Level)
|
||||
if err != nil {
|
||||
level = zap.NewAtomicLevelAt(zap.InfoLevel)
|
||||
}
|
||||
|
||||
config := zap.Config{
|
||||
Level: level,
|
||||
Development: cfg.App.IsDevelopment(),
|
||||
Encoding: cfg.Logger.Format,
|
||||
EncoderConfig: zap.NewProductionEncoderConfig(),
|
||||
OutputPaths: []string{cfg.Logger.Output},
|
||||
ErrorOutputPaths: []string{"stderr"},
|
||||
}
|
||||
|
||||
if cfg.Logger.Format == "" {
|
||||
config.Encoding = "json"
|
||||
}
|
||||
if cfg.Logger.Output == "" {
|
||||
config.OutputPaths = []string{"stdout"}
|
||||
}
|
||||
|
||||
return config.Build()
|
||||
}
|
||||
|
||||
// NewDatabase 创建数据库连接
|
||||
func NewDatabase(cfg *config.Config, logger *zap.Logger) (*gorm.DB, error) {
|
||||
dbConfig := database.Config{
|
||||
Host: cfg.Database.Host,
|
||||
Port: cfg.Database.Port,
|
||||
User: cfg.Database.User,
|
||||
Password: cfg.Database.Password,
|
||||
Name: cfg.Database.Name,
|
||||
SSLMode: cfg.Database.SSLMode,
|
||||
Timezone: cfg.Database.Timezone,
|
||||
MaxOpenConns: cfg.Database.MaxOpenConns,
|
||||
MaxIdleConns: cfg.Database.MaxIdleConns,
|
||||
ConnMaxLifetime: cfg.Database.ConnMaxLifetime,
|
||||
}
|
||||
|
||||
db, err := database.NewConnection(dbConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return db.DB, nil
|
||||
}
|
||||
|
||||
// NewRedisClient 创建Redis客户端
|
||||
func NewRedisClient(cfg *config.Config, logger *zap.Logger) (*redis.Client, error) {
|
||||
client := redis.NewClient(&redis.Options{
|
||||
Addr: cfg.Redis.GetRedisAddr(),
|
||||
Password: cfg.Redis.Password,
|
||||
DB: cfg.Redis.DB,
|
||||
PoolSize: cfg.Redis.PoolSize,
|
||||
MinIdleConns: cfg.Redis.MinIdleConns,
|
||||
DialTimeout: cfg.Redis.DialTimeout,
|
||||
ReadTimeout: cfg.Redis.ReadTimeout,
|
||||
WriteTimeout: cfg.Redis.WriteTimeout,
|
||||
})
|
||||
|
||||
// 测试连接
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
_, err := client.Ping(ctx).Result()
|
||||
if err != nil {
|
||||
logger.Error("Failed to connect to Redis", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
logger.Info("Redis connection established")
|
||||
return client, nil
|
||||
}
|
||||
|
||||
// NewRedisCache 创建Redis缓存服务
|
||||
func NewRedisCache(client *redis.Client, logger *zap.Logger, cfg *config.Config) interfaces.CacheService {
|
||||
return cache.NewRedisCache(client, logger, "app")
|
||||
}
|
||||
|
||||
// NewEventBus 创建事件总线
|
||||
func NewEventBus(logger *zap.Logger, cfg *config.Config) interfaces.EventBus {
|
||||
return events.NewMemoryEventBus(logger, 5) // 默认5个工作协程
|
||||
}
|
||||
|
||||
// NewHealthChecker 创建健康检查器
|
||||
func NewHealthChecker(logger *zap.Logger) *health.HealthChecker {
|
||||
return health.NewHealthChecker(logger)
|
||||
}
|
||||
|
||||
// HTTP组件构造函数
|
||||
|
||||
// NewResponseBuilder 创建响应构建器
|
||||
func NewResponseBuilder() interfaces.ResponseBuilder {
|
||||
return http.NewResponseBuilder()
|
||||
}
|
||||
|
||||
// NewRequestValidator 创建请求验证器
|
||||
func NewRequestValidator(response interfaces.ResponseBuilder) interfaces.RequestValidator {
|
||||
return http.NewRequestValidator(response)
|
||||
}
|
||||
|
||||
// NewGinRouter 创建Gin路由器
|
||||
func NewGinRouter(cfg *config.Config, logger *zap.Logger) *http.GinRouter {
|
||||
return http.NewGinRouter(cfg, logger)
|
||||
}
|
||||
|
||||
// 中间件构造函数
|
||||
|
||||
// NewRequestIDMiddleware 创建请求ID中间件
|
||||
func NewRequestIDMiddleware() *middleware.RequestIDMiddleware {
|
||||
return middleware.NewRequestIDMiddleware()
|
||||
}
|
||||
|
||||
// NewSecurityHeadersMiddleware 创建安全头部中间件
|
||||
func NewSecurityHeadersMiddleware() *middleware.SecurityHeadersMiddleware {
|
||||
return middleware.NewSecurityHeadersMiddleware()
|
||||
}
|
||||
|
||||
// NewResponseTimeMiddleware 创建响应时间中间件
|
||||
func NewResponseTimeMiddleware() *middleware.ResponseTimeMiddleware {
|
||||
return middleware.NewResponseTimeMiddleware()
|
||||
}
|
||||
|
||||
// NewCORSMiddleware 创建CORS中间件
|
||||
func NewCORSMiddleware(cfg *config.Config) *middleware.CORSMiddleware {
|
||||
return middleware.NewCORSMiddleware(cfg)
|
||||
}
|
||||
|
||||
// NewRateLimitMiddleware 创建限流中间件
|
||||
func NewRateLimitMiddleware(cfg *config.Config) *middleware.RateLimitMiddleware {
|
||||
return middleware.NewRateLimitMiddleware(cfg)
|
||||
}
|
||||
|
||||
// NewRequestLoggerMiddleware 创建请求日志中间件
|
||||
func NewRequestLoggerMiddleware(logger *zap.Logger) *middleware.RequestLoggerMiddleware {
|
||||
return middleware.NewRequestLoggerMiddleware(logger)
|
||||
}
|
||||
|
||||
// NewJWTAuthMiddleware 创建JWT认证中间件
|
||||
func NewJWTAuthMiddleware(cfg *config.Config, logger *zap.Logger) *middleware.JWTAuthMiddleware {
|
||||
return middleware.NewJWTAuthMiddleware(cfg, logger)
|
||||
}
|
||||
|
||||
// NewOptionalAuthMiddleware 创建可选认证中间件
|
||||
func NewOptionalAuthMiddleware(jwtAuth *middleware.JWTAuthMiddleware) *middleware.OptionalAuthMiddleware {
|
||||
return middleware.NewOptionalAuthMiddleware(jwtAuth)
|
||||
}
|
||||
|
||||
// 用户域构造函数
|
||||
|
||||
// NewUserRepository 创建用户仓储
|
||||
func NewUserRepository(db *gorm.DB, cache interfaces.CacheService, logger *zap.Logger) *repositories.UserRepository {
|
||||
return repositories.NewUserRepository(db, cache, logger)
|
||||
}
|
||||
|
||||
// NewUserService 创建用户服务
|
||||
func NewUserService(
|
||||
repo *repositories.UserRepository,
|
||||
eventBus interfaces.EventBus,
|
||||
logger *zap.Logger,
|
||||
) *services.UserService {
|
||||
return services.NewUserService(repo, eventBus, logger)
|
||||
}
|
||||
|
||||
// NewUserHandler 创建用户处理器
|
||||
func NewUserHandler(
|
||||
userService *services.UserService,
|
||||
response interfaces.ResponseBuilder,
|
||||
validator interfaces.RequestValidator,
|
||||
logger *zap.Logger,
|
||||
jwtAuth *middleware.JWTAuthMiddleware,
|
||||
) *handlers.UserHandler {
|
||||
return handlers.NewUserHandler(userService, response, validator, logger, jwtAuth)
|
||||
}
|
||||
|
||||
// NewUserRoutes 创建用户路由
|
||||
func NewUserRoutes(
|
||||
handler *handlers.UserHandler,
|
||||
jwtAuth *middleware.JWTAuthMiddleware,
|
||||
optionalAuth *middleware.OptionalAuthMiddleware,
|
||||
) *routes.UserRoutes {
|
||||
return routes.NewUserRoutes(handler, jwtAuth, optionalAuth)
|
||||
}
|
||||
|
||||
// 注册函数
|
||||
|
||||
// RegisterMiddlewares 注册中间件
|
||||
func RegisterMiddlewares(
|
||||
router *http.GinRouter,
|
||||
requestID *middleware.RequestIDMiddleware,
|
||||
security *middleware.SecurityHeadersMiddleware,
|
||||
responseTime *middleware.ResponseTimeMiddleware,
|
||||
cors *middleware.CORSMiddleware,
|
||||
rateLimit *middleware.RateLimitMiddleware,
|
||||
requestLogger *middleware.RequestLoggerMiddleware,
|
||||
) {
|
||||
// 注册全局中间件
|
||||
router.RegisterMiddleware(requestID)
|
||||
router.RegisterMiddleware(security)
|
||||
router.RegisterMiddleware(responseTime)
|
||||
router.RegisterMiddleware(cors)
|
||||
router.RegisterMiddleware(rateLimit)
|
||||
router.RegisterMiddleware(requestLogger)
|
||||
}
|
||||
|
||||
// RegisterRoutes 注册路由
|
||||
func RegisterRoutes(
|
||||
router *http.GinRouter,
|
||||
userRoutes *routes.UserRoutes,
|
||||
) {
|
||||
// 设置默认路由
|
||||
router.SetupDefaultRoutes()
|
||||
|
||||
// 注册用户路由
|
||||
userRoutes.RegisterRoutes(router.GetEngine())
|
||||
userRoutes.RegisterPublicRoutes(router.GetEngine())
|
||||
userRoutes.RegisterAdminRoutes(router.GetEngine())
|
||||
userRoutes.RegisterHealthRoutes(router.GetEngine())
|
||||
|
||||
// 打印路由信息
|
||||
router.PrintRoutes()
|
||||
}
|
||||
|
||||
// 生命周期钩子
|
||||
|
||||
// RegisterLifecycleHooks 注册生命周期钩子
|
||||
func RegisterLifecycleHooks(
|
||||
lc fx.Lifecycle,
|
||||
logger *zap.Logger,
|
||||
cfg *config.Config,
|
||||
db *gorm.DB,
|
||||
cache interfaces.CacheService,
|
||||
eventBus interfaces.EventBus,
|
||||
healthChecker *health.HealthChecker,
|
||||
router *http.GinRouter,
|
||||
userService *services.UserService,
|
||||
) {
|
||||
lc.Append(fx.Hook{
|
||||
OnStart: func(ctx context.Context) error {
|
||||
logger.Info("Starting application services...")
|
||||
|
||||
// 注册服务到健康检查器
|
||||
healthChecker.RegisterService(userService)
|
||||
|
||||
// 初始化缓存服务
|
||||
if err := cache.Initialize(ctx); err != nil {
|
||||
logger.Error("Failed to initialize cache", zap.Error(err))
|
||||
return err
|
||||
}
|
||||
|
||||
// 启动事件总线
|
||||
if err := eventBus.Start(ctx); err != nil {
|
||||
logger.Error("Failed to start event bus", zap.Error(err))
|
||||
return err
|
||||
}
|
||||
|
||||
// 启动健康检查(如果启用)
|
||||
if cfg.Health.Enabled {
|
||||
go healthChecker.StartPeriodicCheck(ctx, cfg.Health.Interval)
|
||||
}
|
||||
|
||||
// 启动HTTP服务器
|
||||
go func() {
|
||||
addr := fmt.Sprintf("%s:%s", cfg.Server.Host, cfg.Server.Port)
|
||||
if err := router.Start(addr); err != nil {
|
||||
logger.Error("Failed to start HTTP server", zap.Error(err))
|
||||
}
|
||||
}()
|
||||
|
||||
logger.Info("All services started successfully")
|
||||
return nil
|
||||
},
|
||||
OnStop: func(ctx context.Context) error {
|
||||
logger.Info("Stopping application services...")
|
||||
|
||||
// 停止HTTP服务器
|
||||
if err := router.Stop(ctx); err != nil {
|
||||
logger.Error("Failed to stop HTTP server", zap.Error(err))
|
||||
}
|
||||
|
||||
// 停止事件总线
|
||||
if err := eventBus.Stop(ctx); err != nil {
|
||||
logger.Error("Failed to stop event bus", zap.Error(err))
|
||||
}
|
||||
|
||||
// 关闭缓存服务
|
||||
if err := cache.Shutdown(ctx); err != nil {
|
||||
logger.Error("Failed to shutdown cache service", zap.Error(err))
|
||||
}
|
||||
|
||||
// 关闭数据库连接
|
||||
if sqlDB, err := db.DB(); err == nil {
|
||||
if err := sqlDB.Close(); err != nil {
|
||||
logger.Error("Failed to close database", zap.Error(err))
|
||||
}
|
||||
}
|
||||
|
||||
logger.Info("All services stopped")
|
||||
return nil
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// ServiceRegistrar 服务注册器接口
|
||||
type ServiceRegistrar interface {
|
||||
RegisterServices() fx.Option
|
||||
}
|
||||
|
||||
// DomainModule 领域模块接口
|
||||
type DomainModule interface {
|
||||
ServiceRegistrar
|
||||
GetName() string
|
||||
GetDependencies() []string
|
||||
}
|
||||
|
||||
// RegisterDomainModule 注册领域模块
|
||||
func RegisterDomainModule(module DomainModule) fx.Option {
|
||||
return fx.Options(
|
||||
fx.Provide(
|
||||
fx.Annotated{
|
||||
Name: module.GetName(),
|
||||
Target: func() DomainModule {
|
||||
return module
|
||||
},
|
||||
},
|
||||
),
|
||||
module.RegisterServices(),
|
||||
)
|
||||
}
|
||||
|
||||
// GetContainer 获取容器实例(用于测试或特殊情况)
|
||||
func GetContainer(cfg *config.Config) *Container {
|
||||
return NewContainer()
|
||||
}
|
||||
Reference in New Issue
Block a user