Merge pull request #3297 from FinnStutzenstein/Issue3295

improved reconnect handling if the server was flushed (fixed #3295)
This commit is contained in:
Emanuel Schütze 2017-06-16 07:56:30 +02:00 committed by GitHub
commit bef986630e
3 changed files with 44 additions and 8 deletions

View File

@ -49,6 +49,7 @@ Core:
- Enhanced performance esp. for server restart and first connection of all - Enhanced performance esp. for server restart and first connection of all
clients by refactoring autoupdate, Collection and AccessPermission [#3223]. clients by refactoring autoupdate, Collection and AccessPermission [#3223].
- Fixes autoupdate bug for a user without user.can_see_name permission [#3233]. - Fixes autoupdate bug for a user without user.can_see_name permission [#3233].
- Improved reconnect handling if the server was flushed [#3297].
Mediafiles: Mediafiles:
- Fixed reloading of PDF on page change [#3274] - Fixed reloading of PDF on page change [#3274]

View File

@ -48,10 +48,11 @@ angular.module('OpenSlidesApp.core', [
'REALM', 'REALM',
'ProjectorID', 'ProjectorID',
'$q', '$q',
'$timeout',
'ErrorMessage', 'ErrorMessage',
function (DS, REALM, ProjectorID, $q, ErrorMessage) { function (DS, REALM, ProjectorID, $q, $timeout, ErrorMessage) {
var socket = null; var socket = null;
var recInterval = null; var retryConnectCallbacks = [];
var websocketProtocol; var websocketProtocol;
if (location.protocol == 'https:') { if (location.protocol == 'https:') {
@ -69,6 +70,21 @@ angular.module('OpenSlidesApp.core', [
console.error('The constant REALM is not set properly.'); 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 = {}; var Autoupdate = {};
Autoupdate.messageReceivers = []; Autoupdate.messageReceivers = [];
// We use later a promise to defer the first message of the established ws connection. // 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 () { Autoupdate.newConnect = function () {
socket = new WebSocket(websocketProtocol + '//' + location.host + websocketPath); 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.onclose = function (event) {
socket = null; socket = null;
recInterval = setInterval(function () {
Autoupdate.newConnect();
}, 1000);
if (event.code !== 1000) { // 1000 is a normal close, like the close on logout if (event.code !== 1000) { // 1000 is a normal close, like the close on logout
ErrorMessage.setConnectionError(); ErrorMessage.setConnectionError();
} }
$timeout(runRetryConnectCallbacks, 1000);
}; };
socket.onmessage = function (event) { socket.onmessage = function (event) {
var dataList = []; var dataList = [];
@ -116,6 +131,9 @@ angular.module('OpenSlidesApp.core', [
} }
Autoupdate.firstMessageDeferred = $q.defer(); Autoupdate.firstMessageDeferred = $q.defer();
}; };
Autoupdate.registerRetryConnectCallback = function (callback) {
retryConnectCallbacks.push(callback);
};
return Autoupdate; return Autoupdate;
} }
]) ])

View File

@ -8,13 +8,14 @@ angular.module('OpenSlidesApp.core.start', [])
'$http', '$http',
'$rootScope', '$rootScope',
'$state', '$state',
'$q',
'DS', 'DS',
'autoupdate', 'autoupdate',
'operator', 'operator',
'Group', 'Group',
'mainMenu', 'mainMenu',
function($http, $rootScope, $state, DS, autoupdate, operator, Group, mainMenu) { function($http, $rootScope, $state, $q, DS, autoupdate, operator, Group, mainMenu) {
return { var OpenSlides = {
bootup: function () { bootup: function () {
$rootScope.openslidesBootstrapDone = false; $rootScope.openslidesBootstrapDone = false;
$http.get('/users/whoami/').then(function (success) { $http.get('/users/whoami/').then(function (success) {
@ -46,6 +47,22 @@ angular.module('OpenSlidesApp.core.start', [])
this.bootup(); 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;
} }
]) ])