package main import ( "context" "flag" "log" "os" "os/signal" "syscall" "time" "gitea.loveuer.com/loveuer/cluster/api" "gitea.loveuer.com/loveuer/cluster/internal/config" "gitea.loveuer.com/loveuer/cluster/internal/database" "gitea.loveuer.com/loveuer/cluster/internal/middleware" "gitea.loveuer.com/loveuer/cluster/internal/registry/storage" "github.com/gofiber/fiber/v3" ) func main() { // 解析命令行参数 var ( debug = flag.Bool("debug", false, "Enable debug mode") address = flag.String("address", ":8080", "API server listen address") dataDir = flag.String("data-dir", "./storage", "Data directory for storing all data") ) flag.Parse() // 加载配置 cfg, err := config.LoadFromFlags(*debug, *address, *dataDir) if err != nil { log.Fatalf("Failed to load config: %v", err) } log.Printf("Starting server with config: debug=%v, address=%s, data-dir=%s", cfg.Server.Debug, cfg.Server.Address, cfg.Storage.RootPath) // 初始化数据库 if err := database.Init(cfg.Storage.RootPath); err != nil { log.Fatalf("Failed to initialize database: %v", err) } // 初始化存储(使用 GORM 元数据 + 文件系统) store, err := storage.NewGormStorage(cfg.Storage.RootPath) if err != nil { log.Fatalf("Failed to initialize storage: %v", err) } // 创建 Fiber 应用 config := fiber.Config{} if !cfg.Server.Debug { // Fiber v3 默认不显示启动消息 } app := fiber.New(config) // 全局中间件 app.Use(middleware.Logger()) app.Use(middleware.Recovery()) app.Use(middleware.CORS()) // 健康检查 app.Get("/health", func(c fiber.Ctx) error { return c.JSON(fiber.Map{"status": "ok"}) }) // 设置路由 api.SetupRoutes(app, store) // 启动服务器(在 goroutine 中) go func() { log.Printf("Server listening on %s", cfg.Server.Address) if err := app.Listen(cfg.Server.Address); err != nil { log.Fatalf("Failed to start server: %v", err) } }() // 等待中断信号以优雅关闭服务器 quit := make(chan os.Signal, 1) signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) <-quit log.Println("Shutting down server...") // 优雅关闭,等待 5 秒 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() if err := app.ShutdownWithContext(ctx); err != nil { log.Fatalf("Server forced to shutdown: %v", err) } log.Println("Server exited") }