fix: Fix broken shutdown handler

This is a #PATCH release.
This commit is contained in:
Harrison (Harry) Cramer
2024-09-14 18:34:05 -04:00
committed by GitHub
parent 22bfd0c83e
commit dba15127fe
3 changed files with 21 additions and 54 deletions

View File

@@ -18,7 +18,7 @@ to handle potential shutdown requests and incoming HTTP requests.
*/ */
func StartServer(client *Client, projectInfo *ProjectInfo, GitInfo git.GitData) { func StartServer(client *Client, projectInfo *ProjectInfo, GitInfo git.GitData) {
s := shutdown{ s := shutdownService{
sigCh: make(chan os.Signal, 1), sigCh: make(chan os.Signal, 1),
} }
@@ -26,7 +26,7 @@ func StartServer(client *Client, projectInfo *ProjectInfo, GitInfo git.GitData)
r := CreateRouter( r := CreateRouter(
client, client,
projectInfo, projectInfo,
s, &s,
func(a *data) error { a.projectInfo = projectInfo; return nil }, func(a *data) error { a.projectInfo = projectInfo; return nil },
func(a *data) error { a.gitInfo = &GitInfo; return nil }, func(a *data) error { a.gitInfo = &GitInfo; return nil },
func(a *data) error { err := attachEmojis(a, fr); return err }, func(a *data) error { err := attachEmojis(a, fr); return err },
@@ -39,10 +39,8 @@ func StartServer(client *Client, projectInfo *ProjectInfo, GitInfo git.GitData)
go func() { go func() {
err := server.Serve(l) err := server.Serve(l)
if err != nil { if err != nil {
if errors.Is(err, http.ErrServerClosed) { if !errors.Is(err, http.ErrServerClosed) {
os.Exit(0) fmt.Fprintf(os.Stderr, "Server crashed: %s\n", err)
} else {
fmt.Fprintf(os.Stderr, "Server did not respond: %s\n", err)
os.Exit(1) os.Exit(1)
} }
} }
@@ -76,7 +74,7 @@ type data struct {
type optFunc func(a *data) error type optFunc func(a *data) error
func CreateRouter(gitlabClient *Client, projectInfo *ProjectInfo, s ShutdownHandler, optFuncs ...optFunc) http.Handler { func CreateRouter(gitlabClient *Client, projectInfo *ProjectInfo, s *shutdownService, optFuncs ...optFunc) http.Handler {
m := http.NewServeMux() m := http.NewServeMux()
d := data{ d := data{
@@ -188,7 +186,6 @@ func CreateRouter(gitlabClient *Client, projectInfo *ProjectInfo, s ShutdownHand
withPayloadValidation(methodToPayload{http.MethodPost: &DraftNotePublishRequest{}}), withPayloadValidation(methodToPayload{http.MethodPost: &DraftNotePublishRequest{}}),
withMethodCheck(http.MethodPost), withMethodCheck(http.MethodPost),
)) ))
m.HandleFunc("/pipeline", middleware( m.HandleFunc("/pipeline", middleware(
pipelineService{d, gitlabClient, git.Git{}}, pipelineService{d, gitlabClient, git.Git{}},
withMethodCheck(http.MethodGet), withMethodCheck(http.MethodGet),
@@ -230,8 +227,12 @@ func CreateRouter(gitlabClient *Client, projectInfo *ProjectInfo, s ShutdownHand
withPayloadValidation(methodToPayload{http.MethodPost: &MergeRequestByUsernameRequest{}}), withPayloadValidation(methodToPayload{http.MethodPost: &MergeRequestByUsernameRequest{}}),
withMethodCheck(http.MethodPost), withMethodCheck(http.MethodPost),
)) ))
m.HandleFunc("/shutdown", middleware(
*s,
withPayloadValidation(methodToPayload{http.MethodPost: &ShutdownRequest{}}),
withMethodCheck(http.MethodPost),
))
m.HandleFunc("/shutdown", s.shutdownHandler)
m.Handle("/ping", http.HandlerFunc(pingHandler)) m.Handle("/ping", http.HandlerFunc(pingHandler))
return LoggingServer{handler: m} return LoggingServer{handler: m}

View File

@@ -3,9 +3,7 @@ package app
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"io"
"net/http" "net/http"
"os" "os"
) )
@@ -19,22 +17,20 @@ func (k killer) String() string {
type ShutdownHandler interface { type ShutdownHandler interface {
WatchForShutdown(server *http.Server) WatchForShutdown(server *http.Server)
shutdownHandler(w http.ResponseWriter, r *http.Request) ServeHTTP(w http.ResponseWriter, r *http.Request)
} }
type shutdown struct { type shutdownService struct {
sigCh chan os.Signal sigCh chan os.Signal
} }
func (s shutdown) WatchForShutdown(server *http.Server) { func (s shutdownService) WatchForShutdown(server *http.Server) {
/* Handles shutdown requests */ /* Handles shutdown requests */
<-s.sigCh <-s.sigCh
err := server.Shutdown(context.Background()) err := server.Shutdown(context.Background())
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "Server could not shut down gracefully: %s\n", err) fmt.Fprintf(os.Stderr, "Server could not shut down gracefully: %s\n", err)
os.Exit(1) os.Exit(1)
} else {
os.Exit(0)
} }
} }
@@ -42,36 +38,20 @@ type ShutdownRequest struct {
Restart bool `json:"restart"` Restart bool `json:"restart"`
} }
/* shutdownHandler will shutdown the HTTP server and exit the process by signaling to the shutdown channel */ /* Shuts down the HTTP server and exit the process by signaling to the shutdown channel */
func (s shutdown) shutdownHandler(w http.ResponseWriter, r *http.Request) { func (s shutdownService) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
w.Header().Set("Allow", http.MethodPost)
handleError(w, errors.New("Invalid request type"), "That request type is not allowed", http.StatusMethodNotAllowed)
return
}
body, err := io.ReadAll(r.Body) payload := r.Context().Value(payload("payload")).(*ShutdownRequest)
if err != nil {
handleError(w, err, "Could not read request body", http.StatusBadRequest)
return
}
var shutdownRequest ShutdownRequest
err = json.Unmarshal(body, &shutdownRequest)
if err != nil {
handleError(w, err, "Could not unmarshal data from request body", http.StatusBadRequest)
return
}
var text = "Shut down server" var text = "Shut down server"
if shutdownRequest.Restart { if payload.Restart {
text = "Restarted server" text = "Restarted server"
} }
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
response := SuccessResponse{Message: text} response := SuccessResponse{Message: text}
err = json.NewEncoder(w).Encode(response) err := json.NewEncoder(w).Encode(response)
if err != nil { if err != nil {
handleError(w, err, "Could not encode response", http.StatusInternalServerError) handleError(w, err, "Could not encode response", http.StatusInternalServerError)
} else { } else {

View File

@@ -22,7 +22,7 @@ Table of Contents *gitlab.nvim.table-of-contents*
- Creating an MR |gitlab.nvim.creating-an-mr| - Creating an MR |gitlab.nvim.creating-an-mr|
- Pipelines |gitlab.nvim.pipelines| - Pipelines |gitlab.nvim.pipelines|
- Reviewers and Assignees |gitlab.nvim.reviewers-and-assignees| - Reviewers and Assignees |gitlab.nvim.reviewers-and-assignees|
- Restarting or Shutting Down |gitlab.nvim.restarting-or-shutting-down| - Restarting The Go Server |gitlab.nvim.restarting|
- Keybindings |gitlab.nvim.keybindings| - Keybindings |gitlab.nvim.keybindings|
- Troubleshooting |gitlab.nvim.troubleshooting| - Troubleshooting |gitlab.nvim.troubleshooting|
- Api |gitlab.nvim.api| - Api |gitlab.nvim.api|
@@ -591,26 +591,12 @@ install `dressing.nvim`. If you use Dressing, please enable it:
}) })
< <
RESTARTING OR SHUTTING DOWN *gitlab.nvim.restarting-or-shutting-down* RESTARTING THE GO SERVER *gitlab.nvim.restarting*
The `gitlab.nvim` server will shut down automatically when you exit Neovim. The `gitlab.nvim` server will shut down automatically when you exit Neovim.
However, if you would like to manage this yourself (for instance, restart the You may restart the server at any time via the the `restart` command:
server when you check out a new branch) you may do so via the `restart`
command, or `shutdown` commands, which both accept callbacks:
>lua >lua
require("gitlab.server").restart() require("gitlab.server").restart()
require("gitlab.server").shutdown()
<
For instance you could set up the following keybinding to close and reopen the
reviewer when checking out a new branch:
>lua
local gitlab = require("gitlab")
vim.keymap.set("n", "glB", function ()
require("gitlab.server").restart(function ()
vim.cmd.tabclose()
gitlab.review() -- Reopen the reviewer after the server restarts
end)
end)
< <
KEYBINDINGS *gitlab.nvim.keybindings* KEYBINDINGS *gitlab.nvim.keybindings*