@@ -36,7 +36,7 @@ func runServer(cfg *config.Config, appLogger logger.Logger) error {
3636 return err
3737 }
3838
39- // Set up graceful shutdown
39+ // Set up graceful shutdown - single channel for all signals
4040 shutdown := make (chan os.Signal , 1 )
4141 signalNotify (shutdown , os .Interrupt , syscall .SIGTERM )
4242
@@ -55,20 +55,60 @@ func runServer(cfg *config.Config, appLogger logger.Logger) error {
5555 }
5656 return err
5757 case sig := <- shutdown :
58- appLogger .WithField ("signal" , sig .String ()).Info ("Shutdown signal received" )
58+ appLogger .WithField ("signal" , sig .String ()).Info ("Shutdown signal received - starting graceful shutdown" )
59+ appLogger .Info ("Send signal again (Ctrl+C) to force immediate shutdown" )
60+
61+ // Configure app shutdown timeout for long-running tasks (55+ seconds)
62+ // Set to 65 seconds to allow tasks to complete or save progress
63+ appInstance .SetShutdownTimeout (65 * time .Second )
5964
6065 // Create a context with timeout for graceful shutdown
61- ctx , cancel := context .WithTimeout (context .Background (), 30 * time .Second )
66+ // Use 70 seconds to give 5 seconds buffer beyond app's internal timeout
67+ ctx , cancel := context .WithTimeout (context .Background (), 70 * time .Second )
6268 defer cancel ()
6369
64- // Attempt graceful shutdown
65- if err := appInstance .Shutdown (ctx ); err != nil {
66- appLogger .WithField ("error" , err .Error ()).Error ("Error during shutdown" )
67- return err
70+ // Log current active requests
71+ activeRequests := appInstance .GetActiveRequestCount ()
72+ appLogger .WithField ("active_requests" , activeRequests ).Info ("Starting graceful shutdown" )
73+
74+ // Create a new channel for force shutdown (after first signal received)
75+ forceShutdown := make (chan os.Signal , 1 )
76+ signalNotify (forceShutdown , os .Interrupt , syscall .SIGTERM )
77+
78+ // Start graceful shutdown in a goroutine
79+ shutdownDone := make (chan error , 1 )
80+ go func () {
81+ shutdownDone <- appInstance .Shutdown (ctx )
82+ }()
83+
84+ // Wait for either graceful shutdown completion or forced shutdown signal
85+ select {
86+ case err := <- shutdownDone :
87+ if err != nil {
88+ appLogger .WithField ("error" , err .Error ()).Error ("Error during graceful shutdown" )
89+ return err
90+ }
91+ appLogger .Info ("Server shut down gracefully" )
92+ return nil
93+ case forceSig := <- forceShutdown :
94+ appLogger .WithField ("signal" , forceSig .String ()).Warn ("Force shutdown signal received - terminating immediately" )
95+ appLogger .Warn ("Some requests may be interrupted!" )
96+
97+ // Cancel the graceful shutdown context to force immediate shutdown
98+ cancel ()
99+
100+ // Wait a brief moment for the shutdown to acknowledge the cancellation
101+ select {
102+ case err := <- shutdownDone :
103+ if err != nil {
104+ appLogger .WithField ("error" , err .Error ()).Error ("Error during forced shutdown" )
105+ }
106+ case <- time .After (2 * time .Second ):
107+ appLogger .Warn ("Forced shutdown timeout - exiting immediately" )
108+ }
109+
110+ return fmt .Errorf ("forced shutdown" )
68111 }
69-
70- appLogger .Info ("Server shut down gracefully" )
71- return nil
72112 }
73113}
74114
0 commit comments