Implement graceful server shutdown.
This gives the user a friendly message when the server shuts down.
This commit is contained in:
1 parent
7707775cca
commit
e37e27036e
5 files changed
+41
-7
No files matched your search
@@ -12,3 +12,7 @@ type client interface {
|
||||
pushConn(id string, conn upConnection, tracks []upTrack, label string) error
|
||||
pushClient(id, username string, add bool) error
|
||||
}
|
||||
|
||||
type kickable interface {
|
||||
kick(message string) error
|
||||
}
|
||||
@@ -64,7 +64,7 @@ type connectionFailedAction struct {
|
||||
|
||||
type permissionsChangedAction struct{}
|
||||
|
||||
type kickAction struct{
|
||||
type kickAction struct {
|
||||
message string
|
||||
}
|
||||
|
||||
@@ -288,6 +288,16 @@ func (g *group) Range(f func(c client) bool) {
|
||||
}
|
||||
}
|
||||
|
||||
func (g *group) shutdown(message string) {
|
||||
g.Range(func(c client) bool {
|
||||
cc, ok := c.(kickable)
|
||||
if ok {
|
||||
cc.kick(message)
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
const maxChatHistory = 20
|
||||
|
||||
func (g *group) clearChatHistory() {
|
||||
|
||||
@@ -87,6 +87,7 @@ func main() {
|
||||
webserver()
|
||||
|
||||
terminate := make(chan os.Signal, 1)
|
||||
signal.Notify(terminate, syscall.SIGINT)
|
||||
signal.Notify(terminate, syscall.SIGINT, syscall.SIGTERM)
|
||||
<-terminate
|
||||
shutdown()
|
||||
}
|
||||
+7
-3
@@ -943,6 +943,10 @@ func setPermissions(g *group, id string, perm string) error {
|
||||
return c.action(permissionsChangedAction{})
|
||||
}
|
||||
|
||||
func (c *webClient) kick(message string) error {
|
||||
return c.action(kickAction{message})
|
||||
}
|
||||
|
||||
func kickClient(g *group, id string, message string) error {
|
||||
g.mu.Lock()
|
||||
defer g.mu.Unlock()
|
||||
@@ -952,12 +956,12 @@ func kickClient(g *group, id string, message string) error {
|
||||
return userError("no such user")
|
||||
}
|
||||
|
||||
c, ok := client.(*webClient)
|
||||
c, ok := client.(kickable)
|
||||
if !ok {
|
||||
return userError("this is not a real user")
|
||||
return userError("this client is not kickable")
|
||||
}
|
||||
|
||||
return c.action(kickAction{message})
|
||||
return c.kick(message)
|
||||
}
|
||||
|
||||
func handleClientMessage(c *webClient, m clientMessage) error {
|
||||
|
||||
+17
-2
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -19,6 +20,8 @@ import (
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
var server *http.Server
|
||||
|
||||
func webserver() {
|
||||
http.Handle("/", mungeHandler{http.FileServer(http.Dir(staticRoot))})
|
||||
http.HandleFunc("/group/", groupHandler)
|
||||
@@ -39,17 +42,24 @@ func webserver() {
|
||||
http.HandleFunc("/stats", statsHandler)
|
||||
|
||||
go func() {
|
||||
server := &http.Server{
|
||||
server = &http.Server{
|
||||
Addr: httpAddr,
|
||||
ReadHeaderTimeout: 60 * time.Second,
|
||||
IdleTimeout: 120 * time.Second,
|
||||
}
|
||||
server.RegisterOnShutdown(func() {
|
||||
groups.mu.Lock()
|
||||
defer groups.mu.Unlock()
|
||||
for _, g := range groups.groups {
|
||||
go g.shutdown("server is shutting down")
|
||||
}
|
||||
})
|
||||
var err error
|
||||
err = server.ListenAndServeTLS(
|
||||
filepath.Join(dataDir, "cert.pem"),
|
||||
filepath.Join(dataDir, "key.pem"),
|
||||
)
|
||||
if err != nil {
|
||||
if err != nil && err != http.ErrServerClosed {
|
||||
log.Printf("ListenAndServeTLS: %v", err)
|
||||
}
|
||||
}()
|
||||
@@ -457,3 +467,8 @@ func serveGroupRecordings(w http.ResponseWriter, r *http.Request, f *os.File, gr
|
||||
fmt.Fprintf(w, "</table>\n")
|
||||
fmt.Fprintf(w, "</body></html>\n")
|
||||
}
|
||||
|
||||
func shutdown() {
|
||||
ctx, _ := context.WithTimeout(context.Background(), 2*time.Second)
|
||||
server.Shutdown(ctx)
|
||||
}
|
||||
Reference in new issue
Block a user