package caddyhugo import ( "fmt" "net/http" "time" "git.stephensearles.com/stephen/acedoc" "github.com/gorilla/websocket" ) const ( IdleWebsocketTimeout = 10 * time.Minute WebsocketFileTicker = 1 * time.Second ) func (ch *CaddyHugo) ObserveLTime(ltime uint64) uint64 { ch.mtx.Lock() if ch.ltime < ltime { ch.ltime = ltime } ch.mtx.Unlock() return ch.LTime() } func (ch *CaddyHugo) LTime() uint64 { ch.mtx.Lock() defer ch.mtx.Unlock() ch.ltime++ return ch.ltime } func (ch *CaddyHugo) DeltaWebsocket(w http.ResponseWriter, r *http.Request) (int, error) { var upgrader = websocket.Upgrader{ ReadBufferSize: 1024, WriteBufferSize: 1024, } conn, err := upgrader.Upgrade(w, r, nil) if err != nil { fmt.Println(err) return http.StatusBadRequest, err } doc, err := ch.doc(r) if err != nil { fmt.Println(err) return http.StatusBadRequest, err } const idlePing = 15 * time.Second const idlePingShort = 1 * time.Millisecond var timer *time.Timer timer = time.AfterFunc(idlePing, func() { conn.WriteJSON(Message{ Deltas: []acedoc.Delta{}, LTime: ch.LTime(), }) timer.Reset(idlePing) }) client := doc.doc.Client(acedoc.DeltaHandlerFunc(func(ds []acedoc.Delta) error { timer.Reset(idlePing) err := conn.WriteJSON(Message{ Deltas: ds, LTime: ch.LTime(), }) return err })) ch.mtx.Lock() doc.clients++ ch.mtx.Unlock() defer func() { ch.mtx.Lock() client.Close() doc.clients-- ch.mtx.Unlock() }() for { var message Message err := conn.ReadJSON(&message) if err != nil { return http.StatusBadRequest, err } ch.ObserveLTime(message.LTime) timer.Reset(idlePingShort) err = client.PushDeltas(message.Deltas...) if err != nil { return http.StatusBadRequest, err } } } type Message struct { Deltas []acedoc.Delta `json:"deltas"` LTime uint64 `json:"ltime"` }