From 5a644b0856661513908e500f01de25a1ec907786 Mon Sep 17 00:00:00 2001 From: James Read Date: Sat, 20 Apr 2024 00:11:40 +0100 Subject: [PATCH] bugfix: The web interface now refreshes when the config file is changed! (#281) --- OliveTin.proto | 2 ++ cmd/OliveTin/main.go | 1 + internal/config/config_reloader.go | 10 ++++++++++ internal/websocket/websocket.go | 25 +++++++++++++++++-------- webui.dev/js/websocket.js | 1 + webui.dev/main.js | 2 ++ 6 files changed, 33 insertions(+), 8 deletions(-) diff --git a/OliveTin.proto b/OliveTin.proto index 0bc72b9..e37dcbb 100644 --- a/OliveTin.proto +++ b/OliveTin.proto @@ -184,6 +184,8 @@ message GetReadyzResponse { string status = 1; } +message EventConfigChanged {} + service OliveTinApiService { rpc GetDashboardComponents(GetDashboardComponentsRequest) returns (GetDashboardComponentsResponse) { option (google.api.http) = { diff --git a/cmd/OliveTin/main.go b/cmd/OliveTin/main.go index e59b9a4..4ab3a2c 100644 --- a/cmd/OliveTin/main.go +++ b/cmd/OliveTin/main.go @@ -137,6 +137,7 @@ func main() { executor := executor.DefaultExecutor() executor.AddListener(websocket.ExecutionListener) + config.AddListener(websocket.OnConfigChanged) go onstartup.Execute(cfg, executor) go oncron.Schedule(cfg, executor) diff --git a/internal/config/config_reloader.go b/internal/config/config_reloader.go index 4fc7a31..5042d12 100644 --- a/internal/config/config_reloader.go +++ b/internal/config/config_reloader.go @@ -21,8 +21,14 @@ var ( Name: "olivetin_config_reloaded_count", Help: "The number of times the config has been reloaded", }) + + listeners []func() ) +func AddListener(l func()) { + listeners = append(listeners, l) +} + func Reload(cfg *Config) { if err := viper.UnmarshalExact(&cfg); err != nil { log.Errorf("Config unmarshal error %+v", err) @@ -34,4 +40,8 @@ func Reload(cfg *Config) { cfg.SetDir(path.Dir(viper.ConfigFileUsed())) cfg.Sanitize() + + for _, l := range listeners { + l() + } } diff --git a/internal/websocket/websocket.go b/internal/websocket/websocket.go index f2b3db4..7499571 100644 --- a/internal/websocket/websocket.go +++ b/internal/websocket/websocket.go @@ -6,6 +6,7 @@ import ( ws "github.com/gorilla/websocket" log "github.com/sirupsen/logrus" "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/reflect/protoreflect" "net/http" ) @@ -24,6 +25,12 @@ var marshalOptions = protojson.MarshalOptions{ EmitUnpopulated: true, } +func OnConfigChanged() { + evt := &pb.EventConfigChanged{} + + broadcast(evt) +} + var ExecutionListener WebsocketExecutionListener type WebsocketExecutionListener struct{} @@ -72,12 +79,19 @@ func (WebsocketExecutionListener) OnExecutionFinished(logEntry *executor.Interna ExecutionFinished: logEntry.ExecutionFinished, } - broadcast("ExecutionFinished", le) + broadcast(le) } -func broadcast(messageType string, pbmsg *pb.LogEntry) { +func broadcast(pbmsg protoreflect.ProtoMessage) { payload, err := marshalOptions.Marshal(pbmsg) + if err != nil { + log.Errorf("websocket marshal error: %v", err) + return + } + + messageType := pbmsg.ProtoReflect().Descriptor().FullName() + // // So, the websocket wants to encode messages using the same protomarshaller // as the REST API - this gives consistency instead of using encoding/json @@ -97,13 +111,8 @@ func broadcast(messageType string, pbmsg *pb.LogEntry) { hackyMessage = append(hackyMessage, []byte("}")...) // - if err != nil { - log.Errorf("websocket marshal error: %v", err) - return - } - for _, client := range clients { - client.conn.WriteMessage(1, hackyMessage) + client.conn.WriteMessage(ws.TextMessage, hackyMessage) } } diff --git a/webui.dev/js/websocket.js b/webui.dev/js/websocket.js index bb81002..c7a47e5 100644 --- a/webui.dev/js/websocket.js +++ b/webui.dev/js/websocket.js @@ -40,6 +40,7 @@ function websocketOnMessage (msg) { e.payload = j.payload switch (j.type) { + case 'EventConfigChanged': case 'ExecutionFinished': window.dispatchEvent(e) break diff --git a/webui.dev/main.js b/webui.dev/main.js index 6895065..d4e2e3a 100644 --- a/webui.dev/main.js +++ b/webui.dev/main.js @@ -134,6 +134,8 @@ function main () { initMarshaller() setupLogSearchBox() + window.addEventListener('EventConfigChanged', fetchGetDashboardComponents) // For websocket + window.fetch('webUiSettings.json').then(res => { return res.json() }).then(res => {