Skip to content

Instantly share code, notes, and snippets.

@feketegy
Last active September 2, 2023 02:28
Show Gist options
  • Save feketegy/63308542ad44150f00e03bc3ff167e20 to your computer and use it in GitHub Desktop.
Save feketegy/63308542ad44150f00e03bc3ff167e20 to your computer and use it in GitHub Desktop.
Go API server shutdown with graceful timeout
// Setup signal capture
signalShutdown := make(chan os.Signal, 1)
signal.Notify(signalShutdown, os.Interrupt, os.Kill, syscall.SIGTERM)
ctxCancel, cancel := context.WithCancel(context.Background())
wg := sync.WaitGroup{}
// Init API server
apiSrv := apiserver.New(ctxCancel, &wg)
// Start internal webserver
wg.Add(1)
// HTTP ListenAndServe
go apiSrv.Start()
// Will block until a signal is received to shut down the API
// When the shutdown signal is received, it executes a cancel context and forcefully stop the services if needed.
<-signalShutdown
fmt.Printf("\nWaiting for services to stop")
// Signal goroutines to cancel
cancel()
// Waiting for graceful stop
normalShutdown := make(chan struct{})
ticker := time.NewTicker(time.Second)
t := time.Now()
timeoutDuration := 10 * time.Second
go func() {
wg.Wait()
close(normalShutdown)
}()
loop:
for {
select {
case <-normalShutdown:
break loop
case <-ticker.C:
fmt.Printf(".")
if time.Since(t) >= timeoutDuration {
fmt.Printf("\nTimed out, force killing services.")
break loop
}
}
}
ticker.Stop()
fmt.Printf("\nAPI stopped.")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment