From 32eaf864268620bcb2b0b24f777029aa5dc3bf4c Mon Sep 17 00:00:00 2001 From: appleboy Date: Sat, 27 Sep 2025 08:56:41 +0000 Subject: [PATCH] feat: implement graceful server shutdown on interrupt or SIGTERM (#98) - Add graceful shutdown for HTTP server on interrupt or SIGTERM signals - Wait for server to finish shutting down before exiting Signed-off-by: appleboy Reviewed-on: https://gitea.com/gitea/gitea-mcp/pulls/98 Co-authored-by: appleboy Co-committed-by: appleboy --- operation/operation.go | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/operation/operation.go b/operation/operation.go index 8a2f59c..3e7715d 100644 --- a/operation/operation.go +++ b/operation/operation.go @@ -4,7 +4,10 @@ import ( "context" "fmt" "net/http" + "os" + "os/signal" "strings" + "syscall" "time" "gitea.com/gitea/gitea-mcp/operation/issue" @@ -100,9 +103,27 @@ func Run() error { server.WithHTTPContextFunc(getContextWithToken), ) log.Infof("Gitea MCP HTTP server listening on :%d", flag.Port) + + // Graceful shutdown setup + sigCh := make(chan os.Signal, 1) + signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM) + shutdownDone := make(chan struct{}) + + go func() { + <-sigCh + log.Infof("Shutdown signal received, gracefully stopping HTTP server...") + shutdownCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + if err := httpServer.Shutdown(shutdownCtx); err != nil { + log.Errorf("HTTP server shutdown error: %v", err) + } + close(shutdownDone) + }() + if err := httpServer.Start(fmt.Sprintf(":%d", flag.Port)); err != nil { return err } + <-shutdownDone // Wait for shutdown to finish default: return fmt.Errorf("invalid transport type: %s. Must be 'stdio' or 'http'", flag.Mode) } @@ -118,4 +139,3 @@ func newMCPServer(version string) *server.MCPServer { server.WithRecovery(), ) } -