I'd like to improve the resilience of my clientside implementation of a signalR client.
Currently, I do this:
hub.server.sendClientNotification(string, appSettings.username());
However occasionally, an exception related to connectivity is thrown because either the server is not responding or the client's internet connection has become unusable.
I'd like to solve this by queuing up requests and then doing something like this:
try {
// pop from queue
hub.server.sendClientNotification(string, appSettings.username());
// success - discard element
} catch (e) {
// requeue element
}
With this kind of implementation, would I need to re-initialize my signalR connection using $.connection.hub.start
between disconnects, or can I just continue attempting hub transmits within an interval?
This is what I'm proposing:
var hub = null;
const internalQueue = [];
const states = {
connecting: 0, connected: 1, reconnecting: 2, disconnected: 4
}
const signalrModule = {};
var isInitialized = false;
const connectSignalR = function () {
return new Promise(function (resolve, reject) {
if ($.connection.hub.state == states.connected) {
resolve();
} else {
window.hubReady = $.connection.hub.start({ transport: ["serverSentEvents", "foreverFrame", "longPolling"] });
window.hubReady.done(function () {
isInitialized = true;
resolve();
});
window.onbeforeunload = function (e) {
$.connection.hub.stop();
};
}
})
}
signalrModule.init = function (handleNotification) {
hub = $.connection.appHub;
hub.client.clientNotification = handleNotification;
$.connection.hub.qs = {
"username": appSettings.username()
};
connectSignalR();
}
const tryEmptyQueue = function () {
connectSignalR().then(function() {
if (isInitialized) {
var continueTrying = true;
while (internalQueue.length && continueTrying) {
const nextMessage = internalQueue.shift();
try {
hub.server.sendClientNotification(nextMessage, appSettings.username());
} catch (e) {
internalQueue.push(nextMessage);
continueTrying = false;
}
}
}
})
}
signalrModule.sendClientNotification = function (message) {
if (typeof message != "string") {
message = JSON.stringify(message);
}
if (isInitialized) {
try {
hub.server.sendClientNotification(message, appSettings.username());
tryEmptyQueue();
} catch (e) {
logger.log("SignalR disconnected; queuing request", logger.logLevels.warning);
internalQueue.push(message);
}
} else {
internalQueue.push(message);
};
}
const internalQueueInterval = setInterval(function () {
tryEmptyQueue();
}, 5000);
return signalrModule;