package main import ( "context" "fmt" "log" "net/http" "carrot_bbs/internal/config" "carrot_bbs/internal/grpc/runner" "carrot_bbs/internal/router" "carrot_bbs/internal/service" "gorm.io/gorm" ) // App 应用程序结构体 type App struct { Config *config.Config DB *gorm.DB Router *router.Router PushService service.PushService GRPCServer *runner.Server Server *http.Server } // NewApp 创建应用程序 func NewApp( cfg *config.Config, db *gorm.DB, r *router.Router, pushService service.PushService, grpcServer *runner.Server, ) *App { return &App{ Config: cfg, DB: db, Router: r, PushService: pushService, GRPCServer: grpcServer, } } // Start 启动应用程序 func (a *App) Start(ctx context.Context) error { // 1. 启动 gRPC 服务器(在 HTTP 服务器之前) if a.GRPCServer != nil { log.Println("Starting gRPC server...") if err := a.GRPCServer.Start(); err != nil { return fmt.Errorf("failed to start gRPC server: %w", err) } } // 2. 启动推送 Worker a.PushService.StartPushWorker(ctx) // 3. 创建 HTTP 服务器 addr := fmt.Sprintf("%s:%d", a.Config.Server.Host, a.Config.Server.Port) log.Printf("Starting HTTP server at %s", addr) a.Server = &http.Server{ Addr: addr, Handler: a.Router.Engine(), } // 4. 启动 HTTP 服务器 go func() { if err := a.Server.ListenAndServe(); err != nil && err != http.ErrServerClosed { log.Fatalf("listen: %s\n", err) } }() return nil } // Stop 停止应用程序 func (a *App) Stop(ctx context.Context) error { log.Println("Shutting down server...") // 1. 停止 HTTP 服务器 if a.Server != nil { log.Println("Stopping HTTP server...") if err := a.Server.Shutdown(ctx); err != nil { log.Printf("HTTP server forced to shutdown: %v", err) } } // 2. 停止 gRPC 服务器 if a.GRPCServer != nil { log.Println("Stopping gRPC server...") a.GRPCServer.Stop() } // 3. 停止推送 Worker log.Println("Stopping push worker...") a.PushService.StopPushWorker() // 4. 关闭数据库连接 log.Println("Closing database connection...") sqlDB, err := a.DB.DB() if err == nil { sqlDB.Close() } log.Println("Server exited") return nil }