package main import ( "context" "log" "net/http" "os" "os/signal" "syscall" "time" "autostore/internal/application/interfaces" "autostore/internal/config" "autostore/internal/container" ) func main() { // Load configuration cfg, err := config.Load() if err != nil { log.Fatalf("Failed to load configuration: %v", err) } // Validate configuration if err := cfg.Validate(); err != nil { log.Fatalf("Invalid configuration: %v", err) } // Create dependency injection container container := container.NewContainer(cfg) if err := container.Initialize(); err != nil { log.Fatalf("Failed to initialize container: %v", err) } // Get server and scheduler from container server := container.GetServer() scheduler := container.GetExpiredItemsScheduler() logger := container.GetLogger() // Setup graceful shutdown shutdownComplete := make(chan struct{}) go setupGracefulShutdown(server, scheduler, logger, shutdownComplete) // Start scheduler if err := scheduler.Start(context.Background()); err != nil { logger.Error(context.Background(), "Failed to start scheduler", "error", err) log.Fatalf("Failed to start scheduler: %v", err) } // Start server if err := server.Start(); err != nil { if err == http.ErrServerClosed { // This is expected during graceful shutdown logger.Info(context.Background(), "Server shutdown complete") } else { logger.Error(context.Background(), "Server failed to start", "error", err) log.Fatalf("Server failed to start: %v", err) } } // Wait for graceful shutdown to complete <-shutdownComplete logger.Info(context.Background(), "Application exiting gracefully") } func setupGracefulShutdown(server interface { Shutdown(ctx context.Context) error }, scheduler interface { Stop() error }, logger interfaces.ILogger, shutdownComplete chan struct{}) { sigChan := make(chan os.Signal, 1) signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) sig := <-sigChan logger.Info(context.Background(), "Received shutdown signal", "signal", sig) ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() if err := scheduler.Stop(); err != nil { logger.Error(ctx, "Scheduler shutdown failed", "error", err) } else { logger.Info(ctx, "Scheduler shutdown completed gracefully") } if err := server.Shutdown(ctx); err != nil { logger.Error(ctx, "Server shutdown failed", "error", err) } else { logger.Info(ctx, "Server shutdown completed gracefully") } // Signal that shutdown is complete close(shutdownComplete) }