feat: make server graceful shutdown timeout configurable
5 files changed, 20 insertions(+), 16 deletions(-)
M defaults.toml → defaults.toml
@@ -3,6 +3,8 @@ DataPath = './data' # Settings for the web server [Web] +# How long to wait for connections to finish before shutting down. +GracefulShutdownTimeout = '5s' # Which address or hostname to listen on. IPv6 addresses need square brackets. ListenAddress = 'localhost' # Port number to listen on.
M internal/config/default.go → internal/config/default.go
@@ -38,6 +38,7 @@ ScriptSrc: []string{}, FormAction: []string{self}, ConnectSrc: []string{self}, }, + GracefulShutdownTimeout: Duration{5 * time.Second}, Headers: map[string]string{ "strict-transport-security": "max-age=" + strconv.FormatFloat( maxAge.Seconds(),
M internal/config/structs.go → internal/config/structs.go
@@ -19,16 +19,17 @@ Importer Importer `comment:"Settings for the import job"` } type Web struct { - ContentSecurityPolicy CSP `comment:"Content-Security-Policy header to send with requests. Should only need changing if ExtraHeadHTML is used."` - ListenAddress string `comment:"Which address or hostname to listen on. IPv6 addresses need square brackets."` - Port int `comment:"Port number to listen on."` - BaseURL URL `comment:"Absolute URL to this instance, useful if behind a reverse proxy"` - SentryDSN string `comment:"If set, will send server errors to Sentry"` - Environment string `comment:"Affects logging parameters. One of 'development' or 'production'"` - ExtraHeadHTML string `comment:"Content to add to HTML <head>. Can be used to override styling, add scripts, etc."` - Headers map[string]string `comment:"Extra headers to send with HTTP requests"` - LogRequests bool `comment:"Whether to log incoming HTTP requests"` - SearchTimeout Duration `comment:"Timeout for search requests"` + ContentSecurityPolicy CSP `comment:"Content-Security-Policy header to send with requests. Should only need changing if ExtraHeadHTML is used."` + GracefulShutdownTimeout Duration `comment:"How long to wait for connections to finish before shutting down."` + ListenAddress string `comment:"Which address or hostname to listen on. IPv6 addresses need square brackets."` + Port int `comment:"Port number to listen on."` + BaseURL URL `comment:"Absolute URL to this instance, useful if behind a reverse proxy"` + SentryDSN string `comment:"If set, will send server errors to Sentry"` + Environment string `comment:"Affects logging parameters. One of 'development' or 'production'"` + ExtraHeadHTML string `comment:"Content to add to HTML <head>. Can be used to override styling, add scripts, etc."` + Headers map[string]string `comment:"Extra headers to send with HTTP requests"` + LogRequests bool `comment:"Whether to log incoming HTTP requests"` + SearchTimeout Duration `comment:"Timeout for search requests"` } type Importer struct {
M internal/server/mux.go → internal/server/mux.go
@@ -7,6 +7,7 @@ "net/http" "path" "slices" "strings" + "time" "alin.ovh/searchix/frontend" "alin.ovh/searchix/internal/config"@@ -34,6 +35,7 @@ cfg.Web.ContentSecurityPolicy.ScriptSrc = append( cfg.Web.ContentSecurityPolicy.ScriptSrc, "'unsafe-inline'", ) + cfg.Web.GracefulShutdownTimeout.Duration = 200 * time.Millisecond } func sortSources(ss map[string]config.Source) {
M internal/server/server.go → internal/server/server.go
@@ -18,8 +18,6 @@ "golang.org/x/net/http2" "golang.org/x/net/http2/h2c" ) -var shutdownTimeout = 10 * time.Second - type Server struct { cfg *config.Config log *log.Logger@@ -92,13 +90,13 @@ func (s *Server) Stop() chan struct{} { s.log.Debug("stop called") idleConnsClosed := make(chan struct{}) - if s.cfg.Web.Environment == "development" { - shutdownTimeout = 1 * time.Millisecond - } go func() { s.log.Debug("shutting down server") - ctx, cancel := context.WithTimeout(context.Background(), shutdownTimeout) + ctx, cancel := context.WithTimeout( + context.Background(), + s.cfg.Web.GracefulShutdownTimeout.Duration, + ) err := s.server.Shutdown(ctx) cancel() s.log.Debug("server shut down")