···
8
+
"github.com/gorilla/websocket"
11
+
var upgrader = websocket.Upgrader{
12
+
ReadBufferSize: 1024,
13
+
WriteBufferSize: 1024,
16
+
func (h *Handle) OpLog(w http.ResponseWriter, r *http.Request) {
17
+
l := h.l.With("handler", "OpLog")
18
+
l.Info("received new connection")
20
+
conn, err := upgrader.Upgrade(w, r, nil)
22
+
l.Error("websocket upgrade failed", "err", err)
23
+
w.WriteHeader(http.StatusInternalServerError)
27
+
l.Info("upgraded http to wss")
29
+
ch := h.n.Subscribe()
30
+
defer h.n.Unsubscribe(ch)
32
+
ctx, cancel := context.WithCancel(r.Context())
36
+
if _, _, err := conn.NextReader(); err != nil {
37
+
l.Error("failed to read", "err", err)
46
+
// complete backfill first before going to live data
47
+
l.Info("going through backfill", "cursor", cursor)
48
+
if err := h.streamOps(conn, &cursor); err != nil {
49
+
l.Error("failed to backfill", "err", err)
54
+
// wait for new data or timeout
57
+
l.Info("stopping stream: client closed connection")
60
+
// we have been notified of new data
61
+
l.Info("going through live data", "cursor", cursor)
62
+
if err := h.streamOps(conn, &cursor); err != nil {
63
+
l.Error("failed to stream", "err", err)
66
+
case <-time.After(30 * time.Second):
67
+
// send a keep-alive
68
+
l.Info("sent keepalive")
69
+
if err = conn.WriteControl(websocket.PingMessage, []byte{}, time.Now().Add(time.Second)); err != nil {
70
+
l.Error("failed to write control", "err", err)
76
+
func (h *Handle) streamOps(conn *websocket.Conn, cursor *string) error {
77
+
ops, err := h.db.GetOps(*cursor)
79
+
h.l.Debug("err", "err", err)
82
+
h.l.Debug("ops", "ops", ops)
84
+
for _, op := range ops {
85
+
if err := conn.WriteJSON(op); err != nil {
86
+
h.l.Debug("err", "err", err)