From 10bf54f96185384393a57347ad79e294e13a6f06 Mon Sep 17 00:00:00 2001 From: Fabio Manganiello Date: Tue, 10 Apr 2018 15:56:00 +0200 Subject: [PATCH] A more consistent a bug-free handling of websocket reconnection cycles --- platypush/backend/http/__init__.py | 5 +- .../backend/http/static/js/application.js | 52 ++++++++++++++++--- 2 files changed, 48 insertions(+), 9 deletions(-) diff --git a/platypush/backend/http/__init__.py b/platypush/backend/http/__init__.py index 45a439312..8394b4c3e 100644 --- a/platypush/backend/http/__init__.py +++ b/platypush/backend/http/__init__.py @@ -24,6 +24,7 @@ class HttpBackend(Backend): http://localhost:8008/execute """ websocket_ping_tries = 3 + websocket_ping_timeout = 10.0 def __init__(self, port=8008, websocket_port=8009, disable_websocket=False, token=None, **kwargs): @@ -125,8 +126,8 @@ class HttpBackend(Backend): while True: try: waiter = await websocket.ping() - await asyncio.wait_for(waiter, timeout=5) - time.sleep(5) + await asyncio.wait_for(waiter, timeout=self.websocket_ping_timeout) + time.sleep(self.websocket_ping_timeout) except (asyncio.TimeoutError, websockets.exceptions.ConnectionClosed) as e: close = False if isinstance(e, asyncio.TimeoutError): diff --git a/platypush/backend/http/static/js/application.js b/platypush/backend/http/static/js/application.js index 54992cf7d..f712d1899 100644 --- a/platypush/backend/http/static/js/application.js +++ b/platypush/backend/http/static/js/application.js @@ -1,11 +1,34 @@ $(document).ready(function() { var websocket, + pendingConnection = false, + openedWebsocket, dateTimeInterval, - websocketReconnectInterval, + websocketTimeoutId, + websocketReconnectMsecs = 4000, eventListeners = []; var initWebsocket = function() { - websocket = new WebSocket('ws://' + window.location.hostname + ':' + window.websocket_port); + try { + websocket = new WebSocket('ws://' + window.location.hostname + ':' + window.websocket_port); + } catch (err) { + websocket = undefined; + return; + } + + pendingConnection = websocket; + + var onWebsocketTimeout = function(sock) { + return function() { + console.log('Websocket reconnection timed out, retrying'); + pendingConnection = false; + sock.close(); + sock.onclose({ code: 1000 }); + }; + }; + + websocketTimeoutId = setTimeout( + onWebsocketTimeout(websocket), websocketReconnectMsecs); + websocket.onmessage = function(event) { for (var listener of eventListeners) { data = event.data; @@ -18,10 +41,22 @@ $(document).ready(function() { }; websocket.onopen = function(event) { + if (openedWebsocket) { + console.log("There's already an opened websocket connection, closing the newly opened one"); + this.onclose = function() {}; + this.close(); + } + console.log('Websocket connection successful'); - if (websocketReconnectInterval) { - clearInterval(websocketReconnectInterval); - websocketReconnectInterval = undefined; + openedWebsocket = this; + + if (pendingConnection) { + pendingConnection = false; + } + + if (websocketTimeoutId) { + clearInterval(websocketTimeoutId); + websocketTimeoutId = undefined; } }; @@ -31,9 +66,12 @@ $(document).ready(function() { websocket.onclose = function(event) { console.log('Websocket closed, code: ' + event.code); - websocketReconnectInterval = setInterval(function() { + openedWebsocket = undefined; + + if (!pendingConnection) { + pendingConnection = true; initWebsocket(); - }, 3000); + } }; };