This repository has been archived on 2026-10-08. You can view files and clone it, but cannot push or open issues or pull requests.
allotment/packages/server/socket/SubscriptionRegistry.js

62 lines
1.9 KiB
JavaScript

/**
* Tracks which socket.io connection ids are subscribed to each logical channel.
* Keys: "patch:<patchId>", "waterTank", "power", "wateringSessions", "waterSchedules"
*/
export class SubscriptionRegistry {
constructor() {
/** @type {Map<string, Set<string>>} */
this._keyToSockets = new Map();
/** @type {Map<string, Set<string>>} */
this._socketToKeys = new Map();
}
static channelKey(resource, id) {
if (resource === "patch") {
if (id == null || id === "") return null;
return `patch:${id}`;
}
if (resource === "waterTank") return "waterTank";
if (resource === "power") return "power";
if (resource === "wateringSessions") return "wateringSessions";
if (resource === "waterSchedules") return "waterSchedules";
return null;
}
subscribe(socketId, key) {
if (!key) return;
if (!this._keyToSockets.has(key)) this._keyToSockets.set(key, new Set());
this._keyToSockets.get(key).add(socketId);
if (!this._socketToKeys.has(socketId)) this._socketToKeys.set(socketId, new Set());
this._socketToKeys.get(socketId).add(key);
}
unsubscribe(socketId, key) {
if (!key) return;
this._keyToSockets.get(key)?.delete(socketId);
if (this._keyToSockets.get(key)?.size === 0) {
this._keyToSockets.delete(key);
}
this._socketToKeys.get(socketId)?.delete(key);
if (this._socketToKeys.get(socketId)?.size === 0) {
this._socketToKeys.delete(socketId);
}
}
removeSocket(socketId) {
const keys = this._socketToKeys.get(socketId);
if (!keys) return;
for (const key of keys) {
this._keyToSockets.get(key)?.delete(socketId);
if (this._keyToSockets.get(key)?.size === 0) {
this._keyToSockets.delete(key);
}
}
this._socketToKeys.delete(socketId);
}
/** @returns {Iterable<string>} */
getSubscriberIds(key) {
return this._keyToSockets.get(key) ?? [];
}
}