mirror of
https://github.com/ClusterCockpit/cc-backend
synced 2026-03-25 17:17:29 +01:00
fix: Improve shutdown time
Entire-Checkpoint: a4d012e1edcf
This commit is contained in:
@@ -18,6 +18,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/99designs/gqlgen/graphql"
|
"github.com/99designs/gqlgen/graphql"
|
||||||
@@ -399,16 +400,6 @@ func (s *Server) Start(ctx context.Context) error {
|
|||||||
return fmt.Errorf("dropping privileges: %w", err)
|
return fmt.Errorf("dropping privileges: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle context cancellation for graceful shutdown
|
|
||||||
go func() {
|
|
||||||
<-ctx.Done()
|
|
||||||
shutdownCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
|
||||||
defer cancel()
|
|
||||||
if err := s.server.Shutdown(shutdownCtx); err != nil {
|
|
||||||
cclog.Errorf("Server shutdown error: %v", err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
if err = s.server.Serve(listener); err != nil && err != http.ErrServerClosed {
|
if err = s.server.Serve(listener); err != nil && err != http.ErrServerClosed {
|
||||||
return fmt.Errorf("server failed: %w", err)
|
return fmt.Errorf("server failed: %w", err)
|
||||||
}
|
}
|
||||||
@@ -416,8 +407,7 @@ func (s *Server) Start(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) Shutdown(ctx context.Context) {
|
func (s *Server) Shutdown(ctx context.Context) {
|
||||||
// Create a shutdown context with timeout
|
shutdownCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
||||||
shutdownCtx, cancel := context.WithTimeout(ctx, 30*time.Second)
|
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
nc := nats.GetClient()
|
nc := nats.GetClient()
|
||||||
@@ -425,20 +415,36 @@ func (s *Server) Shutdown(ctx context.Context) {
|
|||||||
nc.Close()
|
nc.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// First shut down the server gracefully (waiting for all ongoing requests)
|
|
||||||
if err := s.server.Shutdown(shutdownCtx); err != nil {
|
if err := s.server.Shutdown(shutdownCtx); err != nil {
|
||||||
cclog.Errorf("Server shutdown error: %v", err)
|
cclog.Errorf("Server shutdown error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Archive all the metric store data
|
// Run metricstore and archiver shutdown concurrently.
|
||||||
ms := metricstore.GetMemoryStore()
|
// They are independent: metricstore writes .bin snapshots,
|
||||||
|
// archiver flushes pending job archives.
|
||||||
|
done := make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
defer close(done)
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
if ms != nil {
|
if ms := metricstore.GetMemoryStore(); ms != nil {
|
||||||
|
wg.Go(func() {
|
||||||
metricstore.Shutdown()
|
metricstore.Shutdown()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shutdown archiver with 10 second timeout for fast shutdown
|
wg.Go(func() {
|
||||||
if err := archiver.Shutdown(10 * time.Second); err != nil {
|
if err := archiver.Shutdown(10 * time.Second); err != nil {
|
||||||
cclog.Warnf("Archiver shutdown: %v", err)
|
cclog.Warnf("Archiver shutdown: %v", err)
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
}()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-done:
|
||||||
|
case <-time.After(10 * time.Second):
|
||||||
|
cclog.Warn("Shutdown deadline exceeded, forcing exit")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user