use a websocket which automatically reconnects if the connection is lost

This commit is contained in:
Caleb James DeLisle 2014-11-04 10:51:53 +01:00
parent e3a54c11ee
commit 0d3ded68a0
4 changed files with 39 additions and 46 deletions

View file

@ -22,6 +22,7 @@
"tweetnacl": "~0.12.2",
"ckeditor": "~4.4.5",
"requirejs": "~2.1.15",
"modalBox": "~1.0.2"
"modalBox": "~1.0.2",
"reconnectingWebsocket": ""
}
}

View file

@ -649,7 +649,6 @@ var sync = function (realtime) {
};
var getMessages = function (realtime) {
if (realtime.registered === true) { return; }
realtime.registered = true;
/*var to = schedule(realtime, function () {
throw new Error("failed to connect to the server");
@ -1135,6 +1134,7 @@ module.exports.create = function (userName, authToken, channelId, initialState,
}),
start: enterChainPad(realtime, function () {
getMessages(realtime);
if (realtime.syncSchedule) { unschedule(realtime, realtime.syncSchedule); }
realtime.syncSchedule = schedule(realtime, function () { sync(realtime); });
}),
abort: enterChainPad(realtime, function () {

View file

@ -13,6 +13,7 @@ define(function () {
out.otherPeople = 'other people';
out.disconnected = 'Disconnected';
out.synchronizing = 'Synchronizing';
out.reconnecting = 'Reconnecting...';
out.lag = 'Lag';
out.initialState = [

View file

@ -18,12 +18,13 @@ define([
'html-patcher',
'errorbox',
'messages',
'bower/reconnectingWebsocket/reconnecting-websocket',
'rangy',
'chainpad',
'otaml',
'bower/jquery/dist/jquery.min',
'bower/tweetnacl/nacl-fast.min'
], function (HTMLPatcher, ErrorBox, Messages) {
], function (HTMLPatcher, ErrorBox, Messages, ReconnectingWebSocket) {
window.ErrorBox = ErrorBox;
@ -129,33 +130,29 @@ window.ErrorBox = ErrorBox;
var updateUserList = function (myUserName, listElement, userList) {
var meIdx = userList.indexOf(myUserName);
if (meIdx === -1) {
listElement.text(Messages.synchronizing);
listElement.textContent = Messages.synchronizing;
return;
}
if (userList.length === 1) {
listElement.text(Messages.editingAlone);
listElement.textContent = Messages.editingAlone;
} else if (userList.length === 2) {
listElement.text(Messages.editingWithOneOtherPerson);
listElement.textContent = Messages.editingWithOneOtherPerson;
} else {
listElement.text(Messages.editingWith + ' ' + (userList.length - 1) +
Messages.otherPeople);
listElement.textContent = Messages.editingWith + ' ' + (userList.length - 1) +
Messages.otherPeople;
}
};
var createUserList = function (realtime, myUserName, container) {
var createUserList = function (container) {
var id = uid();
$(container).prepend('<div class="' + USER_LIST_CLS + '" id="'+id+'"></div>');
var listElement = $('#'+id);
realtime.onUserListChange(function (userList) {
updateUserList(myUserName, listElement, userList);
});
return listElement;
return $('#'+id)[0];
};
var abort = function (socket, realtime) {
realtime.abort();
try { socket._socket.close(); } catch (e) { }
$('.'+USER_LIST_CLS).text("Disconnected");
$('.'+USER_LIST_CLS).text(Messages.disconnected);
$('.'+LAG_ELEM_CLS).text("");
};
@ -300,18 +297,13 @@ window.ErrorBox = ErrorBox;
} else {
lagMsg += lagSec;
}
lagElement.text(lagMsg);
lagElement.textContent = lagMsg;
};
var createLagElement = function (socket, realtime, container) {
var createLagElement = function (container) {
var id = uid();
$(container).append('<div class="' + LAG_ELEM_CLS + '" id="'+id+'"></div>');
var lagElement = $('#'+id);
var intr = setInterval(function () {
checkLag(realtime, lagElement);
}, 3000);
socket.onClose.push(function () { clearTimeout(intr); });
return lagElement;
return $('#'+id)[0];
};
var createSpinner = function (container) {
@ -376,7 +368,7 @@ window.ErrorBox = ErrorBox;
};
var makeWebsocket = function (url) {
var socket = new WebSocket(url);
var socket = new ReconnectingWebSocket(url);
var out = {
onOpen: [],
onClose: [],
@ -460,16 +452,12 @@ window.ErrorBox = ErrorBox;
var toolbar = createRealtimeToolbar('#cke_1_toolbox');
socket.onClose.push(function () {
$(toolbar).remove();
checkSocket();
});
var allMessages = [];
var isErrorState = false;
var initializing = true;
var recoverableErrorCount = 0;
var error = function (recoverable, err) {
console.log(new Error().stack);
console.log('error: ' + err.stack);
if (recoverable && recoverableErrorCount++ < MAX_RECOVERABLE_ERRORS) { return; }
var realtime = socket.realtime;
@ -489,15 +477,19 @@ window.ErrorBox = ErrorBox;
};
var checkSocket = function () {
if (isSocketDisconnected(socket, socket.realtime) && !socket.intentionallyClosing) {
isErrorState = true;
abort(socket, socket.realtime);
ErrorBox.show('disconnected', getDocHTML(doc));
//isErrorState = true;
//abort(socket, socket.realtime);
//ErrorBox.show('disconnected', getDocHTML(doc));
return true;
}
return false;
};
socket.onOpen.push(function (evt) {
if (!initializing) {
socket.realtime.start();
return;
}
var realtime = socket.realtime =
ChainPad.create(userName,
@ -508,11 +500,14 @@ window.ErrorBox = ErrorBox;
//createDebugLink(realtime, doc, allMessages, toolbar);
createUserList(realtime,
userName,
toolbar.find('.rtwysiwyg-toolbar-leftside'));
var userListElement = createUserList(toolbar.find('.rtwysiwyg-toolbar-leftside'));
var spinner = createSpinner(toolbar.find('.rtwysiwyg-toolbar-rightside'));
var lagElement = createLagElement(toolbar.find('.rtwysiwyg-toolbar-rightside'));
setInterval(function () {
if (initializing || isSocketDisconnected(socket, realtime)) { return; }
checkLag(realtime, lagElement);
}, 3000);
onEvent = function () {
if (isErrorState) { return; }
@ -552,13 +547,11 @@ window.ErrorBox = ErrorBox;
};
realtime.onUserListChange(function (userList) {
updateUserList(userName, userListElement, userList);
if (!initializing || userList.indexOf(userName) === -1) { return; }
// if we spot ourselves being added to the document, we'll switch
// 'initializing' off because it means we're fully synced.
initializing = false;
createLagElement(socket,
realtime,
toolbar.find('.rtwysiwyg-toolbar-rightside'));
incomingPatch();
});
@ -578,21 +571,19 @@ window.ErrorBox = ErrorBox;
try {
socket.send(message);
} catch (e) {
if (!checkSocket()) { error(true, e.stack); }
error(true, e.stack);
}
});
realtime.onPatch(incomingPatch);
socket.onError.push(function (err) {
if (isErrorState) { return; }
if (!checkSocket()) { error(true, err); }
});
bindAllEvents(wysiwygDiv, doc.body, onEvent, false);
setInterval(function () {
if (isErrorState || checkSocket()) { return; }
if (isErrorState || checkSocket()) {
userListElement.textContent = Messages.reconnecting;
lagElement.textContent = '';
}
}, 200);
realtime.start();