Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make livereloading of watched dashboards more reliable #514

Merged
merged 2 commits into from
Oct 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ require (
github.com/go-openapi/runtime v0.28.0
github.com/gobwas/glob v0.2.3
github.com/google/go-jsonnet v0.20.0
github.com/google/uuid v1.6.0
github.com/gorilla/websocket v1.5.1
github.com/grafana/grafana-openapi-client-go v0.0.0-20240325012504-4958bdd139e7
github.com/grafana/synthetic-monitoring-agent v0.23.1
Expand Down Expand Up @@ -51,6 +50,7 @@ require (
github.com/go-openapi/validate v0.24.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
Expand Down
69 changes: 69 additions & 0 deletions internal/livereload/connection.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Copyright 2015 The Hugo Authors. All rights reserved.
K-Phoen marked this conversation as resolved.
Show resolved Hide resolved
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Original file: https://github.com/gohugoio/hugo/blob/89bd025ebfd2c559039826641702941fc35a7fdb/livereload/connection.go
// No changes were made.

package livereload

import (
"bytes"
"sync"

"github.com/gorilla/websocket"
)

type connection struct {
// The websocket connection.
ws *websocket.Conn

// Buffered channel of outbound messages.
send chan []byte

// There is a potential data race, especially visible with large files.
// This is protected by synchronization of the send channel's close.
closer sync.Once
}

func (c *connection) close() {
c.closer.Do(func() {
close(c.send)
})
}

func (c *connection) reader() {
for {
_, message, err := c.ws.ReadMessage()
if err != nil {
break
}
if bytes.Contains(message, []byte(`"command":"hello"`)) {
c.send <- []byte(`{
"command": "hello",
"protocols": ["http://livereload.com/protocols/official-7"],
"serverName": "Grizzly"
}`)
}
}
c.ws.Close()
}

func (c *connection) writer() {
for message := range c.send {
err := c.ws.WriteMessage(websocket.TextMessage, message)
if err != nil {
break
}
}
c.ws.Close()
}
59 changes: 59 additions & 0 deletions internal/livereload/hub.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright 2015 The Hugo Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Original file: https://github.com/gohugoio/hugo/blob/89bd025ebfd2c559039826641702941fc35a7fdb/livereload/hub.go
// No changes were made.

package livereload

type hub struct {
// Registered connections.
connections map[*connection]bool

// Inbound messages from the connections.
broadcast chan []byte

// Register requests from the connections.
register chan *connection

// Unregister requests from connections.
unregister chan *connection
}

var wsHub = hub{
broadcast: make(chan []byte),
register: make(chan *connection),
unregister: make(chan *connection),
connections: make(map[*connection]bool),
}

func (h *hub) run() {
for {
select {
case c := <-h.register:
h.connections[c] = true
case c := <-h.unregister:
delete(h.connections, c)
c.close()
case m := <-h.broadcast:
for c := range h.connections {
select {
case c.send <- m:
default:
delete(h.connections, c)
c.close()
}
}
}
}
}
52 changes: 52 additions & 0 deletions internal/livereload/livereload.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright 2015 The Hugo Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Original file: https://github.com/gohugoio/hugo/blob/89bd025ebfd2c559039826641702941fc35a7fdb/livereload/livereload.go

package livereload

import (
"fmt"
"net/http"

"github.com/gorilla/websocket"
)

// Initialize starts the Websocket Hub handling live reloads.
// Original: https://github.com/gohugoio/hugo/blob/89bd025ebfd2c559039826641702941fc35a7fdb/livereload/livereload.go#L107
func Initialize() {
go wsHub.run()
}

// Handler is a HandlerFunc handling the livereload
// Websocket interaction.
// Original: https://github.com/gohugoio/hugo/blob/89bd025ebfd2c559039826641702941fc35a7fdb/livereload/livereload.go#L93-L105
// Our version is modified to accept a websocket upgrader coming from the server.
func Handler(upgrader *websocket.Upgrader) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ws, err := upgrader.Upgrade(w, r, nil)
if err != nil {
return
}
c := &connection{send: make(chan []byte, 256), ws: ws}
wsHub.register <- c
defer func() { wsHub.unregister <- c }()
go c.writer()
c.reader()
}
}

func ReloadDashboard(uid string) {
msg := fmt.Sprintf(`{"command": "reload", "path": "/grizzly/Dashboard/%s"}`, uid)
wsHub.broadcast <- []byte(msg)
}
46 changes: 40 additions & 6 deletions pkg/grizzly/embed/templates/proxy/iframe.html.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,44 @@
<title>Grizzly</title>
<link rel="stylesheet" href="/grizzly/assets/style.css"/>
</head>
<body>
{{ template "proxy/header.html.tmpl" . }}
<iframe src="{{ .IframeURL }}"></iframe>

<html>
<body>
{{ template "proxy/header.html.tmpl" . }}
<iframe src="{{ .IframeURL }}"></iframe>
</body>
</html>
<script>
window.LiveReloadOptions = {
host: 'localhost',
port: {{ .Port }},
};
</script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/livereload.min.js"></script>
<script>
class CustomReloadPlugin {
constructor (window, host) {
this.window = window;
this.host = host;
}

reload (path, options) {
console.info('reload() path: ', path);
console.info('window.location.pathname', window.location.pathname);

if (path === window.location.pathname) {
this.window.document.location.reload();
}

return true;
}

analyze () {
return {};
}
}

CustomReloadPlugin.identifier = 'custom-reload';
CustomReloadPlugin.version = '1.0';

LiveReload.addPlugin(CustomReloadPlugin);
</script>
</body>
</html>
Loading
Loading