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" // 认证域实体 certEntities "tyapi-server/internal/domains/certification/entities" // 财务域实体 financeEntities "tyapi-server/internal/domains/finance/entities" // 产品域实体 productEntities "tyapi-server/internal/domains/product/entities" // 文章域实体 articleEntities "tyapi-server/internal/domains/article/entities" apiEntities "tyapi-server/internal/domains/api/entities" "tyapi-server/internal/infrastructure/database" ) // 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() // 检查是否需要自动迁移 if a.config.Database.AutoMigrate { a.logger.Info("Auto migration is enabled, running database migrations...") if err := a.RunMigrations(); err != nil { a.logger.Error("Auto migration failed", zap.Error(err)) return fmt.Errorf("auto migration failed: %w", err) } a.logger.Info("Auto migration completed successfully") } // 启动容器 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.logger.Info("Container started successfully, setting up graceful shutdown...") // 设置优雅关闭 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) { dbCfg := database.Config{ Host: a.config.Database.Host, Port: a.config.Database.Port, User: a.config.Database.User, Password: a.config.Database.Password, Name: a.config.Database.Name, SSLMode: a.config.Database.SSLMode, Timezone: a.config.Database.Timezone, MaxOpenConns: a.config.Database.MaxOpenConns, MaxIdleConns: a.config.Database.MaxIdleConns, ConnMaxLifetime: a.config.Database.ConnMaxLifetime, } db, err := database.NewConnection(dbCfg) if err != nil { return nil, err } return db.DB, nil } // autoMigrate 自动迁移 func (a *Application) autoMigrate(db *gorm.DB) error { a.logger.Info("Starting database auto migration...") // 如果需要删除某些表,可以在这里手动删除 // 注意:这会永久删除数据,请谨慎使用! /* // 删除不再需要的表(示例,请根据实际情况使用) if err := db.Migrator().DropTable(&entities.FavoriteItem{}); err != nil { a.logger.Warn("Failed to drop table", zap.Error(err)) // 继续执行,不阻断迁移 } */ // 自动迁移所有实体 return db.AutoMigrate( // 用户域 &entities.User{}, &entities.SMSCode{}, &entities.EnterpriseInfo{}, &entities.ContractInfo{}, // 认证域 &certEntities.Certification{}, &certEntities.EnterpriseInfoSubmitRecord{}, &certEntities.EsignContractGenerateRecord{}, &certEntities.EsignContractSignRecord{}, // 财务域 &financeEntities.Wallet{}, &financeEntities.WalletTransaction{}, &financeEntities.RechargeRecord{}, &financeEntities.AlipayOrder{}, &financeEntities.InvoiceApplication{}, &financeEntities.UserInvoiceInfo{}, // 产品域 &productEntities.Product{}, &productEntities.ProductPackageItem{}, &productEntities.ProductCategory{}, &productEntities.Subscription{}, &productEntities.ProductDocumentation{}, &productEntities.ProductApiConfig{}, // 文章域 &articleEntities.Article{}, &articleEntities.Category{}, &articleEntities.Tag{}, // api &apiEntities.ApiUser{}, &apiEntities.ApiCall{}, ) } // 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) } } // GetArticleService 获取文章服务 (用于 Worker) func (app *Application) GetArticleService() interface{} { // 这里需要从容器中获取文章服务 // 由于循环导入问题,暂时返回 nil // 实际使用时需要通过其他方式获取 return nil }