mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-10-19 10:33:29 +00:00
fix(server): fail fast on frontend bind errors
This commit is contained in:
parent
b38488f2da
commit
adad2bbd1c
2 changed files with 71 additions and 44 deletions
|
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
|
|
@ -256,15 +257,6 @@ func Run(ctx context.Context, version string) error {
|
|||
// Wire multi-tenant monitor to resource handlers for tenant-aware state
|
||||
router.SetMultiTenantMonitor(reloadableMonitor.GetMultiTenantMonitor())
|
||||
|
||||
// Start AI patrol service for background infrastructure monitoring
|
||||
router.StartPatrol(ctx)
|
||||
|
||||
// Start AI chat service
|
||||
router.StartAIChat(ctx)
|
||||
|
||||
// Wire alert-triggered AI analysis
|
||||
router.WireAlertTriggeredAI()
|
||||
|
||||
// Create HTTP server with unified configuration
|
||||
srv := &http.Server{
|
||||
Addr: fmt.Sprintf("%s:%d", cfg.BindAddress, cfg.FrontendPort),
|
||||
|
|
@ -274,6 +266,48 @@ func Run(ctx context.Context, version string) error {
|
|||
IdleTimeout: 120 * time.Second,
|
||||
}
|
||||
|
||||
useTLS := cfg.HTTPSEnabled && cfg.TLSCertFile != "" && cfg.TLSKeyFile != ""
|
||||
if cfg.HTTPSEnabled && !useTLS {
|
||||
log.Warn().Msg("HTTPS_ENABLED is true but TLS_CERT_FILE or TLS_KEY_FILE not configured, falling back to HTTP")
|
||||
}
|
||||
|
||||
listener, err := net.Listen("tcp", srv.Addr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to bind frontend listener on %s: %w", srv.Addr, err)
|
||||
}
|
||||
|
||||
serverErrCh := make(chan error, 1)
|
||||
go func() {
|
||||
if useTLS {
|
||||
log.Info().
|
||||
Str("host", cfg.BindAddress).
|
||||
Int("port", cfg.FrontendPort).
|
||||
Str("protocol", "HTTPS").
|
||||
Msg("Server listening")
|
||||
if err := srv.ServeTLS(listener, cfg.TLSCertFile, cfg.TLSKeyFile); err != nil && err != http.ErrServerClosed {
|
||||
serverErrCh <- fmt.Errorf("https server failed: %w", err)
|
||||
}
|
||||
} else {
|
||||
log.Info().
|
||||
Str("host", cfg.BindAddress).
|
||||
Int("port", cfg.FrontendPort).
|
||||
Str("protocol", "HTTP").
|
||||
Msg("Server listening")
|
||||
if err := srv.Serve(listener); err != nil && err != http.ErrServerClosed {
|
||||
serverErrCh <- fmt.Errorf("http server failed: %w", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// Start AI patrol service for background infrastructure monitoring
|
||||
router.StartPatrol(ctx)
|
||||
|
||||
// Start AI chat service
|
||||
router.StartAIChat(ctx)
|
||||
|
||||
// Wire alert-triggered AI analysis
|
||||
router.WireAlertTriggeredAI()
|
||||
|
||||
// Start config watcher for .env file changes
|
||||
configWatcher, err := config.NewConfigWatcher(cfg)
|
||||
if err != nil {
|
||||
|
|
@ -304,35 +338,10 @@ func Run(ctx context.Context, version string) error {
|
|||
defer configWatcher.Stop()
|
||||
}
|
||||
|
||||
// Start server
|
||||
go func() {
|
||||
if cfg.HTTPSEnabled && cfg.TLSCertFile != "" && cfg.TLSKeyFile != "" {
|
||||
log.Info().
|
||||
Str("host", cfg.BindAddress).
|
||||
Int("port", cfg.FrontendPort).
|
||||
Str("protocol", "HTTPS").
|
||||
Msg("Server listening")
|
||||
if err := srv.ListenAndServeTLS(cfg.TLSCertFile, cfg.TLSKeyFile); err != nil && err != http.ErrServerClosed {
|
||||
log.Error().Err(err).Msg("Failed to start HTTPS server")
|
||||
}
|
||||
} else {
|
||||
if cfg.HTTPSEnabled {
|
||||
log.Warn().Msg("HTTPS_ENABLED is true but TLS_CERT_FILE or TLS_KEY_FILE not configured, falling back to HTTP")
|
||||
}
|
||||
log.Info().
|
||||
Str("host", cfg.BindAddress).
|
||||
Int("port", cfg.FrontendPort).
|
||||
Str("protocol", "HTTP").
|
||||
Msg("Server listening")
|
||||
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
||||
log.Error().Err(err).Msg("Failed to start HTTP server")
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// Setup signal handlers
|
||||
sigChan := make(chan os.Signal, 1)
|
||||
reloadChan := make(chan os.Signal, 1)
|
||||
var runErr error
|
||||
|
||||
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
|
||||
signal.Notify(reloadChan, syscall.SIGHUP)
|
||||
|
|
@ -343,6 +352,11 @@ func Run(ctx context.Context, version string) error {
|
|||
log.Info().Msg("Context cancelled, shutting down...")
|
||||
goto shutdown
|
||||
|
||||
case err := <-serverErrCh:
|
||||
log.Error().Err(err).Msg("Frontend server terminated unexpectedly")
|
||||
runErr = err
|
||||
goto shutdown
|
||||
|
||||
case <-reloadChan:
|
||||
log.Info().Msg("Received SIGHUP, reloading configuration...")
|
||||
if configWatcher != nil {
|
||||
|
|
@ -386,7 +400,7 @@ shutdown:
|
|||
tenantAuditManager.Close()
|
||||
|
||||
log.Info().Msg("Server stopped")
|
||||
return nil
|
||||
return runErr
|
||||
}
|
||||
|
||||
// startMetricsServer is moved from main.go
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue