I'm trying to implement a clean way of gracefully stopping my gin server using a parent context passed to my class. Here the current code I have
Is there a cleaner way to do this? It feels like a lot of boilerplate code and unnessesary e.g. using an infinite loop for such an easy task.
func (instance *MyListener) Listen(ctx context.Context) error {
ctx, cancel := context.WithCancel(ctx)
defer cancel()
engine := gin.Default()
engine.POST("/doStuff", func(c *gin.Context) {
instance.doStuff()
c.Status(200)
})
instance.httpSrv = &http.Server {
Addr: ":8080",
Handler: engine,
}
// Initializing the server in a goroutine so that
// it won't block the graceful shutdown handling below
go func() {
if err := instance.httpSrv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
logging.Log.Error("Could not start listener", zap.Error(err))
}
}()
loop:
for {
select {
case <- ctx.Done():
break loop
default:
time.Sleep(1000)
}
}
ctx, cancel = context.WithTimeout(ctx, 2 * time.Second)
if err := instance.httpSrv.Shutdown(ctx); err != nil {
logging.Log.Error("Server forced to shutdown:", err)
}
return nil
}
This:
loop:
for {
select {
case <- ctx.Done():
break loop
default:
time.Sleep(1000)
}
}
Could be replaced with this:
<- ctx.Done()
And it would be just as effective and more efficient. Other than that, the solution you have seems clean, clear, and correct.