Implement initial load through websocket to cut one unnecessary HTTP GET that caused conn pool overflow. Increased reload / retry delays to reduce server spamming by poorly loaded client.

This commit is contained in:
2017-09-08 23:53:23 +02:00
parent a20ec8a49e
commit 1d6d6ee228
2 changed files with 131 additions and 115 deletions
+117 -114
View File
@@ -1,131 +1,134 @@
/** Handle connections */ /** Handle connections */
var Conn = (function() { var Conn = (function () {
var ws; var ws;
var heartbeatTout; var heartbeatTout;
var pingIv; var pingIv;
var xoff = false; var xoff = false;
var autoXoffTout; var autoXoffTout;
var reconTout;
function onOpen(evt) { var pageShown = false;
console.log("CONNECTED");
}
function onClose(evt) { function onOpen(evt) {
console.warn("SOCKET CLOSED, code "+evt.code+". Reconnecting..."); console.log("CONNECTED");
setTimeout(function() { doSend("i");
init(); }
}, 200);
// this happens when the buffer gets fucked up via invalid unicode.
// we basically use polling instead of socket then
}
function onMessage(evt) { function onClose(evt) {
try { console.warn("SOCKET CLOSED, code " + evt.code + ". Reconnecting...");
// . = heartbeat clearTimeout(reconTout);
switch (evt.data.charAt(0)) { reconTout = setTimeout(function () {
case 'B': init();
case 'T': }, 2000);
case 'S': // this happens when the buffer gets fucked up via invalid unicode.
Screen.load(evt.data); // we basically use polling instead of socket then
break; }
case '-': function onMessage(evt) {
//console.log('xoff'); try {
xoff = true; // . = heartbeat
autoXoffTout = setTimeout(function(){xoff=false;}, 250); switch (evt.data.charAt(0)) {
break; case 'B':
case 'T':
case 'S':
Screen.load(evt.data);
if(!pageShown) {
showPage();
pageShown = true;
}
break;
case '+': case '-':
//console.log('xon'); //console.log('xoff');
xoff = false; xoff = true;
clearTimeout(autoXoffTout); autoXoffTout = setTimeout(function () {
break; xoff = false;
} }, 250);
heartbeat(); break;
} catch(e) {
console.error(e);
}
}
function canSend() { case '+':
return !xoff; //console.log('xon');
} xoff = false;
clearTimeout(autoXoffTout);
break;
}
heartbeat();
} catch (e) {
console.error(e);
}
}
function doSend(message) { function canSend() {
if (_demo) { return !xoff;
console.log("TX: ", message); }
return true; // Simulate success
}
if (xoff) {
// TODO queue
console.log("Can't send, flood control.");
return false;
}
if (!ws) return false; // for dry testing function doSend(message) {
if (ws.readyState != 1) { if (_demo) {
console.error("Socket not ready"); console.log("TX: ", message);
return false; return true; // Simulate success
} }
if (typeof message != "string") { if (xoff) {
message = JSON.stringify(message); // TODO queue
} console.log("Can't send, flood control.");
ws.send(message); return false;
return true; }
}
function init() { if (!ws) return false; // for dry testing
if (_demo) { if (ws.readyState != 1) {
console.log("Demo mode!"); console.error("Socket not ready");
Screen.load(_demo_screen); return false;
showPage(); }
return; if (typeof message != "string") {
} message = JSON.stringify(message);
heartbeat(); }
ws.send(message);
return true;
}
ws = new WebSocket("ws://"+_root+"/term/update.ws"); function init() {
ws.onopen = onOpen; if (_demo) {
ws.onclose = onClose; console.log("Demo mode!");
ws.onmessage = onMessage; Screen.load(_demo_screen);
showPage();
return;
}
console.log("Opening socket."); clearTimeout(reconTout);
clearTimeout(heartbeatTout);
// Ask for initial data ws = new WebSocket("ws://" + _root + "/term/update.ws");
$.get('http://'+_root+'/term/init', function(resp, status) { ws.onopen = onOpen;
if (status !== 200) location.reload(true); ws.onclose = onClose;
console.log("Data received!"); ws.onmessage = onMessage;
Screen.load(resp); console.log("Opening socket.");
heartbeat(); heartbeat();
}
showPage(); function heartbeat() {
}); clearTimeout(heartbeatTout);
} heartbeatTout = setTimeout(heartbeatFail, 2000);
}
function heartbeat() { function heartbeatFail() {
clearTimeout(heartbeatTout); console.error("Heartbeat lost, probing server...");
heartbeatTout = setTimeout(heartbeatFail, 2000); pingIv = setInterval(function () {
} console.log("> ping");
$.get('http://' + _root + '/system/ping', function (resp, status) {
if (status == 200) {
clearInterval(pingIv);
console.info("Server ready, reloading page...");
location.reload();
}
}, {
timeout: 100,
});
}, 1000);
}
function heartbeatFail() { return {
console.error("Heartbeat lost, probing server..."); ws: null,
pingIv = setInterval(function() { init: init,
console.log("> ping"); send: doSend,
$.get('http://'+_root+'/system/ping', function(resp, status) { canSend: canSend, // check flood control
if (status == 200) { };
clearInterval(pingIv);
console.info("Server ready, reloading page...");
location.reload();
}
}, {
timeout: 100,
});
}, 500);
}
return {
ws: null,
init: init,
send: doSend,
canSend: canSend, // check flood control
};
})(); })();
+14 -1
View File
@@ -47,6 +47,7 @@ notifyCooldownTimCb(void *arg)
static void ICACHE_FLASH_ATTR static void ICACHE_FLASH_ATTR
notifyContentTimCb(void *arg) notifyContentTimCb(void *arg)
{ {
Websock *ws = arg;
void *data = NULL; void *data = NULL;
int max_bl, total_bl; int max_bl, total_bl;
char sock_buff[SOCK_BUF_LEN]; char sock_buff[SOCK_BUF_LEN];
@@ -65,8 +66,14 @@ notifyContentTimCb(void *arg)
int flg = 0; int flg = 0;
if (cont == HTTPD_CGI_MORE) flg |= WEBSOCK_FLAG_MORE; if (cont == HTTPD_CGI_MORE) flg |= WEBSOCK_FLAG_MORE;
if (i > 0) flg |= WEBSOCK_FLAG_CONT; if (i > 0) flg |= WEBSOCK_FLAG_CONT;
cgiWebsockBroadcast(URL_WS_UPDATE, sock_buff, (int) strlen(sock_buff), flg); if (ws) {
cgiWebsocketSend(ws, sock_buff, (int) strlen(sock_buff), flg);
} else {
cgiWebsockBroadcast(URL_WS_UPDATE, sock_buff, (int) strlen(sock_buff), flg);
}
if (cont == HTTPD_CGI_DONE) break; if (cont == HTTPD_CGI_DONE) break;
system_soft_wdt_feed();
} }
// cleanup // cleanup
@@ -251,6 +258,12 @@ void ICACHE_FLASH_ATTR updateSockRx(Websock *ws, char *data, int len, int flags)
} }
break; break;
case 'i':
// requests initial load
dbg("Client requests initial load");
notifyContentTimCb(ws);
break;
case 'm': case 'm':
case 'p': case 'p':
case 'r': case 'r':