From 64f50cc50414c88ae389d07ae0ea53c58d5d0e94 Mon Sep 17 00:00:00 2001 From: niksis02 Date: Fri, 10 Oct 2025 22:10:56 +0400 Subject: [PATCH] feat: gracul shutdown of s3api and admin servers Implements graceful shutdown for the admin and s3api servers. They are shut down before other components (IAM, s3logger, etc.) to allow the servers to properly handle any pending requests while dependencies are still active. The shutdown process is controlled by a context with a 10-second timeout. If it exceeds this duration, all remaining requests are forcefully terminated and the servers are closed. --- cmd/versitygw/main.go | 26 ++++++++++++++------------ s3api/admin-server.go | 5 +++++ s3api/server.go | 10 ++++++++++ 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/cmd/versitygw/main.go b/cmd/versitygw/main.go index 710b7a1..a1e5990 100644 --- a/cmd/versitygw/main.go +++ b/cmd/versitygw/main.go @@ -832,31 +832,36 @@ Loop: } saveErr := err + // first shut down the s3api and admin servers + // as they have dependecy from other modules + err = srv.ShutDown() + if err != nil { + fmt.Fprintf(os.Stderr, "shutdown api server: %v\n", err) + } + + if admSrv != nil { + err := admSrv.Shutdown() + if err != nil { + fmt.Fprintf(os.Stderr, "shutdown admin server: %v\n", err) + } + } + be.Shutdown() err = iam.Shutdown() if err != nil { - if saveErr == nil { - saveErr = err - } fmt.Fprintf(os.Stderr, "shutdown iam: %v\n", err) } if loggers.S3Logger != nil { err := loggers.S3Logger.Shutdown() if err != nil { - if saveErr == nil { - saveErr = err - } fmt.Fprintf(os.Stderr, "shutdown s3 logger: %v\n", err) } } if loggers.AdminLogger != nil { err := loggers.AdminLogger.Shutdown() if err != nil { - if saveErr == nil { - saveErr = err - } fmt.Fprintf(os.Stderr, "shutdown admin logger: %v\n", err) } } @@ -864,9 +869,6 @@ Loop: if evSender != nil { err := evSender.Close() if err != nil { - if saveErr == nil { - saveErr = err - } fmt.Fprintf(os.Stderr, "close event sender: %v\n", err) } } diff --git a/s3api/admin-server.go b/s3api/admin-server.go index 8fed246..c336e3d 100644 --- a/s3api/admin-server.go +++ b/s3api/admin-server.go @@ -100,3 +100,8 @@ func (sa *S3AdminServer) Serve() (err error) { } return sa.app.Listen(sa.port) } + +// ShutDown gracefully shuts down the server with a context timeout +func (sa S3AdminServer) Shutdown() error { + return sa.app.ShutdownWithTimeout(shutDownDuration) +} diff --git a/s3api/server.go b/s3api/server.go index 99ab140..76f66e2 100644 --- a/s3api/server.go +++ b/s3api/server.go @@ -19,6 +19,7 @@ import ( "errors" "net/http" "strings" + "time" "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/logger" @@ -35,6 +36,10 @@ import ( "github.com/versity/versitygw/s3log" ) +const ( + shutDownDuration = time.Second * 10 +) + type S3ApiServer struct { app *fiber.App backend backend.Backend @@ -167,6 +172,11 @@ func (sa *S3ApiServer) Serve() (err error) { return sa.app.Listen(sa.port) } +// ShutDown gracefully shuts down the server with a context timeout +func (sa *S3ApiServer) ShutDown() error { + return sa.app.ShutdownWithTimeout(shutDownDuration) +} + // stackTraceHandler stores the system panics // in the context locals func stackTraceHandler(ctx *fiber.Ctx, e any) {