package main import ( "context" "fmt" "log" "net/http" "os" "os/signal" "syscall" "time" "github.com/allai/allai-backend/internal/app" "github.com/allai/allai-backend/internal/config" "github.com/allai/allai-backend/internal/httpapi" "github.com/allai/allai-backend/internal/provider/mock" ) func main() { cfg := config.Load() logger := log.New(os.Stdout, "[allai-backend] ", log.LstdFlags|log.Lmsgprefix) var provider app.GenerationProvider switch cfg.ProviderKind { case "mock": provider = mock.New() default: logger.Printf("provider %q not recognised, falling back to mock provider", cfg.ProviderKind) provider = mock.New() } service := app.NewService(provider) router := httpapi.NewRouter(service, logger) server := &http.Server{ Addr: cfg.Address(), Handler: router, ReadTimeout: 15 * time.Second, WriteTimeout: 60 * time.Second, IdleTimeout: 90 * time.Second, } go func() { logger.Printf("server starting on %s", cfg.Address()) if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { logger.Fatalf("http server failed: %v", err) } }() shutdown(server, logger) } func shutdown(server *http.Server, logger *log.Logger) { ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) defer stop() <-ctx.Done() logger.Println("shutdown signal received, draining requests…") shutdownCtx, cancel := context.WithTimeout(context.Background(), 20*time.Second) defer cancel() if err := server.Shutdown(shutdownCtx); err != nil { logger.Printf("graceful shutdown failed: %v", err) if closeErr := server.Close(); closeErr != nil { logger.Printf("forced close failed: %v", closeErr) } } logger.Println("server stopped cleanly") }