|
4 | 4 | "context" |
5 | 5 | "net/http" |
6 | 6 | "os" |
| 7 | + "os/signal" |
7 | 8 | "sync/atomic" |
| 9 | + "syscall" |
8 | 10 | "time" |
9 | 11 |
|
10 | 12 | "benchmark-report-api/internal/config" |
@@ -100,7 +102,57 @@ type ServerService struct { |
100 | 102 |
|
101 | 103 | func (s *ServerService) Start(ctx context.Context) error { |
102 | 104 | s.logger.Info("Server starting", "addr", s.server.Addr) |
103 | | - return s.server.ListenAndServe() |
| 105 | + |
| 106 | + // Create a channel to listen for OS signals (Ctrl+C, SIGTERM) |
| 107 | + sigChan := make(chan os.Signal, 1) |
| 108 | + signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) |
| 109 | + defer signal.Stop(sigChan) // Clean up signal notification |
| 110 | + |
| 111 | + // Start server in a goroutine |
| 112 | + serverErr := make(chan error, 1) |
| 113 | + go func() { |
| 114 | + if err := s.server.ListenAndServe(); err != nil && err != http.ErrServerClosed { |
| 115 | + serverErr <- err |
| 116 | + } |
| 117 | + }() |
| 118 | + |
| 119 | + // Wait for either a signal or server error |
| 120 | + select { |
| 121 | + case err := <-serverErr: |
| 122 | + s.logger.Error("Server failed to start", "error", err) |
| 123 | + return err |
| 124 | + case sig := <-sigChan: |
| 125 | + s.logger.Info("Received shutdown signal", "signal", sig) |
| 126 | + |
| 127 | + // Create a context with timeout for graceful shutdown |
| 128 | + shutdownCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second) |
| 129 | + defer cancel() |
| 130 | + |
| 131 | + s.logger.Info("Shutting down server gracefully...") |
| 132 | + if err := s.server.Shutdown(shutdownCtx); err != nil { |
| 133 | + s.logger.Error("Server forced to shutdown", "error", err) |
| 134 | + return err |
| 135 | + } |
| 136 | + |
| 137 | + s.logger.Info("Server shutdown complete") |
| 138 | + s.stopped.Store(true) |
| 139 | + return nil |
| 140 | + case <-ctx.Done(): |
| 141 | + s.logger.Info("Context cancelled, shutting down server") |
| 142 | + |
| 143 | + // Create a context with timeout for graceful shutdown |
| 144 | + shutdownCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second) |
| 145 | + defer cancel() |
| 146 | + |
| 147 | + if err := s.server.Shutdown(shutdownCtx); err != nil { |
| 148 | + s.logger.Error("Server forced to shutdown", "error", err) |
| 149 | + return err |
| 150 | + } |
| 151 | + |
| 152 | + s.logger.Info("Server shutdown complete") |
| 153 | + s.stopped.Store(true) |
| 154 | + return ctx.Err() |
| 155 | + } |
104 | 156 | } |
105 | 157 |
|
106 | 158 | func (s *ServerService) Stop(ctx context.Context) error { |
|
0 commit comments