mirror of
https://git.sr.ht/~ashkeel/strimertul
synced 2024-09-20 02:00:49 +00:00
fix: server config doesn't get half-changed in case of error
This commit is contained in:
parent
db31c75662
commit
a99f944f33
1 changed files with 29 additions and 21 deletions
|
@ -8,6 +8,8 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/pprof"
|
"net/http/pprof"
|
||||||
|
|
||||||
|
"github.com/strimertul/strimertul/utils"
|
||||||
|
|
||||||
"git.sr.ht/~hamcha/containers"
|
"git.sr.ht/~hamcha/containers"
|
||||||
jsoniter "github.com/json-iterator/go"
|
jsoniter "github.com/json-iterator/go"
|
||||||
"github.com/strimertul/strimertul/database"
|
"github.com/strimertul/strimertul/database"
|
||||||
|
@ -20,14 +22,14 @@ import (
|
||||||
var json = jsoniter.ConfigFastest
|
var json = jsoniter.ConfigFastest
|
||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
Config ServerConfig
|
Config *containers.RWSync[ServerConfig]
|
||||||
db *database.LocalDBClient
|
db *database.LocalDBClient
|
||||||
logger *zap.Logger
|
logger *zap.Logger
|
||||||
server *http.Server
|
server *http.Server
|
||||||
frontend fs.FS
|
frontend fs.FS
|
||||||
hub *kv.Hub
|
hub *kv.Hub
|
||||||
mux *http.ServeMux
|
mux *http.ServeMux
|
||||||
requestedRoutes map[string]http.Handler
|
requestedRoutes *containers.SyncMap[string, http.Handler]
|
||||||
cancelConfigSub database.CancelFunc
|
cancelConfigSub database.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,17 +38,18 @@ func NewServer(db *database.LocalDBClient, logger *zap.Logger) (*Server, error)
|
||||||
logger: logger,
|
logger: logger,
|
||||||
db: db,
|
db: db,
|
||||||
server: &http.Server{},
|
server: &http.Server{},
|
||||||
requestedRoutes: make(map[string]http.Handler),
|
requestedRoutes: containers.NewSyncMap[string, http.Handler](),
|
||||||
|
Config: containers.NewRWSync(ServerConfig{}),
|
||||||
}
|
}
|
||||||
|
|
||||||
err := db.GetJSON(ServerConfigKey, &server.Config)
|
err := utils.LoadJSONToWrapped[ServerConfig](ServerConfigKey, server.Config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Initialize with default config
|
// Initialize with default config
|
||||||
server.Config = ServerConfig{
|
server.Config.Set(ServerConfig{
|
||||||
Bind: "localhost:4337",
|
Bind: "localhost:4337",
|
||||||
EnableStaticServer: false,
|
EnableStaticServer: false,
|
||||||
KVPassword: "",
|
KVPassword: "",
|
||||||
}
|
})
|
||||||
// Save
|
// Save
|
||||||
err = db.PutJSON(ServerConfigKey, server.Config)
|
err = db.PutJSON(ServerConfigKey, server.Config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -59,7 +62,7 @@ func NewServer(db *database.LocalDBClient, logger *zap.Logger) (*Server, error)
|
||||||
|
|
||||||
// Set password
|
// Set password
|
||||||
server.hub.SetOptions(kv.HubOptions{
|
server.hub.SetOptions(kv.HubOptions{
|
||||||
Password: server.Config.KVPassword,
|
Password: server.Config.Get().KVPassword,
|
||||||
})
|
})
|
||||||
|
|
||||||
return server, nil
|
return server, nil
|
||||||
|
@ -100,10 +103,11 @@ func (s *Server) makeMux() *http.ServeMux {
|
||||||
kv.ServeWs(s.hub, w, r)
|
kv.ServeWs(s.hub, w, r)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if s.Config.EnableStaticServer {
|
config := s.Config.Get()
|
||||||
mux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir(s.Config.Path))))
|
if config.EnableStaticServer {
|
||||||
|
mux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir(config.Path))))
|
||||||
}
|
}
|
||||||
for route, handler := range s.requestedRoutes {
|
for route, handler := range s.requestedRoutes.Copy() {
|
||||||
mux.Handle(route, handler)
|
mux.Handle(route, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,12 +115,12 @@ func (s *Server) makeMux() *http.ServeMux {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) RegisterRoute(route string, handler http.Handler) {
|
func (s *Server) RegisterRoute(route string, handler http.Handler) {
|
||||||
s.requestedRoutes[route] = handler
|
s.requestedRoutes.SetKey(route, handler)
|
||||||
s.mux = s.makeMux()
|
s.mux = s.makeMux()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) UnregisterRoute(route string) {
|
func (s *Server) UnregisterRoute(route string) {
|
||||||
delete(s.requestedRoutes, route)
|
s.requestedRoutes.DeleteKey(route)
|
||||||
s.mux = s.makeMux()
|
s.mux = s.makeMux()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,22 +130,25 @@ func (s *Server) Listen() error {
|
||||||
exit := make(chan error)
|
exit := make(chan error)
|
||||||
var err error
|
var err error
|
||||||
err, s.cancelConfigSub = s.db.SubscribeKey(ServerConfigKey, func(value string) {
|
err, s.cancelConfigSub = s.db.SubscribeKey(ServerConfigKey, func(value string) {
|
||||||
oldBind := s.Config.Bind
|
oldConfig := s.Config.Get()
|
||||||
oldPassword := s.Config.KVPassword
|
|
||||||
err := json.Unmarshal([]byte(value), &s.Config)
|
var config ServerConfig
|
||||||
|
err := json.Unmarshal([]byte(value), &config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.logger.Error("Failed to unmarshal config", zap.Error(err))
|
s.logger.Error("Failed to unmarshal config", zap.Error(err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s.Config.Set(config)
|
||||||
s.mux = s.makeMux()
|
s.mux = s.makeMux()
|
||||||
// Restart hub if password changed
|
// Restart hub if password changed
|
||||||
if oldPassword != s.Config.KVPassword {
|
if oldConfig.KVPassword != config.KVPassword {
|
||||||
s.hub.SetOptions(kv.HubOptions{
|
s.hub.SetOptions(kv.HubOptions{
|
||||||
Password: s.Config.KVPassword,
|
Password: config.KVPassword,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// Restart server if bind changed
|
// Restart server if bind changed
|
||||||
if oldBind != s.Config.Bind {
|
if oldConfig.Bind != config.Bind {
|
||||||
restart.Set(true)
|
restart.Set(true)
|
||||||
err = s.server.Shutdown(context.Background())
|
err = s.server.Shutdown(context.Background())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -155,13 +162,14 @@ func (s *Server) Listen() error {
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
s.logger.Info("Starting HTTP server", zap.String("bind", s.Config.Bind))
|
config := s.Config.Get()
|
||||||
|
s.logger.Info("Starting HTTP server", zap.String("bind", config.Bind))
|
||||||
s.mux = s.makeMux()
|
s.mux = s.makeMux()
|
||||||
s.server = &http.Server{
|
s.server = &http.Server{
|
||||||
Handler: s,
|
Handler: s,
|
||||||
Addr: s.Config.Bind,
|
Addr: config.Bind,
|
||||||
}
|
}
|
||||||
s.logger.Info("HTTP server started", zap.String("bind", s.Config.Bind))
|
s.logger.Info("HTTP server started", zap.String("bind", config.Bind))
|
||||||
err := s.server.ListenAndServe()
|
err := s.server.ListenAndServe()
|
||||||
s.logger.Debug("HTTP server died", zap.Error(err))
|
s.logger.Debug("HTTP server died", zap.Error(err))
|
||||||
if err != nil && !errors.Is(err, http.ErrServerClosed) {
|
if err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||||
|
|
Loading…
Reference in a new issue