mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-07 19:22:14 +09:00
chore(voice): remove voice reconciliation leftovers (#2810)
This commit is contained in:
@@ -1,11 +1,7 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import type {ChannelID, GuildID, UserID} from '@app/api/BrandedTypes';
|
||||
import type {
|
||||
ILiveKitService,
|
||||
ListActiveRoomsResult,
|
||||
ListParticipantsResult,
|
||||
} from '@app/api/infrastructure/ILiveKitService';
|
||||
import type {ILiveKitService, ListParticipantsResult} from '@app/api/infrastructure/ILiveKitService';
|
||||
import type {VoiceRegionMetadata, VoiceServerRecord} from '@app/api/voice/VoiceModel';
|
||||
|
||||
interface CreateTokenParams {
|
||||
@@ -78,10 +74,6 @@ export class DisabledLiveKitService implements ILiveKitService {
|
||||
return {status: 'ok', participants: []};
|
||||
}
|
||||
|
||||
async listActiveRooms(): Promise<ListActiveRoomsResult> {
|
||||
return {rooms: [], errors: [], searchedServers: 0, completed: true};
|
||||
}
|
||||
|
||||
getDefaultRegionId(): string | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import type {ChannelID, GuildID, MessageID, RoleID, UserID} from '@app/api/BrandedTypes';
|
||||
import {createChannelID, createGuildID, createRoleID, createUserID} from '@app/api/BrandedTypes';
|
||||
import {createChannelID, createRoleID, createUserID} from '@app/api/BrandedTypes';
|
||||
import {SYSTEM_USER_ID} from '@app/api/constants/Core';
|
||||
import type {GatewayDispatchEvent} from '@app/api/constants/Gateway';
|
||||
import {GatewayRpcClient} from '@app/api/infrastructure/GatewayRpcClient';
|
||||
import {GatewayRpcMethodError, GatewayRpcMethodErrorCodes} from '@app/api/infrastructure/GatewayRpcError';
|
||||
import type {
|
||||
CallData,
|
||||
GatewayActiveVoiceRooms,
|
||||
GatewayChannelMention,
|
||||
GatewayGuildMemoryStats,
|
||||
GatewayMentionSources,
|
||||
@@ -1066,26 +1065,6 @@ export class GatewayService {
|
||||
};
|
||||
}
|
||||
|
||||
async getActiveVoiceRooms(): Promise<GatewayActiveVoiceRooms> {
|
||||
const result = await this.call<{
|
||||
rooms?: Array<{
|
||||
guild_id?: string | null;
|
||||
channel_id: string;
|
||||
voice_state_count?: number;
|
||||
}>;
|
||||
node_count?: number;
|
||||
}>('process.active_voice_rooms', {});
|
||||
return {
|
||||
nodeCount: result.node_count ?? 0,
|
||||
rooms: (result.rooms ?? []).map((room) => ({
|
||||
guildId:
|
||||
room.guild_id === undefined || room.guild_id === null ? undefined : createGuildID(BigInt(room.guild_id)),
|
||||
channelId: createChannelID(BigInt(room.channel_id)),
|
||||
voiceStateCount: room.voice_state_count ?? 0,
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
async getUserPermissions({guildId, userId, channelId}: UserPermissionsParams): Promise<bigint> {
|
||||
const result = await this.call<{
|
||||
permissions: string;
|
||||
@@ -1638,41 +1617,6 @@ export class GatewayService {
|
||||
};
|
||||
}
|
||||
|
||||
async repairVoiceStateFromCache({
|
||||
guildId,
|
||||
channelId,
|
||||
userId,
|
||||
connectionId,
|
||||
}: {
|
||||
guildId?: GuildID;
|
||||
channelId: ChannelID;
|
||||
userId: UserID;
|
||||
connectionId: string;
|
||||
}): Promise<{
|
||||
success: boolean;
|
||||
repaired?: boolean;
|
||||
error?: string;
|
||||
}> {
|
||||
const params: Record<string, string> = {
|
||||
channel_id: channelId.toString(),
|
||||
user_id: userId.toString(),
|
||||
connection_id: connectionId,
|
||||
};
|
||||
if (guildId !== undefined) {
|
||||
params['guild_id'] = guildId.toString();
|
||||
}
|
||||
const result = await this.call<{
|
||||
success: boolean;
|
||||
repaired?: boolean;
|
||||
error?: string;
|
||||
}>('voice.repair_state_from_cache', params);
|
||||
return {
|
||||
success: result.success,
|
||||
repaired: result.repaired,
|
||||
error: result.error,
|
||||
};
|
||||
}
|
||||
|
||||
async getVoiceStatesForChannel({guildId, channelId}: {guildId?: GuildID; channelId: ChannelID}): Promise<{
|
||||
voiceStates: Array<GatewayVoiceStateEntry>;
|
||||
}> {
|
||||
|
||||
@@ -88,17 +88,6 @@ export interface GatewayVoiceStateCounts {
|
||||
servers: Array<GatewayVoiceStateServerCount>;
|
||||
}
|
||||
|
||||
export interface GatewayActiveVoiceRoom {
|
||||
guildId?: GuildID;
|
||||
channelId: ChannelID;
|
||||
voiceStateCount: number;
|
||||
}
|
||||
|
||||
export interface GatewayActiveVoiceRooms {
|
||||
rooms: Array<GatewayActiveVoiceRoom>;
|
||||
nodeCount: number;
|
||||
}
|
||||
|
||||
export interface GatewayVoiceStateEntry {
|
||||
connectionId: string;
|
||||
userId: string;
|
||||
@@ -162,8 +151,6 @@ export abstract class IGatewayService {
|
||||
|
||||
abstract getVoiceStateCounts(): Promise<GatewayVoiceStateCounts>;
|
||||
|
||||
abstract getActiveVoiceRooms(): Promise<GatewayActiveVoiceRooms>;
|
||||
|
||||
abstract getUsersToMentionByRoles(params: {
|
||||
guildId: GuildID;
|
||||
channelId: ChannelID;
|
||||
@@ -345,17 +332,6 @@ export abstract class IGatewayService {
|
||||
error?: string;
|
||||
}>;
|
||||
|
||||
abstract repairVoiceStateFromCache(params: {
|
||||
guildId?: GuildID;
|
||||
channelId: ChannelID;
|
||||
userId: UserID;
|
||||
connectionId: string;
|
||||
}): Promise<{
|
||||
success: boolean;
|
||||
repaired?: boolean;
|
||||
error?: string;
|
||||
}>;
|
||||
|
||||
abstract getVoiceStatesForChannel(params: {guildId?: GuildID; channelId: ChannelID}): Promise<{
|
||||
voiceStates: Array<GatewayVoiceStateEntry>;
|
||||
}>;
|
||||
|
||||
@@ -61,13 +61,6 @@ interface ListParticipantsParams {
|
||||
serverId: string;
|
||||
}
|
||||
|
||||
export interface LiveKitServerError {
|
||||
regionId: string;
|
||||
serverId: string;
|
||||
errorCode: string;
|
||||
retryable: boolean;
|
||||
}
|
||||
|
||||
export interface ListParticipantsSuccess {
|
||||
status: 'ok';
|
||||
participants: Array<{
|
||||
@@ -84,19 +77,6 @@ export interface ListParticipantsError {
|
||||
|
||||
export type ListParticipantsResult = ListParticipantsSuccess | ListParticipantsError;
|
||||
|
||||
export interface LiveKitRoomLocation {
|
||||
roomName: string;
|
||||
regionId: string;
|
||||
serverId: string;
|
||||
}
|
||||
|
||||
export interface ListActiveRoomsResult {
|
||||
rooms: Array<LiveKitRoomLocation>;
|
||||
errors: Array<LiveKitServerError>;
|
||||
searchedServers: number;
|
||||
completed: boolean;
|
||||
}
|
||||
|
||||
export abstract class ILiveKitService {
|
||||
abstract createToken(params: CreateTokenParams): Promise<{
|
||||
token: string;
|
||||
@@ -111,8 +91,6 @@ export abstract class ILiveKitService {
|
||||
|
||||
abstract listParticipants(params: ListParticipantsParams): Promise<ListParticipantsResult>;
|
||||
|
||||
abstract listActiveRooms(): Promise<ListActiveRoomsResult>;
|
||||
|
||||
abstract getDefaultRegionId(): string | null;
|
||||
|
||||
abstract getRegionMetadata(): Array<VoiceRegionMetadata>;
|
||||
|
||||
@@ -2,11 +2,7 @@
|
||||
|
||||
import type {ChannelID, GuildID, UserID} from '@app/api/BrandedTypes';
|
||||
import {Config} from '@app/api/Config';
|
||||
import type {
|
||||
ListActiveRoomsResult,
|
||||
ListParticipantsResult,
|
||||
LiveKitServerError,
|
||||
} from '@app/api/infrastructure/ILiveKitService';
|
||||
import type {ListParticipantsResult} from '@app/api/infrastructure/ILiveKitService';
|
||||
import {ILiveKitService} from '@app/api/infrastructure/ILiveKitService';
|
||||
import {Logger} from '@app/api/Logger';
|
||||
import type {VoiceRegionMetadata, VoiceServerRecord} from '@app/api/voice/VoiceModel';
|
||||
@@ -339,39 +335,6 @@ export class LiveKitService extends ILiveKitService {
|
||||
}
|
||||
}
|
||||
|
||||
async listActiveRooms(): Promise<ListActiveRoomsResult> {
|
||||
const rooms: ListActiveRoomsResult['rooms'] = [];
|
||||
const errors: Array<LiveKitServerError> = [];
|
||||
const servers = this.getActiveServerClients();
|
||||
for (const server of servers) {
|
||||
try {
|
||||
const liveRooms = await server.roomServiceClient.listRooms();
|
||||
for (const room of liveRooms) {
|
||||
if (typeof room.name !== 'string' || room.name.length === 0) {
|
||||
continue;
|
||||
}
|
||||
rooms.push({
|
||||
roomName: room.name,
|
||||
regionId: server.regionId,
|
||||
serverId: server.serverId,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
Logger.warn(
|
||||
{error, regionId: server.regionId, serverId: server.serverId},
|
||||
'LiveKit listRooms failed during voice reconciliation',
|
||||
);
|
||||
errors.push(this.toServerError(server.regionId, server.serverId, error));
|
||||
}
|
||||
}
|
||||
return {
|
||||
rooms,
|
||||
errors,
|
||||
searchedServers: servers.length,
|
||||
completed: errors.length === 0,
|
||||
};
|
||||
}
|
||||
|
||||
private static isHttp404(error: unknown): boolean {
|
||||
return LiveKitService.getHttpStatus(error) === 404;
|
||||
}
|
||||
@@ -396,34 +359,6 @@ export class LiveKitService extends ILiveKitService {
|
||||
return region.get(serverId) ?? null;
|
||||
}
|
||||
|
||||
private getActiveServerClients(): Array<ServerClientConfig & {regionId: string; serverId: string}> {
|
||||
const servers: Array<ServerClientConfig & {regionId: string; serverId: string}> = [];
|
||||
for (const [regionId, region] of this.serverClients.entries()) {
|
||||
for (const [serverId, server] of region.entries()) {
|
||||
if (server.isActive) {
|
||||
servers.push({...server, regionId, serverId});
|
||||
}
|
||||
}
|
||||
}
|
||||
return servers.sort((left, right) => {
|
||||
const regionComparison = left.regionId.localeCompare(right.regionId);
|
||||
if (regionComparison !== 0) {
|
||||
return regionComparison;
|
||||
}
|
||||
return left.serverId.localeCompare(right.serverId);
|
||||
});
|
||||
}
|
||||
|
||||
private toServerError(regionId: string, serverId: string, error: unknown): LiveKitServerError {
|
||||
const status = LiveKitService.getHttpStatus(error);
|
||||
return {
|
||||
regionId,
|
||||
serverId,
|
||||
errorCode: error instanceof Error ? error.message : 'unknown',
|
||||
retryable: status != null && status >= 500,
|
||||
};
|
||||
}
|
||||
|
||||
getDefaultRegionId(): string | null {
|
||||
return this.topology.getDefaultRegionId();
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ export class LiveKitWebhookService {
|
||||
roomName: data.event.room?.name ?? null,
|
||||
eventType: data.event.event,
|
||||
},
|
||||
'LiveKit webhook reports dropped events - reconciliation may be needed',
|
||||
'LiveKit webhook reports dropped events',
|
||||
);
|
||||
}
|
||||
await this.processEvent(data);
|
||||
@@ -256,7 +256,7 @@ export class LiveKitWebhookService {
|
||||
error: result.error,
|
||||
participantIdentity: participant.identity,
|
||||
},
|
||||
'LiveKit participant_joined did not match gateway state; leaving participant connected for reconciliation',
|
||||
'LiveKit participant_joined did not match gateway state; leaving participant connected',
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import {GuildRepository} from '@app/api/guild/repositories/GuildRepository';
|
||||
import {GuildRoleRepository} from '@app/api/guild/repositories/GuildRoleRepository';
|
||||
import {
|
||||
type CallData,
|
||||
type GatewayActiveVoiceRooms,
|
||||
type GatewayChannelMention,
|
||||
type GatewayGuildMemoryStats,
|
||||
type GatewayMentionSources,
|
||||
@@ -168,25 +167,6 @@ export class NoopGatewayService extends IGatewayService {
|
||||
};
|
||||
}
|
||||
|
||||
async getActiveVoiceRooms(): Promise<GatewayActiveVoiceRooms> {
|
||||
return {
|
||||
nodeCount: 1,
|
||||
rooms: Array.from(this.voiceStatesByChannel.entries()).flatMap(([key, voiceStates]) => {
|
||||
if (voiceStates.length === 0) {
|
||||
return [];
|
||||
}
|
||||
const [guildIdText, channelIdText] = key.split(':');
|
||||
return [
|
||||
{
|
||||
guildId: guildIdText === 'dm' ? undefined : (BigInt(guildIdText) as GuildID),
|
||||
channelId: BigInt(channelIdText) as ChannelID,
|
||||
voiceStateCount: voiceStates.length,
|
||||
},
|
||||
];
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
async getUsersToMentionByRoles(_params: {
|
||||
guildId: GuildID;
|
||||
channelId: ChannelID;
|
||||
@@ -882,19 +862,6 @@ export class NoopGatewayService extends IGatewayService {
|
||||
return {success: false};
|
||||
}
|
||||
|
||||
async repairVoiceStateFromCache(_params: {
|
||||
guildId?: GuildID;
|
||||
channelId: ChannelID;
|
||||
userId: UserID;
|
||||
connectionId: string;
|
||||
}): Promise<{
|
||||
success: boolean;
|
||||
repaired?: boolean;
|
||||
error?: string;
|
||||
}> {
|
||||
return {success: false};
|
||||
}
|
||||
|
||||
async getVoiceStatesForChannel(params: {guildId?: GuildID; channelId: ChannelID}): Promise<{
|
||||
voiceStates: Array<GatewayVoiceStateEntry>;
|
||||
}> {
|
||||
|
||||
Reference in New Issue
Block a user