|
|
@ -34,6 +34,67 @@ func (ch *CaddyHugo) LTime() uint64 { |
|
|
|
return ch.ltime |
|
|
|
return ch.ltime |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (ch *CaddyHugo) ShouldApply(ltime uint64) bool { |
|
|
|
|
|
|
|
lowest := ch.LowestPendingConfirmation() |
|
|
|
|
|
|
|
for _, c := range ch.Confirming() { |
|
|
|
|
|
|
|
if lowest == 0 || c < lowest { |
|
|
|
|
|
|
|
lowest = c |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ltime < lowest { |
|
|
|
|
|
|
|
return false |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ch.mtx.Lock() |
|
|
|
|
|
|
|
defer ch.mtx.Unlock() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if _, ok := ch.confirmingToClient[ltime]; ok { |
|
|
|
|
|
|
|
return false |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (ch *CaddyHugo) ConfirmLTime(ltime uint64) { |
|
|
|
|
|
|
|
ch.mtx.Lock() |
|
|
|
|
|
|
|
defer ch.mtx.Unlock() |
|
|
|
|
|
|
|
ch.confirmingToClient[ltime] = struct{}{} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (ch *CaddyHugo) Confirming() []uint64 { |
|
|
|
|
|
|
|
var times []uint64 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ch.mtx.Lock() |
|
|
|
|
|
|
|
defer ch.mtx.Unlock() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for ltime := range ch.confirmingToClient { |
|
|
|
|
|
|
|
times = append(times, ltime) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return times |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (ch *CaddyHugo) LowestPendingConfirmation() uint64 { |
|
|
|
|
|
|
|
var lowest uint64 |
|
|
|
|
|
|
|
for _, c := range ch.Confirming() { |
|
|
|
|
|
|
|
if lowest == 0 || c < lowest { |
|
|
|
|
|
|
|
lowest = c |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return lowest |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (ch *CaddyHugo) ClearConfirmed(lowestPending uint64) { |
|
|
|
|
|
|
|
ch.mtx.Lock() |
|
|
|
|
|
|
|
defer ch.mtx.Unlock() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for ltime := range ch.confirmingToClient { |
|
|
|
|
|
|
|
if ltime < lowestPending { |
|
|
|
|
|
|
|
delete(ch.confirmingToClient, ltime) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (ch *CaddyHugo) DeltaWebsocket(w http.ResponseWriter, r *http.Request) (int, error) { |
|
|
|
func (ch *CaddyHugo) DeltaWebsocket(w http.ResponseWriter, r *http.Request) (int, error) { |
|
|
|
var upgrader = websocket.Upgrader{ |
|
|
|
var upgrader = websocket.Upgrader{ |
|
|
|
ReadBufferSize: 1024, |
|
|
|
ReadBufferSize: 1024, |
|
|
@ -61,6 +122,8 @@ func (ch *CaddyHugo) Message(deltas ...acedoc.Delta) Message { |
|
|
|
return Message{ |
|
|
|
return Message{ |
|
|
|
Deltas: deltas, |
|
|
|
Deltas: deltas, |
|
|
|
LTime: ch.LTime(), |
|
|
|
LTime: ch.LTime(), |
|
|
|
|
|
|
|
Confirmed: ch.Confirming(), |
|
|
|
|
|
|
|
LowestPending: ch.LowestPendingConfirmation(), |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -125,12 +188,19 @@ func (ch *CaddyHugo) handleDeltaConn(conn DeltaConn, doc *editSession) (int, err |
|
|
|
continue |
|
|
|
continue |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if !ch.ShouldApply(message.LTime) { |
|
|
|
|
|
|
|
continue |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
err = client.PushDeltas(message.Deltas...) |
|
|
|
err = client.PushDeltas(message.Deltas...) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
errCh <- fmt.Errorf("error pushing deltas into document: %v", err) |
|
|
|
errCh <- fmt.Errorf("error pushing deltas into document: %v", err) |
|
|
|
return |
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ch.ConfirmLTime(message.LTime) |
|
|
|
|
|
|
|
ch.ClearConfirmed(message.LowestPending) |
|
|
|
|
|
|
|
|
|
|
|
select { |
|
|
|
select { |
|
|
|
case readMessagesCh <- message: |
|
|
|
case readMessagesCh <- message: |
|
|
|
case <-doneCh: |
|
|
|
case <-doneCh: |
|
|
@ -165,4 +235,6 @@ func (ch *CaddyHugo) handleDeltaConn(conn DeltaConn, doc *editSession) (int, err |
|
|
|
type Message struct { |
|
|
|
type Message struct { |
|
|
|
Deltas []acedoc.Delta `json:"deltas"` |
|
|
|
Deltas []acedoc.Delta `json:"deltas"` |
|
|
|
LTime uint64 `json:"ltime"` |
|
|
|
LTime uint64 `json:"ltime"` |
|
|
|
|
|
|
|
Confirmed []uint64 `json:"confirmed"` |
|
|
|
|
|
|
|
LowestPending uint64 `json:"lowestPending"` |
|
|
|
} |
|
|
|
} |
|
|
|