package main import ( "context" "errors" "net/http" "os" "os/signal" "syscall" "time" "0451meishiditu/backend/internal/config" "0451meishiditu/backend/internal/db" "0451meishiditu/backend/internal/httpx" "0451meishiditu/backend/internal/logger" "0451meishiditu/backend/internal/migrate" "0451meishiditu/backend/internal/redisx" "0451meishiditu/backend/internal/settings" "0451meishiditu/backend/internal/seed" ) func main() { cfg, err := config.Load() if err != nil { panic(err) } log := logger.New(cfg.AppEnv) defer func() { _ = log.Sync() }() gdb, err := db.Open(cfg, log) if err != nil { log.Fatal("open db failed", logger.Err(err)) } rdb := redisx.New(cfg) if err := migrate.AutoMigrate(gdb); err != nil { log.Fatal("auto migrate failed", logger.Err(err)) } if err := seed.EnsureInitialAdmin(gdb, cfg); err != nil { log.Fatal("seed admin failed", logger.Err(err)) } st, err := settings.New(gdb, cfg) if err != nil { log.Fatal("settings init failed", logger.Err(err)) } router := httpx.NewRouter(cfg, log, gdb, rdb, st) srv := &http.Server{ Addr: ":" + cfg.AppPort, Handler: router, ReadTimeout: 15 * time.Second, ReadHeaderTimeout: 10 * time.Second, WriteTimeout: 30 * time.Second, IdleTimeout: 60 * time.Second, } go func() { log.Info("server started", logger.Str("addr", srv.Addr)) if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { log.Fatal("listen failed", logger.Err(err)) } }() stop := make(chan os.Signal, 1) signal.Notify(stop, syscall.SIGINT, syscall.SIGTERM) <-stop ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() _ = srv.Shutdown(ctx) log.Info("server stopped") }