package main import ( "context" "errors" "log" "net/http" "os" "os/signal" "syscall" "time" "github.com/joho/godotenv" "github.com/mrhid6/vantage/admin/internal/config" "github.com/mrhid6/vantage/admin/internal/db" "github.com/mrhid6/vantage/admin/internal/licensing" "github.com/mrhid6/vantage/admin/internal/models" ) func main() { godotenv.Load() cfg, err := config.Load() if err != nil { log.Fatalf("configuration error: %v", err) } licensing.SetSigningKey(cfg.SigningKey) ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second) if err := db.Connect(ctx, cfg); err != nil { cancel() log.Fatalf("database: %v", err) } cancel() log.Printf("connected: admin=%s control=%s", cfg.AdminDBName, cfg.ControlDBName) idxCtx, idxCancel := context.WithTimeout(context.Background(), 30*time.Second) if err := db.EnsureIndexes(idxCtx); err != nil { idxCancel() log.Fatalf("indexes: %v", err) } if err := models.SeedPlans(idxCtx); err != nil { idxCancel() log.Fatalf("plan seed: %v", err) } idxCancel() srv := &http.Server{ Addr: cfg.Addr, Handler: http.NotFoundHandler(), // replaced in Task 8 ReadHeaderTimeout: 10 * time.Second, ReadTimeout: 20 * time.Second, WriteTimeout: 30 * time.Second, IdleTimeout: 60 * time.Second, } go func() { log.Printf("admin listening on %s", cfg.Addr) if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { log.Fatalf("server error: %v", err) } }() stopCtx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) defer stop() <-stopCtx.Done() shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 15*time.Second) defer shutdownCancel() _ = srv.Shutdown(shutdownCtx) log.Println("admin stopped") os.Exit(0) }