diff --git a/CHANGELOG b/CHANGELOG index c05b48c08..84831f340 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -49,6 +49,7 @@ Core: - Enhanced performance esp. for server restart and first connection of all clients by refactoring autoupdate, Collection and AccessPermission [#3223]. - Fixes autoupdate bug for a user without user.can_see_name permission [#3233]. +- Improved reconnect handling if the server was flushed [#3297]. Mediafiles: - Fixed reloading of PDF on page change [#3274] diff --git a/openslides/core/static/js/core/base.js b/openslides/core/static/js/core/base.js index 588e01d81..395224f5d 100644 --- a/openslides/core/static/js/core/base.js +++ b/openslides/core/static/js/core/base.js @@ -48,10 +48,11 @@ angular.module('OpenSlidesApp.core', [ 'REALM', 'ProjectorID', '$q', + '$timeout', 'ErrorMessage', - function (DS, REALM, ProjectorID, $q, ErrorMessage) { + function (DS, REALM, ProjectorID, $q, $timeout, ErrorMessage) { var socket = null; - var recInterval = null; + var retryConnectCallbacks = []; var websocketProtocol; if (location.protocol == 'https:') { @@ -69,6 +70,21 @@ angular.module('OpenSlidesApp.core', [ console.error('The constant REALM is not set properly.'); } + /* The callbacks are invoked if the ws connection closed and this factory tries to + * reconnect after 1 second. The callbacks should return a promise. If the promise + * resolves, the retry-process is stopped, so the callback can indicate whether it + * has managed the reconnecting different.*/ + var runRetryConnectCallbacks = function () { + var callbackPromises = _.map(retryConnectCallbacks, function (callback) { + return callback(); + }); + $q.all(callbackPromises).then(function (success) { + ErrorMessage.clearConnectionError(); + }, function (error) { + $timeout(runRetryConnectCallbacks, 1000); + }); + }; + var Autoupdate = {}; Autoupdate.messageReceivers = []; // We use later a promise to defer the first message of the established ws connection. @@ -78,15 +94,14 @@ angular.module('OpenSlidesApp.core', [ }; Autoupdate.newConnect = function () { socket = new WebSocket(websocketProtocol + '//' + location.host + websocketPath); - clearInterval(recInterval); + // Make shure the servers state hasn't changed: Send a whoami request. If no users is logged and + // anonymous are deactivated, reboot the client in fact that the server has lost all login information. socket.onclose = function (event) { socket = null; - recInterval = setInterval(function () { - Autoupdate.newConnect(); - }, 1000); if (event.code !== 1000) { // 1000 is a normal close, like the close on logout ErrorMessage.setConnectionError(); } + $timeout(runRetryConnectCallbacks, 1000); }; socket.onmessage = function (event) { var dataList = []; @@ -116,6 +131,9 @@ angular.module('OpenSlidesApp.core', [ } Autoupdate.firstMessageDeferred = $q.defer(); }; + Autoupdate.registerRetryConnectCallback = function (callback) { + retryConnectCallbacks.push(callback); + }; return Autoupdate; } ]) diff --git a/openslides/core/static/js/core/start.js b/openslides/core/static/js/core/start.js index 3940a8f95..bcdbac630 100644 --- a/openslides/core/static/js/core/start.js +++ b/openslides/core/static/js/core/start.js @@ -8,13 +8,14 @@ angular.module('OpenSlidesApp.core.start', []) '$http', '$rootScope', '$state', + '$q', 'DS', 'autoupdate', 'operator', 'Group', 'mainMenu', - function($http, $rootScope, $state, DS, autoupdate, operator, Group, mainMenu) { - return { + function($http, $rootScope, $state, $q, DS, autoupdate, operator, Group, mainMenu) { + var OpenSlides = { bootup: function () { $rootScope.openslidesBootstrapDone = false; $http.get('/users/whoami/').then(function (success) { @@ -46,6 +47,22 @@ angular.module('OpenSlidesApp.core.start', []) this.bootup(); }, }; + + // We need to 'ping' the server with a get request to whoami, because then we can decide, + // if the server is down or respond with a 403 (this cannot be differentiated with websockets) + autoupdate.registerRetryConnectCallback(function () { + return $http.get('/users/whoami').then(function (success) { + if (success.data.user_id === null && !success.data.guest_enabled) { + OpenSlides.shutdown(); + // Redirect to login dialog if user is not logged in. + $state.go('login', {guest_enabled: success.data.guest_enabled}); + } else { + autoupdate.newConnect(); + } + }); + }); + + return OpenSlides; } ])