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

Merge pull request #357 from sharelatex/bg-rate-limit-on-reconnects

rate limit on reconnects
Brian Gough 10 лет назад
Родитель
Сommit
4623f3cbe7
1 измененных файлов с 42 добавлено и 11 удалено
  1. 42 11
      services/web/public/coffee/ide/connection/ConnectionManager.coffee

+ 42 - 11
services/web/public/coffee/ide/connection/ConnectionManager.coffee

@@ -28,24 +28,27 @@ define [], () ->
 			@connected = false
 			@connected = false
 			@userIsInactive = false
 			@userIsInactive = false
 			@gracefullyReconnecting = false
 			@gracefullyReconnecting = false
-			
-			@$scope.connection = 
+
+			@$scope.connection =
 				reconnecting: false
 				reconnecting: false
 				# If we need to force everyone to reload the editor
 				# If we need to force everyone to reload the editor
 				forced_disconnect: false
 				forced_disconnect: false
 				inactive_disconnect: false
 				inactive_disconnect: false
 
 
 			@$scope.tryReconnectNow = () =>
 			@$scope.tryReconnectNow = () =>
-				@tryReconnect()
+				# user manually requested reconnection via "Try now" button
+				@tryReconnectWithRateLimit({force:true})
 
 
 			@$scope.$on 'cursor:editor:update', () =>
 			@$scope.$on 'cursor:editor:update', () =>
-				@lastUserAction = new Date()
+				@lastUserAction = new Date()  # time of last edit
 				if !@connected
 				if !@connected
-					@tryReconnect()
+					# user is editing, try to reconnect
+					@tryReconnectWithRateLimit()
 
 
 			document.querySelector('body').addEventListener 'click', (e) =>
 			document.querySelector('body').addEventListener 'click', (e) =>
 				if !@connected and e.target.id != 'try-reconnect-now-button'
 				if !@connected and e.target.id != 'try-reconnect-now-button'
-					@tryReconnect()
+					# user is editing, try to reconnect
+					@tryReconnectWithRateLimit()
 
 
 			@ide.socket = io.connect null,
 			@ide.socket = io.connect null,
 				reconnect: false
 				reconnect: false
@@ -166,11 +169,13 @@ define [], () ->
 			@tryReconnect()
 			@tryReconnect()
 
 
 		disconnect: () ->
 		disconnect: () ->
+			sl_console.log "[socket.io] disconnecting client"
 			@ide.socket.disconnect()
 			@ide.socket.disconnect()
 
 
 		startAutoReconnectCountdown: () ->
 		startAutoReconnectCountdown: () ->
+			sl_console.log "[ConnectionManager] starting autoreconnect countdown"
 			twoMinutes = 2 * 60 * 1000
 			twoMinutes = 2 * 60 * 1000
-			if @lastUpdated? and new Date() - @lastUpdated > twoMinutes
+			if @lastUserAction? and new Date() - @lastUserAction > twoMinutes
 				# between 1 minute and 3 minutes
 				# between 1 minute and 3 minutes
 				countdown = 60 + Math.floor(Math.random() * 120)
 				countdown = 60 + Math.floor(Math.random() * 120)
 			else
 			else
@@ -189,10 +194,16 @@ define [], () ->
 			, 200)
 			, 200)
 
 
 		cancelReconnect: () ->
 		cancelReconnect: () ->
-			clearTimeout @timeoutId if @timeoutId?
-					
+			# clear timeout and set to null so we know there is no countdown running
+			if @timeoutId?
+				sl_console.log "[ConnectionManager] cancelling existing reconnect timer"
+				clearTimeout @timeoutId
+				@timeoutId = null
+
 		decreaseCountdown: () ->
 		decreaseCountdown: () ->
+			@timeoutId = null
 			return if !@$scope.connection.reconnection_countdown?
 			return if !@$scope.connection.reconnection_countdown?
+			sl_console.log "[ConnectionManager] decreasing countdown", @$scope.connection.reconnection_countdown
 			@$scope.$apply () =>
 			@$scope.$apply () =>
 				@$scope.connection.reconnection_countdown--
 				@$scope.connection.reconnection_countdown--
 
 
@@ -203,13 +214,33 @@ define [], () ->
 				@timeoutId = setTimeout (=> @decreaseCountdown()), 1000
 				@timeoutId = setTimeout (=> @decreaseCountdown()), 1000
 
 
 		tryReconnect: () ->
 		tryReconnect: () ->
+			sl_console.log "[ConnectionManager] tryReconnect"
 			@cancelReconnect()
 			@cancelReconnect()
 			delete @$scope.connection.reconnection_countdown
 			delete @$scope.connection.reconnection_countdown
 			return if @connected
 			return if @connected
 			@$scope.connection.reconnecting = true
 			@$scope.connection.reconnecting = true
-			@ide.socket.socket.reconnect()
+			# use socket.io connect() here to make a single attempt, the
+			# reconnect() method makes multiple attempts
+			@ide.socket.socket.connect()
+			# record the time of the last attempt to connect
+			@lastConnectionAttempt = new Date()
 			setTimeout (=> @startAutoReconnectCountdown() if !@connected), 2000
 			setTimeout (=> @startAutoReconnectCountdown() if !@connected), 2000
 
 
+		MIN_RETRY_INTERVAL: 1000 # ms
+		BACKGROUND_RETRY_INTERVAL : 30 * 1000 # ms
+
+		tryReconnectWithRateLimit: (options) ->
+			# bail out if the reconnect is already in progress
+			return if @$scope.connection?.reconnecting
+			# bail out if we are going to reconnect soon anyway
+			reconnectingSoon = @$scope.connection?.reconnection_countdown? and @$scope.connection.reconnection_countdown <= 5
+			clickedTryNow = options?.force  # user requested reconnection
+			return if reconnectingSoon and not clickedTryNow
+			# bail out if we tried reconnecting recently
+			allowedInterval = if clickedTryNow then @MIN_RETRY_INTERVAL else @BACKGROUND_RETRY_INTERVAL
+			return if @lastConnectionAttempt? and new Date() - @lastConnectionAttempt < allowedInterval
+			@tryReconnect()
+
 		disconnectIfInactive: ()->
 		disconnectIfInactive: ()->
 			@userIsInactive = (new Date() - @lastUserAction) > @disconnectAfterMs
 			@userIsInactive = (new Date() - @lastUserAction) > @disconnectAfterMs
 			if @userIsInactive and @connected
 			if @userIsInactive and @connected
@@ -231,7 +262,7 @@ define [], () ->
 				setTimeout () =>
 				setTimeout () =>
 					@reconnectGracefully()
 					@reconnectGracefully()
 				, @RECONNECT_GRACEFULLY_RETRY_INTERVAL
 				, @RECONNECT_GRACEFULLY_RETRY_INTERVAL
-		
+
 		_reconnectGracefullyNow: () ->
 		_reconnectGracefullyNow: () ->
 			@gracefullyReconnecting = true
 			@gracefullyReconnecting = true
 			@reconnectGracefullyStarted = null
 			@reconnectGracefullyStarted = null