cleanup, forwarding now handled by subscriptionHandler
This commit is contained in:
@@ -0,0 +1,62 @@
|
|||||||
|
import { WS } from "./index";
|
||||||
|
|
||||||
|
export interface Subscriber {
|
||||||
|
send: (message: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SubscriptionMap {
|
||||||
|
channelsPerSubscriber = new Map<Subscriber, Set<string>>();
|
||||||
|
subscribersPerChannel = new Map<string, Set<Subscriber>>();
|
||||||
|
|
||||||
|
// prepare
|
||||||
|
private prepareChannelSet(subscriber: Subscriber): void {
|
||||||
|
if (this.channelsPerSubscriber.has(subscriber)) return;
|
||||||
|
this.channelsPerSubscriber.set(subscriber, new Set());
|
||||||
|
}
|
||||||
|
|
||||||
|
private prepareSubscriberSet(channel: string): void {
|
||||||
|
if (this.subscribersPerChannel.has(channel)) return;
|
||||||
|
this.subscribersPerChannel.set(channel, new Set());
|
||||||
|
}
|
||||||
|
|
||||||
|
// utility
|
||||||
|
getChannelList(subscriber: Subscriber): Set<string> | undefined {
|
||||||
|
return this.channelsPerSubscriber.get(subscriber);
|
||||||
|
}
|
||||||
|
|
||||||
|
getClientList(channel: string): Set<Subscriber> | undefined {
|
||||||
|
return this.subscribersPerChannel.get(channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
// modifications
|
||||||
|
set(subscriber: Subscriber, channel: string): void {
|
||||||
|
this.prepareChannelSet(subscriber);
|
||||||
|
this.prepareSubscriberSet(channel);
|
||||||
|
|
||||||
|
this.getChannelList(subscriber)?.add(channel);
|
||||||
|
this.getClientList(channel)?.add(subscriber);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(subscriber: Subscriber, channel: string): void {
|
||||||
|
const channelList = this.getChannelList(subscriber);
|
||||||
|
const clientList = this.getClientList(channel);
|
||||||
|
|
||||||
|
channelList?.delete(channel);
|
||||||
|
if (channelList?.size == 0) {
|
||||||
|
this.channelsPerSubscriber.delete(subscriber);
|
||||||
|
}
|
||||||
|
|
||||||
|
clientList?.delete(subscriber);
|
||||||
|
if (clientList?.size == 0) {
|
||||||
|
this.subscribersPerChannel.delete(channel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// messages
|
||||||
|
forwardMessage(channels: string[], messageString: string): void {
|
||||||
|
channels.forEach((channel) => {
|
||||||
|
const subscribers = this.getClientList(channel);
|
||||||
|
subscribers?.forEach((subscriber) => subscriber.send(messageString));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
import { WS } from "./index";
|
|
||||||
|
|
||||||
export class SubscriptionMap {
|
|
||||||
channelsPerClient = new Map<WS, Set<string>>();
|
|
||||||
clientsPerChannel = new Map<string, Set<WS>>();
|
|
||||||
|
|
||||||
// prepare
|
|
||||||
private prepareChannelSet(ws: WS) {
|
|
||||||
if (this.channelsPerClient.has(ws)) return;
|
|
||||||
this.channelsPerClient.set(ws, new Set());
|
|
||||||
}
|
|
||||||
|
|
||||||
private prepareClientSet(channel: string) {
|
|
||||||
if (this.clientsPerChannel.has(channel)) return;
|
|
||||||
this.clientsPerChannel.set(channel, new Set());
|
|
||||||
}
|
|
||||||
|
|
||||||
// utility
|
|
||||||
getChannelList(ws: WS) {
|
|
||||||
return this.channelsPerClient.get(ws);
|
|
||||||
}
|
|
||||||
|
|
||||||
getClientList(channel: string) {
|
|
||||||
return this.clientsPerChannel.get(channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
// modifications
|
|
||||||
set(ws: WS, channel: string) {
|
|
||||||
this.prepareChannelSet(ws);
|
|
||||||
this.prepareClientSet(channel);
|
|
||||||
|
|
||||||
this.getChannelList(ws)?.add(channel);
|
|
||||||
this.getClientList(channel)?.add(ws);
|
|
||||||
}
|
|
||||||
|
|
||||||
delete(ws: WS, channel: string) {
|
|
||||||
const channelList = this.getChannelList(ws);
|
|
||||||
const clientList = this.getClientList(channel);
|
|
||||||
|
|
||||||
channelList?.delete(channel);
|
|
||||||
if (channelList?.size == 0) {
|
|
||||||
this.channelsPerClient.delete(ws);
|
|
||||||
}
|
|
||||||
|
|
||||||
clientList?.delete(ws);
|
|
||||||
if (clientList?.size == 0) {
|
|
||||||
this.clientsPerChannel.delete(channel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+28
-15
@@ -1,3 +1,7 @@
|
|||||||
|
import {
|
||||||
|
Subscriber,
|
||||||
|
SubscriptionMap,
|
||||||
|
} from "./subscriptionHandler";
|
||||||
import {
|
import {
|
||||||
doIfIsString,
|
doIfIsString,
|
||||||
parseMessage,
|
parseMessage,
|
||||||
@@ -7,7 +11,6 @@ import {
|
|||||||
} from "./utility";
|
} from "./utility";
|
||||||
|
|
||||||
import Crypto from "crypto";
|
import Crypto from "crypto";
|
||||||
import { SubscriptionMap } from "./subscriptionMap";
|
|
||||||
import { WS } from "./index";
|
import { WS } from "./index";
|
||||||
import { defaultConfig } from "./config-handler";
|
import { defaultConfig } from "./config-handler";
|
||||||
|
|
||||||
@@ -35,7 +38,9 @@ export interface WebSocketMessage {
|
|||||||
const knownMessageIds = new Set<string>();
|
const knownMessageIds = new Set<string>();
|
||||||
|
|
||||||
export const subscriptionMap = new SubscriptionMap();
|
export const subscriptionMap = new SubscriptionMap();
|
||||||
|
|
||||||
export const clientsConnected = new Set<WS>();
|
export const clientsConnected = new Set<WS>();
|
||||||
|
|
||||||
export const serversConnectedAsClient = new Set<WS>();
|
export const serversConnectedAsClient = new Set<WS>();
|
||||||
export const serversConnected = new Set<WebSocket>();
|
export const serversConnected = new Set<WebSocket>();
|
||||||
export const serversDisconnected = new Set<string>();
|
export const serversDisconnected = new Set<string>();
|
||||||
@@ -58,14 +63,20 @@ export function forgetConnection(ws: WS): void {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function trackSubscription(ws: WS, channel: string): void {
|
export function trackSubscription(
|
||||||
subscriptionMap.set(ws, channel);
|
subscriber: Subscriber,
|
||||||
confirmSubscription(ws, channel);
|
channel: string
|
||||||
|
): void {
|
||||||
|
subscriptionMap.set(subscriber, channel);
|
||||||
|
confirmSubscription(subscriber, channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function forgetSubscription(ws: WS, channel: string): void {
|
export function forgetSubscription(
|
||||||
subscriptionMap.delete(ws, channel);
|
subscriber: Subscriber,
|
||||||
confirmSubscription(ws, channel);
|
channel: string
|
||||||
|
): void {
|
||||||
|
subscriptionMap.delete(subscriber, channel);
|
||||||
|
confirmSubscription(subscriber, channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
// OTHER SERVERS
|
// OTHER SERVERS
|
||||||
@@ -131,7 +142,7 @@ export function subscribeChannel(server: WS, channel: string): void {
|
|||||||
// AUDIT
|
// AUDIT
|
||||||
export function getWebSocketStats(): [string, number][] {
|
export function getWebSocketStats(): [string, number][] {
|
||||||
return [
|
return [
|
||||||
["channels", subscriptionMap.clientsPerChannel.size],
|
["channels", subscriptionMap.subscribersPerChannel.size],
|
||||||
["clients connected", clientsConnected.size],
|
["clients connected", clientsConnected.size],
|
||||||
["servers connected", getServerCount()],
|
["servers connected", getServerCount()],
|
||||||
["servers disconnected", serversDisconnected.size],
|
["servers disconnected", serversDisconnected.size],
|
||||||
@@ -190,10 +201,7 @@ export function sendMessage(
|
|||||||
const messageObject = { uuid, messageChannel, messageBody };
|
const messageObject = { uuid, messageChannel, messageBody };
|
||||||
const messageString = stringifyMessage(messageObject);
|
const messageString = stringifyMessage(messageObject);
|
||||||
|
|
||||||
channels.forEach((channel) => {
|
subscriptionMap.forwardMessage(channels, messageString);
|
||||||
const subscribers = subscriptionMap.getClientList(channel);
|
|
||||||
subscribers?.forEach((ws) => ws.send(messageString));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function requestServerConnection(ws: WS): void {
|
function requestServerConnection(ws: WS): void {
|
||||||
@@ -204,11 +212,16 @@ function requestServerConnection(ws: WS): void {
|
|||||||
ws.send(messageString);
|
ws.send(messageString);
|
||||||
}
|
}
|
||||||
|
|
||||||
function confirmSubscription(ws: WS, messageChannel: string): void {
|
function confirmSubscription(
|
||||||
|
subscriber: Subscriber,
|
||||||
|
messageChannel: string
|
||||||
|
): void {
|
||||||
const messageObject = {
|
const messageObject = {
|
||||||
messageChannel,
|
messageChannel,
|
||||||
subscribed: subscriptionMap.getChannelList(ws) ? true : false,
|
subscribed: subscriptionMap.getChannelList(subscriber)?.has(messageChannel)
|
||||||
|
? true
|
||||||
|
: false,
|
||||||
};
|
};
|
||||||
const messageString = stringifyMessage(messageObject);
|
const messageString = stringifyMessage(messageObject);
|
||||||
ws.send(messageString);
|
subscriber.send(messageString);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user