Skip to content

Commit

Permalink
graceful shutdown implemented
Browse files Browse the repository at this point in the history
  • Loading branch information
potat-dev committed Jul 20, 2024
1 parent b15ac2b commit ac2b458
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 37 deletions.
16 changes: 4 additions & 12 deletions cmd/server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,12 @@ import (

func main() {
cfg := config.MustLoad()

log := prettylog.SetupLogger(cfg.Env)
log.Info("starting librakeeper srv", slog.String("env", cfg.Env), slog.Int("port", cfg.Server.Port))

// Create and initialize the srv
srv := server.NewServer(cfg, log)
if err := srv.Initialize(); err != nil {
log.Error("failed to initialize srv", slog.Any("error", err))
os.Exit(1)
}
log.Info("starting librakeeper server", slog.String("env", cfg.Env), slog.Int("port", cfg.Server.Port))

// Run the srv
if err := srv.Run(); err != nil {
log.Error("failed to run srv", slog.Any("error", err))
// Create and run the server
if err := server.NewServer(cfg, log).Run(); err != nil {
log.Error("server error", slog.Any("error", err))
os.Exit(1)
}
}
71 changes: 46 additions & 25 deletions internal/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,51 @@ func NewServer(config *config.Config, log *slog.Logger) *Server {
return &Server{
config: config,
log: log,
router: gin.New(),
}
}

// Initialize initializes the server components.
func (s *Server) Initialize() error {
// Run initializes and starts the HTTP server and handles graceful shutdown.
func (s *Server) Run() error {
if err := s.initialize(); err != nil {
return fmt.Errorf("failed to initialize server: %w", err)
}

// Graceful Shutdown
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

go func() {
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
s.log.Info("received shutdown signal")
cancel()
}()

return s.runHTTPServer(ctx)
}

func (s *Server) runHTTPServer(ctx context.Context) error {
go func() {
if err := s.httpServer.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
s.log.Error("failed to start server", slog.Any("error", err))
}
}()

s.log.Info("server started successfully, press Ctrl+C to stop")

<-ctx.Done() // Block until the context is canceled (shutdown signal)

s.log.Info("shutting down server...")

shutdownCtx, done := context.WithTimeout(ctx, 5*time.Second)
defer done()

return s.httpServer.Shutdown(shutdownCtx) // Graceful shutdown
}

// initialize initializes the server components.
func (s *Server) initialize() error {
// Initialize Firebase
err := auth.InitializeFirebase(s.config.Auth.ConfigPath)
if err != nil {
Expand All @@ -60,7 +99,7 @@ func (s *Server) Initialize() error {
grpc.WithTransportCredentials(insecure.NewCredentials()),
)
if err != nil {
panic(err)
return fmt.Errorf("failed to connect to gRPC server: %w", err)
}

bookRepo := mongo.NewBookRepo(db, s.log, "user_books")
Expand All @@ -80,11 +119,13 @@ func (s *Server) Initialize() error {

// Configure CORS
corsConfig := cors.Config{
AllowOrigins: s.config.Server.AllowedOrigins, // Get origins from config
AllowOrigins: s.config.Server.AllowedOrigins,
AllowMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
AllowHeaders: []string{"Origin", "Content-Type", "Authorization"},
AllowCredentials: true,
}

s.router = gin.New()
s.router.Use(gin.Logger(), gin.Recovery(), cors.New(corsConfig))
routes.SetupRoutes(s.router, h)

Expand All @@ -95,23 +136,3 @@ func (s *Server) Initialize() error {

return nil
}

// Run starts the HTTP server and handles graceful shutdown.
func (s *Server) Run() error {
go func() {
if err := s.httpServer.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
s.log.Error("failed to start server", slog.Any("error", err))
}
}()

quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit

s.log.Info("shutting down server...")

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

return s.httpServer.Shutdown(ctx)
}

0 comments on commit ac2b458

Please sign in to comment.