move web server to goroutine
This commit is contained in:
parent
2f1267016d
commit
d7ea0508cf
47
cmd/root.go
47
cmd/root.go
@ -1,13 +1,13 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"log/slog"
|
||||
"math/rand"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"git.bloy.org/mike/hasshelper/web"
|
||||
"github.com/spf13/cobra"
|
||||
@ -22,30 +22,32 @@ var rootCmd = &cobra.Command{
|
||||
Run: rootCmdRun,
|
||||
}
|
||||
|
||||
func logLevelVar(str string) slog.Level {
|
||||
levelUpper := strings.ToUpper(str)
|
||||
switch levelUpper {
|
||||
case "DEBUG":
|
||||
return slog.LevelDebug
|
||||
case "INFO":
|
||||
return slog.LevelInfo
|
||||
case "WARN":
|
||||
return slog.LevelWarn
|
||||
case "ERROR":
|
||||
return slog.LevelError
|
||||
default:
|
||||
return slog.LevelInfo
|
||||
}
|
||||
}
|
||||
|
||||
func rootCmdRun(cmd *cobra.Command, args []string) {
|
||||
logLevel := logLevelVar(viper.GetString("loglevel"))
|
||||
var logLevel slog.Level
|
||||
logLevel.UnmarshalText([]byte(viper.GetString("loglevel")))
|
||||
logger := slog.New(slog.NewTextHandler(os.Stdout,
|
||||
&slog.HandlerOptions{Level: logLevel}))
|
||||
logger.Info("HASSHelper startup", "version", viper.GetString("version"))
|
||||
exitchan := make(chan bool)
|
||||
web.Run(logger, exitchan)
|
||||
<-exitchan // run the main command until one of the goroutines is done
|
||||
signalchan := make(chan os.Signal, 1)
|
||||
done := make(chan bool)
|
||||
signal.Notify(signalchan, syscall.SIGINT, syscall.SIGTERM)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
web.Run(logger, exitchan, ctx)
|
||||
go func() {
|
||||
select {
|
||||
case <-signalchan:
|
||||
logger.Warn("received interrupt. Exiting")
|
||||
cancel()
|
||||
done <- true
|
||||
case <-exitchan:
|
||||
logger.Error("unexpected exit of component")
|
||||
cancel()
|
||||
done <- true
|
||||
}
|
||||
}()
|
||||
<-done
|
||||
}
|
||||
|
||||
// Execute will kick off cobra's processing of the root command
|
||||
@ -100,5 +102,4 @@ func initConfig() {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
}
|
||||
|
||||
@ -3,10 +3,12 @@ package web
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
type configObj struct {
|
||||
@ -19,7 +21,7 @@ var config = configObj{}
|
||||
|
||||
// Run starts up the webserver part of hasshelper. It writes to exitch if
|
||||
// the webserver ends unexpectedly. Config values will be read from viper.
|
||||
func Run(rootLogger *slog.Logger, exitch chan bool) {
|
||||
func Run(rootLogger *slog.Logger, exitch chan bool, ctx context.Context) {
|
||||
rootLogger = rootLogger.With("component", "web")
|
||||
config.logger = rootLogger
|
||||
config.port = viper.GetInt("webserver_port")
|
||||
@ -30,15 +32,21 @@ func Run(rootLogger *slog.Logger, exitch chan bool) {
|
||||
var logger = config.logger
|
||||
|
||||
logger.Info("Webserver startup", "port", config.port, "imageDir", config.imageDir)
|
||||
|
||||
addr := fmt.Sprintf(":%d", config.port)
|
||||
|
||||
if err := http.ListenAndServe(addr, middleware(http.DefaultServeMux)); err != nil {
|
||||
logger.Error("Webserver fatal error", "err", err)
|
||||
} else {
|
||||
logger.Info("Webserver shutting down")
|
||||
}
|
||||
exitch <- true
|
||||
go func() {
|
||||
server := http.Server{
|
||||
Addr: fmt.Sprintf(":%d", config.port),
|
||||
Handler: middleware(http.DefaultServeMux),
|
||||
BaseContext: func(net.Listener) context.Context {
|
||||
return ctx
|
||||
},
|
||||
}
|
||||
if err := server.ListenAndServe(); err != nil {
|
||||
logger.Error("Webserver fatal error", "err", err)
|
||||
} else {
|
||||
logger.Info("Webserver shutting down")
|
||||
}
|
||||
exitch <- true
|
||||
}()
|
||||
}
|
||||
|
||||
func middleware(next http.Handler) http.Handler {
|
||||
@ -46,8 +54,7 @@ func middleware(next http.Handler) http.Handler {
|
||||
logger := config.logger.
|
||||
WithGroup("request").
|
||||
With("method", r.Method,
|
||||
"url", r.URL,
|
||||
"remote", r.RemoteAddr)
|
||||
"url", r.URL)
|
||||
logger.Info("Starting web request")
|
||||
start := time.Now()
|
||||
next.ServeHTTP(w, r)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user