commit ddb856ee2efeb60577a85cde2e6640d3db2f0312
parent ac298c1e654c5fb1dbec89d842a2228abb443c3c
Author: Andreas Gruhler <andreas.gruhler@adfinis.com>
Date: Sat, 28 Sep 2024 11:55:01 +0200
fix(api): MaxListenersExceededWarning, manage db sub
This MaxListenersExceededWarning warning occurred when several clients
had a watch on the scores.
MaxListenersExceededWarning: Possible EventEmitter memory leak detected.
11 error listeners added to [Duplex]. MaxListeners is 10. Use
emitter.setMaxListeners() to increase limit at genericNodeError
(node:internal/errors:984:15)
With this fix we create the subscription on the database only once. All
client sockets are passed from the routing/server module to the db
backend and maintained as set. When the client disconnects, it is
removed from the server and the db backend set.
Diffstat:
2 files changed, 26 insertions(+), 6 deletions(-)
diff --git a/src/api/db.cjs b/src/api/db.cjs
@@ -1,4 +1,6 @@
const postgres = require('postgres');
+const watchers = new Set();
+let scoreSubscription = null
require('dotenv').config({
// Configure common config files and modes
@@ -339,13 +341,29 @@ async function setScore(heat, athlete, judge, score) {
}
}
-async function watchScores(clients) {
+async function removeWatcher(sock) {
+ console.log("- Watcher removed")
+ watchers.delete(sock)
+}
+
+// add client to subscription
+async function watchScores(sock) {
+ // add client to watchlist
+ console.log("+ Watcher added")
+ watchers.add(sock);
+
+ if (scoreSubscription !== null) {
+ // we are already subscribed to this publication
+ return scoreSubscription
+ }
+
+ // subscribe to score publication
try {
- const { unsubscribe } = await sql.subscribe(
+ scoreSubscription = await sql.subscribe(
'*:scores',
(row, { command, relation, key, old }) => {
// distributed score updates to all connected clients
- for(let c of clients) {
+ for(let c of watchers) {
c.send(JSON.stringify({
"message": "Received new scores",
"data": row,
@@ -357,7 +375,7 @@ async function watchScores(clients) {
console.log("~ Watching scores")
}
)
- return unsubscribe
+ return scoreSubscription
} catch (error) {
console.error('Error occurred in watchScores:', error);
throw error
@@ -382,6 +400,7 @@ module.exports = {
getScore,
setScore,
watchScores,
+ removeWatcher,
addAthleteToHeat,
addAthlete,
removeAthlete,
diff --git a/src/api/server.cjs b/src/api/server.cjs
@@ -710,7 +710,7 @@ wss1.on('connection', function connection(sock) {
console.log(' Uncle roger hears:', msg);
if (msg.method === 'watchScores') {
- db.watchScores(clients)
+ db.watchScores(sock)
}
} catch (error) {
console.error('x Error:', error.message);
@@ -723,7 +723,8 @@ wss1.on('connection', function connection(sock) {
sock.on('close', function(event) {
console.log(" Close event:", event.code);
console.log(" Close reason:", event.reason);
- clients.delete(ws);
+ clients.delete(sock);
+ db.removeWatcher(sock);
});
clients.add(sock);