Initial commit: Basic project structure and dependencies

This commit is contained in:
2025-06-30 19:21:56 +08:00
commit 03e615a8fd
50 changed files with 11664 additions and 0 deletions

View 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()
}