Skip to content

Instantly share code, notes, and snippets.

@schaternik
Created May 19, 2025 12:43
Show Gist options
  • Select an option

  • Save schaternik/1369ef73013c5cc2a38f690bd16c3cb9 to your computer and use it in GitHub Desktop.

Select an option

Save schaternik/1369ef73013c5cc2a38f690bd16c3cb9 to your computer and use it in GitHub Desktop.
Main function handling graceful shutdown
const (
_shutdownPeriod = 15 * time.Second
_shutdownHardPeriod = 3 * time.Second
_readinessDrainDelay = 5 * time.Second
)
var isShuttingDown atomic.Bool
func main() {
// Setup signal context
rootCtx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer stop()
// Readiness endpoint
http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
if isShuttingDown.Load() {
http.Error(w, "Shutting down", http.StatusServiceUnavailable)
return
}
fmt.Fprintln(w, "OK")
})
// Sample business logic
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
select {
case <-time.After(2 * time.Second):
fmt.Fprintln(w, "Hello, world!")
case <-r.Context().Done():
http.Error(w, "Request cancelled.", http.StatusRequestTimeout)
}
})
// Ensure in-flight requests aren't cancelled immediately on SIGTERM
ongoingCtx, stopOngoingGracefully := context.WithCancel(context.Background())
server := &http.Server{
Addr: ":8080",
BaseContext: func(_ net.Listener) context.Context {
return ongoingCtx
},
}
go func() {
log.Println("Server starting on :8080.")
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
panic(err)
}
}()
// Wait for signal
<-rootCtx.Done()
stop()
isShuttingDown.Store(true)
log.Println("Received shutdown signal, shutting down.")
// Give time for readiness check to propagate
time.Sleep(_readinessDrainDelay)
log.Println("Readiness check propagated, now waiting for ongoing requests to finish.")
shutdownCtx, cancel := context.WithTimeout(context.Background(), _shutdownPeriod)
defer cancel()
err := server.Shutdown(shutdownCtx)
stopOngoingGracefully()
if err != nil {
log.Println("Failed to wait for ongoing requests to finish, waiting for forced cancellation.")
time.Sleep(_shutdownHardPeriod)
}
log.Println("Server shut down gracefully.")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment