mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-07 20:31:06 -05:00
make pollSavedStatus more robust against failure
check last ack timestamp and size of pending op provide method to compute sharejs op size so we can check if pending ops get too big
This commit is contained in:
parent
4623f3cbe7
commit
62b8c30d0b
2 changed files with 36 additions and 4 deletions
|
@ -69,6 +69,12 @@ define [
|
||||||
getPendingOp: () ->
|
getPendingOp: () ->
|
||||||
@doc?.getPendingOp()
|
@doc?.getPendingOp()
|
||||||
|
|
||||||
|
getRecentAck: () ->
|
||||||
|
@doc?.getRecentAck()
|
||||||
|
|
||||||
|
getOpSize: (op) ->
|
||||||
|
@doc?.getOpSize(op)
|
||||||
|
|
||||||
hasBufferedOps: () ->
|
hasBufferedOps: () ->
|
||||||
@doc?.hasBufferedOps()
|
@doc?.hasBufferedOps()
|
||||||
|
|
||||||
|
@ -143,24 +149,35 @@ define [
|
||||||
clearChaosMonkey: () ->
|
clearChaosMonkey: () ->
|
||||||
clearTimeout @_cm
|
clearTimeout @_cm
|
||||||
|
|
||||||
|
MAX_PENDING_OP_SIZE: 30 # pending ops bigger than this are always
|
||||||
|
# considered unsaved
|
||||||
|
|
||||||
pollSavedStatus: () ->
|
pollSavedStatus: () ->
|
||||||
# returns false if doc has ops waiting to be acknowledged or
|
# returns false if doc has ops waiting to be acknowledged or
|
||||||
# sent that haven't changed since the last time we checked.
|
# sent that haven't changed since the last time we checked.
|
||||||
# Otherwise returns true.
|
# Otherwise returns true.
|
||||||
inflightOp = @getInflightOp()
|
inflightOp = @getInflightOp()
|
||||||
pendingOp = @getPendingOp()
|
pendingOp = @getPendingOp()
|
||||||
|
recentAck = @getRecentAck()
|
||||||
|
pendingOpSize = pendingOp? && @getOpSize(pendingOp)
|
||||||
if !inflightOp? and !pendingOp?
|
if !inflightOp? and !pendingOp?
|
||||||
# there's nothing going on
|
# there's nothing going on, this is ok.
|
||||||
saved = true
|
saved = true
|
||||||
sl_console.log "[pollSavedStatus] no inflight or pending ops"
|
sl_console.log "[pollSavedStatus] no inflight or pending ops"
|
||||||
else if inflightOp? and inflightOp == @oldInflightOp
|
else if inflightOp? and inflightOp == @oldInflightOp
|
||||||
# The same inflight op has been sitting unacked since we
|
# The same inflight op has been sitting unacked since we
|
||||||
# last checked.
|
# last checked, this is bad.
|
||||||
saved = false
|
saved = false
|
||||||
sl_console.log "[pollSavedStatus] inflight op is same as before"
|
sl_console.log "[pollSavedStatus] inflight op is same as before"
|
||||||
else
|
else if pendingOp? and recentAck && pendingOpSize < @MAX_PENDING_OP_SIZE
|
||||||
|
# There is an op waiting to go to server but it is small and
|
||||||
|
# within the flushDelay, this is ok for now.
|
||||||
saved = true
|
saved = true
|
||||||
sl_console.log "[pollSavedStatus] assuming saved (inflightOp?: #{inflightOp?}, pendingOp?: #{pendingOp?})"
|
sl_console.log "[pollSavedStatus] pending op (small with recent ack) assume ok", pendingOp, pendingOpSize
|
||||||
|
else
|
||||||
|
# In any other situation, assume the document is unsaved.
|
||||||
|
saved = false
|
||||||
|
sl_console.log "[pollSavedStatus] assuming not saved (inflightOp?: #{inflightOp?}, pendingOp?: #{pendingOp?})"
|
||||||
|
|
||||||
@oldInflightOp = inflightOp
|
@oldInflightOp = inflightOp
|
||||||
return saved
|
return saved
|
||||||
|
|
|
@ -46,6 +46,7 @@ define [
|
||||||
@_doc.on "change", () =>
|
@_doc.on "change", () =>
|
||||||
@trigger "change"
|
@trigger "change"
|
||||||
@_doc.on "acknowledge", () =>
|
@_doc.on "acknowledge", () =>
|
||||||
|
@lastAcked = new Date() # note time of last ack from server
|
||||||
@trigger "acknowledge"
|
@trigger "acknowledge"
|
||||||
@_doc.on "remoteop", () =>
|
@_doc.on "remoteop", () =>
|
||||||
# As soon as we're working with a collaborator, start sending
|
# As soon as we're working with a collaborator, start sending
|
||||||
|
@ -101,12 +102,26 @@ define [
|
||||||
@connection.id = @socket.socket.sessionid
|
@connection.id = @socket.socket.sessionid
|
||||||
@_doc.autoOpen = false
|
@_doc.autoOpen = false
|
||||||
@_doc._connectionStateChanged(state)
|
@_doc._connectionStateChanged(state)
|
||||||
|
@lastAcked = null # reset the last ack time when connection changes
|
||||||
|
|
||||||
hasBufferedOps: () ->
|
hasBufferedOps: () ->
|
||||||
@_doc.inflightOp? or @_doc.pendingOp?
|
@_doc.inflightOp? or @_doc.pendingOp?
|
||||||
|
|
||||||
getInflightOp: () -> @_doc.inflightOp
|
getInflightOp: () -> @_doc.inflightOp
|
||||||
getPendingOp: () -> @_doc.pendingOp
|
getPendingOp: () -> @_doc.pendingOp
|
||||||
|
getRecentAck: () ->
|
||||||
|
# check if we have received an ack recently (within the flush delay)
|
||||||
|
@lastAcked? and new Date() - @lastAcked < @_doc._flushDelay
|
||||||
|
getOpSize: (op) ->
|
||||||
|
# compute size of an op from its components
|
||||||
|
# (total number of characters inserted and deleted)
|
||||||
|
size = 0
|
||||||
|
for component in op or []
|
||||||
|
if component?.i?
|
||||||
|
size += component.i.length
|
||||||
|
if component?.d?
|
||||||
|
size += component.d.length
|
||||||
|
return size
|
||||||
|
|
||||||
attachToAce: (ace) -> @_doc.attach_ace(ace, false, window.maxDocLength)
|
attachToAce: (ace) -> @_doc.attach_ace(ace, false, window.maxDocLength)
|
||||||
detachFromAce: () -> @_doc.detach_ace?()
|
detachFromAce: () -> @_doc.detach_ace?()
|
||||||
|
|
Loading…
Reference in a new issue