DEV Community

Matija Krajnik
Matija Krajnik

Posted on • Updated on • Originally published at letscode.blog

Graceful shutdown

If our server process gets signal to shut it down, we would like to finish the request currently handling before that happens. For that we will use graceful shutdown provided by Gin. This example is explained in detail on Gin GitHub with description in comments, so i will not go into details myself. Our internal/server/server.go will now look like this:

package server

import (
  "context"
  "errors"
  "net/http"
  "os"
  "os/signal"
  "rgb/internal/conf"
  "rgb/internal/database"
  "rgb/internal/store"
  "syscall"
  "time"

  "github.com/rs/zerolog/log"
)

const InternalServerError = "Something went wrong!"

func Start(cfg conf.Config) {
  jwtSetup(cfg)

  store.SetDBConnection(database.NewDBOptions(cfg))

  router := setRouter()

  server := &http.Server{
    Addr:    cfg.Host + ":" + cfg.Port,
    Handler: router,
  }

  // Initializing the server in a goroutine so that
  // it won't block the graceful shutdown handling below
  go func() {
    if err := server.ListenAndServe(); err != nil && errors.Is(err, http.ErrServerClosed) {
      log.Error().Err(err).Msg("Server ListenAndServe error")
    }
  }()

  // Wait for interrupt signal to gracefully shutdown the server with
  // a timeout of 5 seconds.
  quit := make(chan os.Signal)
  // kill (no param) default send syscall.SIGTERM
  // kill -2 is syscall.SIGINT
  // kill -9 is syscall.SIGKILL but can't be catch, so don't need add it
  signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
  <-quit
  log.Info().Msg("Shutting down server...")

  // The context is used to inform the server it has 5 seconds to finish
  // the request it is currently handling
  ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
  defer cancel()

  if err := server.Shutdown(ctx); err != nil {
    log.Fatal().Err(err).Msg("Server forced to shutdown")
  }

  log.Info().Msg("Server exiting.")
}
Enter fullscreen mode Exit fullscreen mode

Latest comments (0)