package app import ( "fmt" "os" "os/signal" "syscall" "go.uber.org/zap" "gorm.io/gorm" "tyapi-server/internal/config" "tyapi-server/internal/container" "tyapi-server/internal/domains/user/entities" ) // Application 应用程序结构 type Application struct { container *container.Container config *config.Config logger *zap.Logger } // NewApplication 创建新的应用程序实例 func NewApplication() (*Application, error) { // 加载配置 cfg, err := config.LoadConfig() if err != nil { return nil, fmt.Errorf("failed to load config: %w", err) } // 创建日志器 logger, err := createLogger(cfg) if err != nil { return nil, fmt.Errorf("failed to create logger: %w", err) } // 创建容器 cont := container.NewContainer() return &Application{ container: cont, config: cfg, logger: logger, }, nil } // Run 运行应用程序 func (a *Application) Run() error { // 打印启动信息 a.printBanner() // 启动容器 a.logger.Info("Starting application container...") if err := a.container.Start(); err != nil { a.logger.Error("Failed to start container", zap.Error(err)) return err } // 设置优雅关闭 a.setupGracefulShutdown() a.logger.Info("Application started successfully", zap.String("version", a.config.App.Version), zap.String("environment", a.config.App.Env), zap.String("port", a.config.Server.Port)) // 等待信号 return a.waitForShutdown() } // RunMigrations 运行数据库迁移 func (a *Application) RunMigrations() error { a.logger.Info("Running database migrations...") // 创建数据库连接 db, err := a.createDatabaseConnection() if err != nil { return fmt.Errorf("failed to create database connection: %w", err) } // 自动迁移 if err := a.autoMigrate(db); err != nil { return fmt.Errorf("failed to run migrations: %w", err) } a.logger.Info("Database migrations completed successfully") return nil } // printBanner 打印启动横幅 func (a *Application) printBanner() { banner := fmt.Sprintf(` ╔══════════════════════════════════════════════════════════════╗ ║ %s ║ ║ Version: %s ║ ║ Environment: %s ║ ║ Port: %s ║ ╚══════════════════════════════════════════════════════════════╝ `, a.config.App.Name, a.config.App.Version, a.config.App.Env, a.config.Server.Port, ) fmt.Println(banner) } // setupGracefulShutdown 设置优雅关闭 func (a *Application) setupGracefulShutdown() { c := make(chan os.Signal, 1) signal.Notify(c, os.Interrupt, syscall.SIGTERM) go func() { <-c a.logger.Info("Received shutdown signal, starting graceful shutdown...") // 停止容器 if err := a.container.Stop(); err != nil { a.logger.Error("Error during container shutdown", zap.Error(err)) } a.logger.Info("Application shutdown completed") os.Exit(0) }() } // waitForShutdown 等待关闭信号 func (a *Application) waitForShutdown() error { // 创建一个通道来等待关闭 done := make(chan bool, 1) // 启动一个协程来监听信号 go func() { c := make(chan os.Signal, 1) signal.Notify(c, os.Interrupt, syscall.SIGTERM) <-c done <- true }() // 等待关闭信号 <-done return nil } // createDatabaseConnection 创建数据库连接 func (a *Application) createDatabaseConnection() (*gorm.DB, error) { return container.NewDatabase(a.config, a.logger) } // autoMigrate 自动迁移 func (a *Application) autoMigrate(db *gorm.DB) error { // 迁移用户相关表 return db.AutoMigrate( &entities.User{}, // 后续可以添加其他实体 ) } // createLogger 创建日志器 func createLogger(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() } // GetConfig 获取配置 func (a *Application) GetConfig() *config.Config { return a.config } // GetLogger 获取日志器 func (a *Application) GetLogger() *zap.Logger { return a.logger } // HealthCheck 应用程序健康检查 func (a *Application) HealthCheck() error { // 这里可以添加应用程序级别的健康检查逻辑 return nil } // GetVersion 获取版本信息 func (a *Application) GetVersion() map[string]string { return map[string]string{ "name": a.config.App.Name, "version": a.config.App.Version, "environment": a.config.App.Env, "go_version": "1.23.4+", } } // RunCommand 运行特定命令 func (a *Application) RunCommand(command string, args ...string) error { switch command { case "migrate": return a.RunMigrations() case "version": version := a.GetVersion() fmt.Printf("Name: %s\n", version["name"]) fmt.Printf("Version: %s\n", version["version"]) fmt.Printf("Environment: %s\n", version["environment"]) fmt.Printf("Go Version: %s\n", version["go_version"]) return nil case "health": if err := a.HealthCheck(); err != nil { fmt.Printf("Health check failed: %v\n", err) return err } fmt.Println("Application is healthy") return nil default: return fmt.Errorf("unknown command: %s", command) } }