From 335c52015e725f890e347481d89c39915c5b64de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9e=20Kooi?= Date: Sat, 7 Dec 2024 11:47:39 +0100 Subject: [PATCH] Tweak guest counting --- src/SocketServer.js | 35 +++++++++++++++++++---------------- src/sockets/LostConnection.js | 27 +++++++++++---------------- 2 files changed, 30 insertions(+), 32 deletions(-) diff --git a/src/SocketServer.js b/src/SocketServer.js index 7b9ebb56..c5a1ed55 100644 --- a/src/SocketServer.js +++ b/src/SocketServer.js @@ -3,7 +3,6 @@ import lodash from 'lodash'; import sjson from 'secure-json-parse'; import { WebSocketServer } from 'ws'; import Ajv from 'ajv'; -import ms from 'ms'; import { stdSerializers } from 'pino'; import { socketVote } from './controllers/booth.js'; import { disconnectUser } from './controllers/users.js'; @@ -13,10 +12,13 @@ import AuthedConnection from './sockets/AuthedConnection.js'; import LostConnection from './sockets/LostConnection.js'; import { serializeUser } from './utils/serialize.js'; -const { debounce, isEmpty } = lodash; +const { isEmpty } = lodash; export const REDIS_ACTIVE_SESSIONS = 'users'; +const PING_INTERVAL = 10_000; +const GUEST_COUNT_INTERVAL = 2_000; + /** * @typedef {import('./schema.js').User} User */ @@ -102,10 +104,10 @@ class SocketServer { #pinger; - /** - * Update online guests count and broadcast an update if necessary. - */ - #recountGuests; + /** Update online guests count and broadcast an update if necessary. */ + #guestCountInterval; + + #guestCountDirty = true; /** * Handlers for commands that come in from clients. @@ -187,16 +189,17 @@ class SocketServer { this.#pinger = setInterval(() => { this.ping(); - }, ms('10 seconds')); + }, PING_INTERVAL); - this.#recountGuests = debounce(() => { - if (this.#closing) { + this.#guestCountInterval = setInterval(() => { + if (!this.#guestCountDirty) { return; } - this.#recountGuestsInternal().catch((error) => { + + this.#recountGuests().catch((error) => { this.#logger.error({ err: error }, 'counting guests failed'); }); - }, ms('2 seconds')); + }, GUEST_COUNT_INTERVAL); this.#clientActions = { sendChat: (user, message) => { @@ -629,7 +632,7 @@ class SocketServer { this.#logger.trace({ type: connection.constructor.name, userID, sessionID }, 'add connection'); this.#connections.push(connection); - this.#recountGuests(); + this.#guestCountDirty = true; } /** @@ -647,7 +650,7 @@ class SocketServer { this.#connections.splice(i, 1); connection.removed(); - this.#recountGuests(); + this.#guestCountDirty = true; } /** @@ -703,12 +706,12 @@ class SocketServer { clearInterval(this.#pinger); this.#closing = true; + clearInterval(this.#guestCountInterval); + for (const connection of this.#connections) { connection.close(); } - this.#recountGuests.cancel(); - const closeWsServer = promisify(this.#wss.close.bind(this.#wss)); await closeWsServer(); await this.#redisSubscription.quit(); @@ -779,7 +782,7 @@ class SocketServer { return parseInt(rawCount, 10); } - async #recountGuestsInternal() { + async #recountGuests() { const { redis } = this.#uw; const guests = this.#connections .filter((connection) => connection instanceof GuestConnection) diff --git a/src/sockets/LostConnection.js b/src/sockets/LostConnection.js index cf66c3bf..32733e0a 100644 --- a/src/sockets/LostConnection.js +++ b/src/sockets/LostConnection.js @@ -3,6 +3,8 @@ import EventEmitter from 'node:events'; class LostConnection extends EventEmitter { #logger; + #removeTimer; + /** * @param {import('../Uwave.js').default} uw * @param {import('../schema.js').User} user @@ -19,7 +21,11 @@ class LostConnection extends EventEmitter { }); this.initQueued(); - this.setTimeout(timeout); + + this.#removeTimer = setTimeout(() => { + this.close(); + this.uw.redis.del(this.key, this.messagesKey); + }, timeout * 1000); } /** @@ -52,17 +58,6 @@ class LostConnection extends EventEmitter { .exec(); } - /** - * @param {number} timeout - * @private - */ - setTimeout(timeout) { - this.removeTimer = setTimeout(() => { - this.close(); - this.uw.redis.del(this.key, this.messagesKey); - }, timeout * 1000); - } - /** * @param {string} command * @param {import('type-fest').JsonValue} data @@ -78,13 +73,13 @@ class LostConnection extends EventEmitter { close() { this.#logger.info('close'); - this.emit('close'); + queueMicrotask(() => { + this.emit('close'); + }); } removed() { - if (this.removeTimer) { - clearTimeout(this.removeTimer); - } + clearTimeout(this.#removeTimer); } toString() {