avoid duplicate channels in WS connection

This commit is contained in:
Hazelnoot 2025-03-27 12:33:38 -04:00
parent 14a7309cfb
commit eff7321860

View file

@ -35,7 +35,7 @@ export default class Connection {
public token?: MiAccessToken; public token?: MiAccessToken;
private wsConnection: WebSocket.WebSocket; private wsConnection: WebSocket.WebSocket;
public subscriber: StreamEventEmitter; public subscriber: StreamEventEmitter;
private channels: Channel[] = []; private channels = new Map<string, Channel>();
private subscribingNotes = new Map<string, number>(); private subscribingNotes = new Map<string, number>();
private cachedNotes = new Map<string, Packed<'Note'>>(); private cachedNotes = new Map<string, Packed<'Note'>>();
public userProfile: MiUserProfile | null = null; public userProfile: MiUserProfile | null = null;
@ -299,7 +299,11 @@ export default class Connection {
*/ */
@bindThis @bindThis
public connectChannel(id: string, params: JsonObject | undefined, channel: string, pong = false) { public connectChannel(id: string, params: JsonObject | undefined, channel: string, pong = false) {
if (this.channels.length >= MAX_CHANNELS_PER_CONNECTION) { if (this.channels.has(id)) {
this.disconnectChannel(id);
}
if (this.channels.size >= MAX_CHANNELS_PER_CONNECTION) {
return; return;
} }
@ -315,12 +319,16 @@ export default class Connection {
} }
// 共有可能チャンネルに接続しようとしていて、かつそのチャンネルに既に接続していたら無意味なので無視 // 共有可能チャンネルに接続しようとしていて、かつそのチャンネルに既に接続していたら無意味なので無視
if (channelService.shouldShare && this.channels.some(c => c.chName === channel)) { if (channelService.shouldShare) {
return; for (const c of this.channels.values()) {
if (c.chName === channel) {
return;
}
}
} }
const ch: Channel = channelService.create(id, this); const ch: Channel = channelService.create(id, this);
this.channels.push(ch); this.channels.set(ch.id, ch);
ch.init(params ?? {}); ch.init(params ?? {});
if (pong) { if (pong) {
@ -336,11 +344,11 @@ export default class Connection {
*/ */
@bindThis @bindThis
public disconnectChannel(id: string) { public disconnectChannel(id: string) {
const channel = this.channels.find(c => c.id === id); const channel = this.channels.get(id);
if (channel) { if (channel) {
if (channel.dispose) channel.dispose(); if (channel.dispose) channel.dispose();
this.channels = this.channels.filter(c => c.id !== id); this.channels.delete(id);
} }
} }
@ -355,7 +363,7 @@ export default class Connection {
if (typeof data.type !== 'string') return; if (typeof data.type !== 'string') return;
if (typeof data.body === 'undefined') return; if (typeof data.body === 'undefined') return;
const channel = this.channels.find(c => c.id === data.id); const channel = this.channels.get(data.id);
if (channel != null && channel.onMessage != null) { if (channel != null && channel.onMessage != null) {
channel.onMessage(data.type, data.body); channel.onMessage(data.type, data.body);
} }
@ -367,7 +375,7 @@ export default class Connection {
@bindThis @bindThis
public dispose() { public dispose() {
if (this.fetchIntervalId) clearInterval(this.fetchIntervalId); if (this.fetchIntervalId) clearInterval(this.fetchIntervalId);
for (const c of this.channels.filter(c => c.dispose)) { for (const c of this.channels.values()) {
if (c.dispose) c.dispose(); if (c.dispose) c.dispose();
} }
for (const k of this.subscribingNotes.keys()) { for (const k of this.subscribingNotes.keys()) {
@ -375,7 +383,7 @@ export default class Connection {
} }
this.fetchIntervalId = null; this.fetchIntervalId = null;
this.channels = []; this.channels.clear();
this.subscribingNotes.clear(); this.subscribingNotes.clear();
this.cachedNotes.clear(); this.cachedNotes.clear();
} }