package main import ( "context" "errors" "log" "net/http" "os" "os/signal" "syscall" "time" "reanimator/internal/api" "reanimator/internal/config" "reanimator/internal/repository" ) func main() { cfg, err := config.Load() if err != nil { log.Fatalf("load config: %v", err) } db, err := repository.Open(cfg.DatabaseDSN) if err != nil { log.Fatalf("open database: %v", err) } defer func() { _ = db.Close() }() srv := api.NewServer(cfg.HTTPAddr, cfg.ReadTimeout, cfg.WriteTimeout, db) errCh := make(chan error, 1) go func() { log.Printf("starting API server on %s", cfg.HTTPAddr) errCh <- srv.Start() }() signalCh := make(chan os.Signal, 1) signal.Notify(signalCh, syscall.SIGINT, syscall.SIGTERM) select { case sig := <-signalCh: log.Printf("received signal %s, shutting down", sig) case err := <-errCh: if err == nil || errors.Is(err, http.ErrServerClosed) { return } log.Fatalf("server error: %v", err) } ctx, cancel := context.WithTimeout(context.Background(), cfg.ShutdownGrace) defer cancel() if err := srv.Shutdown(ctx); err != nil { log.Fatalf("shutdown server: %v", err) } // Ensure in-flight logs flush before exit in short-lived environments. time.Sleep(25 * time.Millisecond) }