fix: Broken voice states and connectivity drops
This commit is contained in:
@@ -33,6 +33,8 @@ export class ServerMembershipSignalingHandler<TMessage> {
|
||||
return;
|
||||
}
|
||||
|
||||
this.migrateServerSignalUrl(roomId, resolvedSignalUrl);
|
||||
|
||||
this.dependencies.signalingCoordinator.setServerSignalUrl(roomId, resolvedSignalUrl);
|
||||
this.dependencies.signalingCoordinator.setLastJoinedServer(resolvedSignalUrl, {
|
||||
serverId: roomId,
|
||||
@@ -55,6 +57,8 @@ export class ServerMembershipSignalingHandler<TMessage> {
|
||||
return;
|
||||
}
|
||||
|
||||
this.migrateServerSignalUrl(serverId, resolvedSignalUrl);
|
||||
|
||||
this.dependencies.signalingCoordinator.setServerSignalUrl(serverId, resolvedSignalUrl);
|
||||
this.dependencies.signalingCoordinator.setLastJoinedServer(resolvedSignalUrl, {
|
||||
serverId,
|
||||
@@ -99,7 +103,9 @@ export class ServerMembershipSignalingHandler<TMessage> {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const { signalUrl, serverIds } of this.dependencies.signalingCoordinator.getJoinedServerEntries()) {
|
||||
const joinedEntries = this.dependencies.signalingCoordinator.getJoinedServerEntries();
|
||||
|
||||
for (const { signalUrl, serverIds } of joinedEntries) {
|
||||
for (const joinedServerId of serverIds) {
|
||||
this.dependencies.signalingTransport.sendRawMessageToSignalUrl(signalUrl, {
|
||||
type: SIGNALING_TYPE_LEAVE_SERVER,
|
||||
@@ -109,6 +115,11 @@ export class ServerMembershipSignalingHandler<TMessage> {
|
||||
}
|
||||
|
||||
this.dependencies.signalingCoordinator.clearJoinedServers();
|
||||
|
||||
for (const { signalUrl } of joinedEntries) {
|
||||
this.dependencies.signalingCoordinator.pruneUnusedSignalUrl(signalUrl);
|
||||
}
|
||||
|
||||
this.dependencies.runFullCleanup();
|
||||
}
|
||||
|
||||
@@ -116,11 +127,13 @@ export class ServerMembershipSignalingHandler<TMessage> {
|
||||
const resolvedSignalUrl = this.dependencies.signalingCoordinator.getServerSignalUrl(serverId);
|
||||
|
||||
if (resolvedSignalUrl) {
|
||||
this.dependencies.signalingCoordinator.removeJoinedServer(resolvedSignalUrl, serverId);
|
||||
this.dependencies.signalingTransport.sendRawMessageToSignalUrl(resolvedSignalUrl, {
|
||||
type: SIGNALING_TYPE_LEAVE_SERVER,
|
||||
serverId
|
||||
});
|
||||
|
||||
this.dependencies.signalingCoordinator.removeJoinedServer(resolvedSignalUrl, serverId);
|
||||
this.dependencies.signalingCoordinator.pruneUnusedSignalUrl(resolvedSignalUrl);
|
||||
} else {
|
||||
this.dependencies.signalingTransport.sendRawMessage({
|
||||
type: SIGNALING_TYPE_LEAVE_SERVER,
|
||||
@@ -143,4 +156,26 @@ export class ServerMembershipSignalingHandler<TMessage> {
|
||||
?? this.dependencies.signalingCoordinator.getServerSignalUrl(serverId)
|
||||
?? this.getCurrentSignalingUrl();
|
||||
}
|
||||
|
||||
private migrateServerSignalUrl(serverId: string, nextSignalUrl: string): void {
|
||||
const previousSignalUrl = this.dependencies.signalingCoordinator.getServerSignalUrl(serverId);
|
||||
|
||||
if (!previousSignalUrl || previousSignalUrl === nextSignalUrl) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.dependencies.signalingTransport.sendRawMessageToSignalUrl(previousSignalUrl, {
|
||||
type: SIGNALING_TYPE_LEAVE_SERVER,
|
||||
serverId
|
||||
});
|
||||
|
||||
this.dependencies.signalingCoordinator.removeJoinedServer(previousSignalUrl, serverId);
|
||||
this.dependencies.signalingCoordinator.pruneUnusedSignalUrl(previousSignalUrl);
|
||||
|
||||
this.dependencies.logger.info('Migrated server to a new signaling route', {
|
||||
previousSignalUrl,
|
||||
serverId,
|
||||
signalUrl: nextSignalUrl
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,6 +110,10 @@ export class ServerSignalingCoordinator<TMessage> {
|
||||
this.lastJoinedServerBySignalUrl.set(signalUrl, joinedServer);
|
||||
}
|
||||
|
||||
getLastJoinedServer(signalUrl: string): JoinedServerInfo | null {
|
||||
return this.lastJoinedServerBySignalUrl.get(signalUrl) ?? null;
|
||||
}
|
||||
|
||||
clearLastJoinedServers(): void {
|
||||
this.lastJoinedServerBySignalUrl.clear();
|
||||
}
|
||||
@@ -156,15 +160,57 @@ export class ServerSignalingCoordinator<TMessage> {
|
||||
}
|
||||
|
||||
removeJoinedServer(signalUrl: string, serverId: string): void {
|
||||
this.getOrCreateMemberServerSet(signalUrl).delete(serverId);
|
||||
const memberServerIds = this.memberServerIdsBySignalUrl.get(signalUrl);
|
||||
|
||||
if (!memberServerIds) {
|
||||
this.repairLastJoinedServer(signalUrl, serverId);
|
||||
return;
|
||||
}
|
||||
|
||||
memberServerIds.delete(serverId);
|
||||
|
||||
if (memberServerIds.size === 0) {
|
||||
this.memberServerIdsBySignalUrl.delete(signalUrl);
|
||||
}
|
||||
|
||||
this.repairLastJoinedServer(signalUrl, serverId);
|
||||
}
|
||||
|
||||
removeJoinedServerEverywhere(serverId: string): void {
|
||||
for (const memberServerIds of this.memberServerIdsBySignalUrl.values()) {
|
||||
memberServerIds.delete(serverId);
|
||||
for (const signalUrl of Array.from(this.memberServerIdsBySignalUrl.keys())) {
|
||||
this.removeJoinedServer(signalUrl, serverId);
|
||||
this.pruneUnusedSignalUrl(signalUrl);
|
||||
}
|
||||
}
|
||||
|
||||
pruneUnusedSignalUrl(signalUrl: string): void {
|
||||
if (this.getMemberServerIdsForSignalUrl(signalUrl).size > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.memberServerIdsBySignalUrl.delete(signalUrl);
|
||||
this.lastJoinedServerBySignalUrl.delete(signalUrl);
|
||||
|
||||
const subscriptions = this.signalingSubscriptions.get(signalUrl);
|
||||
|
||||
if (subscriptions) {
|
||||
for (const subscription of subscriptions) {
|
||||
subscription.unsubscribe();
|
||||
}
|
||||
|
||||
this.signalingSubscriptions.delete(signalUrl);
|
||||
}
|
||||
|
||||
const manager = this.signalingManagers.get(signalUrl);
|
||||
|
||||
if (manager) {
|
||||
manager.destroy();
|
||||
this.signalingManagers.delete(signalUrl);
|
||||
}
|
||||
|
||||
this.removeSignalUrlFromPeerTracking(signalUrl);
|
||||
}
|
||||
|
||||
getMemberServerIdsForSignalUrl(signalUrl: string): ReadonlySet<string> {
|
||||
return this.memberServerIdsBySignalUrl.get(signalUrl) ?? new Set<string>();
|
||||
}
|
||||
@@ -344,6 +390,45 @@ export class ServerSignalingCoordinator<TMessage> {
|
||||
return trackedServerIds;
|
||||
}
|
||||
|
||||
private repairLastJoinedServer(signalUrl: string, removedServerId: string): void {
|
||||
const lastJoined = this.lastJoinedServerBySignalUrl.get(signalUrl);
|
||||
|
||||
if (!lastJoined) {
|
||||
return;
|
||||
}
|
||||
|
||||
const memberServerIds = this.memberServerIdsBySignalUrl.get(signalUrl);
|
||||
|
||||
if (!memberServerIds || memberServerIds.size === 0) {
|
||||
this.lastJoinedServerBySignalUrl.delete(signalUrl);
|
||||
return;
|
||||
}
|
||||
|
||||
if (lastJoined.serverId !== removedServerId && memberServerIds.has(lastJoined.serverId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const nextServerId = memberServerIds.values().next().value as string | undefined;
|
||||
|
||||
if (!nextServerId) {
|
||||
this.lastJoinedServerBySignalUrl.delete(signalUrl);
|
||||
return;
|
||||
}
|
||||
|
||||
this.lastJoinedServerBySignalUrl.set(signalUrl, {
|
||||
...lastJoined,
|
||||
serverId: nextServerId
|
||||
});
|
||||
}
|
||||
|
||||
private removeSignalUrlFromPeerTracking(signalUrl: string): void {
|
||||
const peerIds = new Set<string>([...this.peerKnownSignalUrls.keys(), ...this.peerServerMap.keys()]);
|
||||
|
||||
for (const peerId of peerIds) {
|
||||
this.removePeerSignalScope(peerId, signalUrl);
|
||||
}
|
||||
}
|
||||
|
||||
private removePeerSignalScope(peerId: string, signalUrl: string): void {
|
||||
const trackedSignalUrls = this.peerServerMap.get(peerId);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { SignalingMessage } from '../../../shared-kernel';
|
||||
import { PeerData } from '../realtime.types';
|
||||
import {
|
||||
SIGNALING_TYPE_ACCESS_DENIED,
|
||||
SIGNALING_TYPE_ANSWER,
|
||||
SIGNALING_TYPE_CONNECTED,
|
||||
SIGNALING_TYPE_ICE_CANDIDATE,
|
||||
@@ -98,6 +99,10 @@ export class IncomingSignalingMessageHandler {
|
||||
this.handleIceCandidateSignalingMessage(message, signalUrl);
|
||||
return;
|
||||
|
||||
case SIGNALING_TYPE_ACCESS_DENIED:
|
||||
this.handleAccessDeniedSignalingMessage(message, signalUrl);
|
||||
return;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
@@ -357,6 +362,16 @@ export class IncomingSignalingMessageHandler {
|
||||
this.dependencies.peerManager.handleIceCandidate(fromUserId, candidate);
|
||||
}
|
||||
|
||||
private handleAccessDeniedSignalingMessage(message: IncomingSignalingMessage, signalUrl: string): void {
|
||||
if (!message.serverId) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove the server from the coordinator for this signal URL so it won't
|
||||
// be re-joined on the next reconnect cycle.
|
||||
this.dependencies.signalingCoordinator.removeJoinedServer(signalUrl, message.serverId);
|
||||
}
|
||||
|
||||
private scheduleUserJoinedFallbackOffer(peerId: string, signalUrl: string, serverId?: string): void {
|
||||
this.clearUserJoinedFallbackOffer(peerId);
|
||||
|
||||
|
||||
@@ -118,6 +118,13 @@ export class SignalingTransportHandler<TMessage> {
|
||||
if (serverSignalUrl && this.sendRawMessageToSignalUrl(serverSignalUrl, message)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.dependencies.logger.warn('[signaling] Missing server signal route for outbound raw message', {
|
||||
serverId,
|
||||
type: messageType
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const connectedManagers = this.getConnectedSignalingManagers();
|
||||
@@ -161,14 +168,14 @@ export class SignalingTransportHandler<TMessage> {
|
||||
displayName: normalizedDisplayName
|
||||
};
|
||||
|
||||
const identifyMessage = {
|
||||
type: SIGNALING_TYPE_IDENTIFY,
|
||||
oderId,
|
||||
displayName: normalizedDisplayName
|
||||
};
|
||||
|
||||
if (signalUrl) {
|
||||
this.sendRawMessageToSignalUrl(signalUrl, identifyMessage);
|
||||
this.sendRawMessageToSignalUrl(signalUrl, {
|
||||
type: SIGNALING_TYPE_IDENTIFY,
|
||||
oderId,
|
||||
displayName: normalizedDisplayName,
|
||||
connectionScope: signalUrl
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -178,8 +185,13 @@ export class SignalingTransportHandler<TMessage> {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const { manager } of connectedManagers) {
|
||||
manager.sendRawMessage(identifyMessage);
|
||||
for (const { signalUrl: managerSignalUrl, manager } of connectedManagers) {
|
||||
manager.sendRawMessage({
|
||||
type: SIGNALING_TYPE_IDENTIFY,
|
||||
oderId,
|
||||
displayName: normalizedDisplayName,
|
||||
connectionScope: managerSignalUrl
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,7 +283,8 @@ export class SignalingManager {
|
||||
if (credentials) {
|
||||
this.sendRawMessage({ type: SIGNALING_TYPE_IDENTIFY,
|
||||
oderId: credentials.oderId,
|
||||
displayName: credentials.displayName });
|
||||
displayName: credentials.displayName,
|
||||
connectionScope: this.lastSignalingUrl ?? undefined });
|
||||
}
|
||||
|
||||
const memberIds = this.getMemberServerIds();
|
||||
@@ -296,17 +297,10 @@ export class SignalingManager {
|
||||
|
||||
const lastJoined = this.getLastJoinedServer();
|
||||
|
||||
if (lastJoined) {
|
||||
if (lastJoined && memberIds.has(lastJoined.serverId)) {
|
||||
this.sendRawMessage({ type: SIGNALING_TYPE_VIEW_SERVER,
|
||||
serverId: lastJoined.serverId });
|
||||
}
|
||||
} else {
|
||||
const lastJoined = this.getLastJoinedServer();
|
||||
|
||||
if (lastJoined) {
|
||||
this.sendRawMessage({ type: SIGNALING_TYPE_JOIN_SERVER,
|
||||
serverId: lastJoined.serverId });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user