Просмотр исходного кода

Merge branch 'master' of https://github.com/sharelatex/web-sharelatex

Henry Oswald 11 лет назад
Родитель
Сommit
4f3b01ed43

+ 9 - 8
services/web/public/coffee/ide/editor/Document.coffee

@@ -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,

+ 36 - 5
services/web/public/coffee/ide/editor/ShareJsDoc.coffee

@@ -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
 

+ 0 - 8
services/web/public/coffee/ide/editor/controllers/SavingNotificationController.coffee

@@ -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."