This commit is contained in:
Henry Oswald
2015-11-23 17:11:06 +00:00
3 changed files with 45 additions and 21 deletions
@@ -150,14 +150,16 @@ define [
wantToBeJoined: @wantToBeJoined
update: update
if Math.random() < (@ide.disconnectRate or 0)
console.log "Simulating disconnect"
@ide.connectionManager.disconnect()
if window.disconnectOnAck? and Math.random() < window.disconnectOnAck
console.log "Disconnecting on ack", update
window._ide.socket.socket.disconnect()
# Pretend we never received the ack
return
if Math.random() < (@ide.ignoreRate or 0)
console.log "Simulating lost update"
return
if window.dropAcks? and Math.random() < window.dropAcks
if !update.op? # Only drop our own acks, not collaborator updates
console.log "Simulating a lost ack", update
return
if update?.doc == @doc_id and @doc?
@doc.processUpdateFromServer update
@@ -240,8 +242,7 @@ define [
doc_id: @doc_id
op: op
@trigger "op:timeout"
ga?('send', 'event', 'error', "op timeout", "Op was now acknowledged - #{@ide.socket.socket.transport.name}" )
@ide.connectionManager.reconnectImmediately()
@_onError new Error("op timed out"), {op: op}
@doc.on "flush", (inflightOp, pendingOp, version) =>
@ide.pushEvent "flush",
doc_id: @doc_id,
@@ -28,6 +28,12 @@ define [
@connection = {
send: (update) =>
@_startInflightOpTimeout(update)
if window.disconnectOnUpdate? and Math.random() < window.disconnectOnUpdate
console.log "Disconnecting on update", update
window._ide.socket.socket.disconnect()
if window.dropUpdates? and Math.random() < window.dropUpdates
console.log "Simulating a lost update", update
return
@socket.emit "applyOtUpdate", @doc_id, update
state: "ok"
id: @socket.socket.sessionid
@@ -103,17 +109,42 @@ define [
attachToAce: (ace) -> @_doc.attach_ace(ace, false, window.maxDocLength)
detachFromAce: () -> @_doc.detach_ace?()
INFLIGHT_OP_TIMEOUT: 10000
INFLIGHT_OP_TIMEOUT: 5000 # Retry sending ops after 5 seconds without an ack
_startInflightOpTimeout: (update) ->
meta =
v: update.v
op_sent_at: new Date()
@_startFatalTimeoutTimer(update)
timer = setTimeout () =>
@trigger "op:timeout", update
# Only send the update again if inflightOp is still populated
# This can be cleared when hard reloading the document in which
# case we don't want to keep trying to send it.
if @_doc.inflightOp?
# When there is a socket.io disconnect, @_doc.inflightSubmittedIds
# is updated with the socket.io client id of the current op in flight
# (meta.source of the op).
# @connection.id is the client id of the current socket.io session.
# So we need both depending on whether the op was submitted before
# one or more disconnects, or if it was submitted during the current session.
update.dupIfSource = [@connection.id, @_doc.inflightSubmittedIds...]
@connection.send(update)
, @INFLIGHT_OP_TIMEOUT
@_doc.inflightCallbacks.push () =>
@_clearFatalTimeoutTimer()
clearTimeout timer
FATAL_OP_TIMEOUT: 30000 # 30 seconds
_startFatalTimeoutTimer: (update) ->
# If an op doesn't get acked within FATAL_OP_TIMEOUT, something has
# gone unrecoverably wrong (the op will have been retried multiple times)
return if @_timeoutTimer?
@_timeoutTimer = setTimeout () =>
@_clearFatalTimeoutTimer()
@trigger "op:timeout", update
, @FATAL_OP_TIMEOUT
_clearFatalTimeoutTimer: () ->
return if !@_timeoutTimer?
clearTimeout @_timeoutTimer
@_timeoutTimer = null
_handleError: (error, meta = {}) ->
@trigger "error", error, meta
@@ -24,8 +24,6 @@ define [
if oldStatus[doc_id]?
newStatus[doc_id] = oldStatus[doc_id]
newStatus[doc_id].unsavedSeconds += 1
if newStatus[doc_id].unsavedSeconds == 60
reportUnsavedChanges(doc)
else
newStatus[doc_id] = {
unsavedSeconds: 0
@@ -41,12 +39,6 @@ define [
$scope.docSavingStatusCount = newUnsavedCount
$scope.$apply()
reportUnsavedChanges = (doc) ->
ide.reportError new Error("unsaved changes"), {
inflightOp: doc?.getInflightOp(),
pendingOp: doc?.getPendingOp()
}
warnAboutUnsavedChanges = () ->
if Document.hasUnsavedChanges()
return "You have unsaved changes. If you leave now they will not be saved."