package main import ( "context" "errors" "log" "net/http" "os/signal" "syscall" "time" "lokideploy/config" "lokideploy/repository" "lokideploy/routers" "lokideploy/seed" ) func main() { cfg := config.GetConfig() log.Println("Initializing database...") if err := repository.InitDB(); err != nil { log.Fatalf("Failed to init DB: %v", err) } log.Println("Seeding default data...") seed.Seed() r := routers.SetupRouter() srv := &http.Server{ Addr: ":" + cfg.ServerPort, Handler: r, ReadTimeout: 30 * time.Second, WriteTimeout: 30 * time.Second, IdleTimeout: 120 * time.Second, } // 监听中断/终止信号,实现优雅关停:先停 HTTP(拒绝新请求、处理完在途请求), // 再 flush 数据库,避免防抖/异步保存丢失最近写入。 ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) defer stop() go func() { log.Printf("LokiDeploy starting on port %s", cfg.ServerPort) log.Printf("API: http://localhost:%s/api/v1", cfg.ServerPort) log.Printf("Default login: admin / admin123") if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { log.Fatalf("Server failed: %v", err) } }() <-ctx.Done() log.Println("Shutdown signal received, draining connections...") shutdownCtx, cancel := context.WithTimeout(context.Background(), 15*time.Second) defer cancel() if err := srv.Shutdown(shutdownCtx); err != nil { log.Printf("HTTP shutdown error: %v", err) } log.Println("Flushing database...") if err := repository.Shutdown(); err != nil { log.Printf("DB shutdown error: %v", err) } log.Println("LokiDeploy stopped") }