diff --git a/package.json b/package.json index 62a06700..ae327403 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "author": "Calvin Montgomery", "name": "CyTube", "description": "Online media synchronizer and chat", - "version": "3.59.1", + "version": "3.60.0", "repository": { "url": "http://github.com/calzoneman/sync" }, diff --git a/src/io/ioserver.js b/src/io/ioserver.js index 5e8bcf83..68602ccb 100644 --- a/src/io/ioserver.js +++ b/src/io/ioserver.js @@ -289,8 +289,37 @@ class IOServer { throw new Error('Cannot bind: socket.io has not been initialized yet'); } + const engineOpts = { + /* + * Set ping timeout to 2 minutes to avoid spurious reconnects + * during transient network issues. The default of 5 minutes + * is too aggressive. + * + * https://github.com/calzoneman/sync/issues/780 + */ + pingTimeout: 120000, + + /* + * Per `ws` docs: "Note that Node.js has a variety of issues with + * high-performance compression, where increased concurrency, + * especially on Linux, can lead to catastrophic memory + * fragmentation and slow performance." + * + * CyTube's frames are ordinarily quite small, so there's not much + * point in compressing them. + */ + perMessageDeflate: false, + httpCompression: false, + + /* + * Default is 10MB. + * Even 1MiB seems like a generous limit... + */ + maxHttpBufferSize: 1 << 20 + }; + servers.forEach(server => { - this.io.attach(server); + this.io.attach(server, engineOpts); }); } } @@ -375,6 +404,10 @@ const promSocketDisconnect = new Counter({ name: 'cytube_sockets_disconnects_total', help: 'Counter for number of connections disconnected.' }); +const promSocketReconnect = new Counter({ + name: 'cytube_sockets_reconnects_total', + help: 'Counter for number of reconnects detected.' +}); function emitMetrics(sock) { try { let closed = false; @@ -406,6 +439,15 @@ function emitMetrics(sock) { sock.context.ipAddress, error.stack); } }); + + sock.once('reportReconnect', () => { + try { + promSocketReconnect.inc(1, new Date()); + } catch (error) { + LOGGER.error('Error emitting reconnect metrics for socket (ip=%s): %s', + sock.context.ipAddress, error.stack); + } + }); } catch (error) { LOGGER.error('Error emitting metrics for socket (ip=%s): %s', sock.context.ipAddress, error.stack); diff --git a/www/js/callbacks.js b/www/js/callbacks.js index 21c4c125..3007c17a 100644 --- a/www/js/callbacks.js +++ b/www/js/callbacks.js @@ -35,6 +35,10 @@ Callbacks = { scrollChat(); }, + reconnect: function () { + socket.emit("reportReconnect"); + }, + // Socket.IO error callback error: function (msg) { window.SOCKET_ERROR_REASON = msg;