mirror of
https://github.com/gin-gonic/gin.git
synced 2026-06-04 17:58:14 +08:00
- Add server and serverLock fields to Engine struct - Add Shutdown() method that calls http.Server.Shutdown() - Modify Run/RunTLS/RunUnix/RunListener to store server reference - Add RunWithShutdown convenience method with signal handling - Add comprehensive tests for graceful shutdown (8 test cases) - Fix lint errors (errorlint, testifylint, errcheck)
70 lines
1.9 KiB
Go
70 lines
1.9 KiB
Go
// Copyright 2014 Manu Martinez-Almeida. All rights reserved.
|
|
// Use of this source code is governed by a MIT style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package gin
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"net/http"
|
|
"os"
|
|
"os/signal"
|
|
"syscall"
|
|
"time"
|
|
)
|
|
|
|
// ShutdownConfig holds configuration for graceful shutdown.
|
|
type ShutdownConfig struct {
|
|
// Timeout is the maximum duration to wait for active connections to finish.
|
|
// Default: 10 seconds
|
|
Timeout time.Duration
|
|
|
|
// Signals are the OS signals that will trigger shutdown.
|
|
// Default: SIGINT, SIGTERM
|
|
Signals []os.Signal
|
|
}
|
|
|
|
// RunWithShutdown starts the HTTP server and handles graceful shutdown on SIGINT/SIGTERM.
|
|
// It blocks until the server is shut down.
|
|
// The timeout parameter specifies the maximum duration to wait for active connections to finish.
|
|
func (engine *Engine) RunWithShutdown(addr string, timeout time.Duration) error {
|
|
return engine.RunWithShutdownConfig(addr, ShutdownConfig{
|
|
Timeout: timeout,
|
|
Signals: []os.Signal{syscall.SIGINT, syscall.SIGTERM},
|
|
})
|
|
}
|
|
|
|
// RunWithShutdownConfig starts the HTTP server with custom shutdown configuration.
|
|
// It blocks until the server is shut down.
|
|
func (engine *Engine) RunWithShutdownConfig(addr string, config ShutdownConfig) error {
|
|
if config.Timeout == 0 {
|
|
config.Timeout = 10 * time.Second
|
|
}
|
|
if len(config.Signals) == 0 {
|
|
config.Signals = []os.Signal{syscall.SIGINT, syscall.SIGTERM}
|
|
}
|
|
|
|
ctx, stop := signal.NotifyContext(context.Background(), config.Signals...)
|
|
defer stop()
|
|
|
|
errCh := make(chan error, 1)
|
|
go func() {
|
|
if err := engine.Run(addr); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
|
errCh <- err
|
|
}
|
|
close(errCh)
|
|
}()
|
|
|
|
select {
|
|
case err := <-errCh:
|
|
return err
|
|
case <-ctx.Done():
|
|
}
|
|
|
|
shutdownCtx, cancel := context.WithTimeout(context.Background(), config.Timeout)
|
|
defer cancel()
|
|
|
|
return engine.Shutdown(shutdownCtx)
|
|
}
|