package httpapi import ( "context" "errors" "log/slog" "net/http" "time" "botpontos/internal/bootstrap" "botpontos/internal/config" ) // Run monta o serviço e atende HTTP até o contexto ser cancelado. func Run(ctx context.Context, cfg config.Config, logger *slog.Logger) error { built, err := bootstrap.Build(ctx, cfg, logger) if err != nil { return err } defer built.Pool.Close() if cfg.Web.PublicURL == "" { logger.Warn("BP_PUBLIC_URL vazio: a checagem de origem das requisições está desligada (use só em desenvolvimento)") } if err := built.Service.SeedSettings(ctx); err != nil { return err } server := &http.Server{ Addr: cfg.HTTP.Addr, Handler: NewHandler(built.Pool, built.Service, cfg, logger), ReadHeaderTimeout: 5 * time.Second, ReadTimeout: 15 * time.Second, WriteTimeout: 120 * time.Second, // o teste de credencial pode fazer várias consultas à PontoMais IdleTimeout: 60 * time.Second, } errCh := make(chan error, 1) go func() { logger.Info("api ouvindo", "addr", cfg.HTTP.Addr) errCh <- server.ListenAndServe() }() select { case <-ctx.Done(): logger.Info("encerrando api") shutdownCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() return server.Shutdown(shutdownCtx) case err := <-errCh: if errors.Is(err, http.ErrServerClosed) { return nil } return err } }