mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-17 13:05:32 +09:00
refactor(voice): remove heartbeat and debug logging sessions (#2121)
This commit is contained in:
1 parent
36b85512c6
commit
b4d9cdc584
33 files changed
+566
-3783
No files matched your search
@@ -1,11 +1,6 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import {
|
||||
coerceNumberFromString,
|
||||
createStringType,
|
||||
SnowflakeStringType,
|
||||
SnowflakeType,
|
||||
} from '@fluxer/schema/src/primitives/SchemaPrimitives';
|
||||
import {createStringType, SnowflakeStringType, SnowflakeType} from '@fluxer/schema/src/primitives/SchemaPrimitives';
|
||||
import {z} from 'zod';
|
||||
|
||||
function areServerCoordinatesPaired(
|
||||
@@ -266,64 +261,6 @@ export const GetVoiceServerResponse = z.object({
|
||||
|
||||
export type GetVoiceServerResponse = z.infer<typeof GetVoiceServerResponse>;
|
||||
|
||||
const DiagnosticsTimestampMs = coerceNumberFromString(z.number().int().min(0).max(8640000000000000)).describe(
|
||||
'Unix timestamp in milliseconds',
|
||||
);
|
||||
|
||||
const DiagnosticsSessionId = z
|
||||
.string()
|
||||
.min(1)
|
||||
.max(128)
|
||||
.regex(/^[A-Za-z0-9_.:-]+$/)
|
||||
.optional()
|
||||
.describe('Optional voice diagnostics session id filter');
|
||||
|
||||
export const VoiceDiagnosticsQueryRequest = z
|
||||
.object({
|
||||
channel_id: SnowflakeStringType.describe('Channel id to query diagnostics for'),
|
||||
start_ms: DiagnosticsTimestampMs.describe('Inclusive start timestamp in milliseconds'),
|
||||
end_ms: DiagnosticsTimestampMs.describe('Inclusive end timestamp in milliseconds'),
|
||||
session_id: DiagnosticsSessionId,
|
||||
limit_objects: coerceNumberFromString(z.number().int().min(1).max(5000))
|
||||
.optional()
|
||||
.default(1000)
|
||||
.describe('Maximum matching S3 objects to include'),
|
||||
})
|
||||
.superRefine((value, ctx) => {
|
||||
if (value.end_ms < value.start_ms) {
|
||||
ctx.addIssue({
|
||||
code: 'custom',
|
||||
path: ['end_ms'],
|
||||
message: 'INVALID_FORMAT',
|
||||
});
|
||||
}
|
||||
const maxRangeMs = 31 * 24 * 60 * 60 * 1000;
|
||||
if (value.end_ms - value.start_ms > maxRangeMs) {
|
||||
ctx.addIssue({
|
||||
code: 'custom',
|
||||
path: ['end_ms'],
|
||||
message: 'INVALID_FORMAT',
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
export type VoiceDiagnosticsQueryRequest = z.infer<typeof VoiceDiagnosticsQueryRequest>;
|
||||
|
||||
const VoiceDiagnosticsObjectResponse = z.object({
|
||||
key: z.string().describe('S3 object key'),
|
||||
session_id: z.string().describe('Voice diagnostics session id'),
|
||||
start_ns: z.string().describe('First client event timestamp in the object, in nanoseconds'),
|
||||
end_ns: z.string().describe('Last client event timestamp in the object, in nanoseconds'),
|
||||
last_modified: z.iso.datetime().nullable().describe('S3 object last-modified timestamp'),
|
||||
});
|
||||
|
||||
export const VoiceDiagnosticsObjectListResponse = z.object({
|
||||
bucket: z.string().describe('Diagnostics S3 bucket'),
|
||||
objects: z.array(VoiceDiagnosticsObjectResponse).describe('Matching diagnostics objects'),
|
||||
});
|
||||
|
||||
export type VoiceDiagnosticsObjectListResponse = z.infer<typeof VoiceDiagnosticsObjectListResponse>;
|
||||
|
||||
export const CreateVoiceServerResponse = z.object({
|
||||
server: VoiceServerAdminResponse.describe('Created voice server'),
|
||||
});
|
||||
|
||||
@@ -24,7 +24,6 @@ import {createBase64StringType} from '@fluxer/schema/src/primitives/FileValidato
|
||||
import {ContentWarningLevelSchema} from '@fluxer/schema/src/primitives/GuildValidators';
|
||||
import {QueryBooleanType} from '@fluxer/schema/src/primitives/QueryValidators';
|
||||
import {
|
||||
coerceNumberFromString,
|
||||
createNamedLiteral,
|
||||
createNamedLiteralUnion,
|
||||
createStringType,
|
||||
@@ -292,46 +291,6 @@ export const CallRingBodySchema = z.object({
|
||||
|
||||
export type CallRingBodySchema = z.infer<typeof CallRingBodySchema>;
|
||||
|
||||
export const VoiceDebugLoggingToggleBodySchema = z.object({
|
||||
enabled: z.boolean().describe('Whether voice debug logging should be active for this channel'),
|
||||
duration_ms: coerceNumberFromString(z.number().int().min(60000).max(14400000))
|
||||
.optional()
|
||||
.describe('Optional activation duration in milliseconds. Defaults to one hour and is capped at four hours.'),
|
||||
});
|
||||
|
||||
export type VoiceDebugLoggingToggleBodySchema = z.infer<typeof VoiceDebugLoggingToggleBodySchema>;
|
||||
|
||||
const VoiceDebugLoggingTimestampNs = z
|
||||
.string()
|
||||
.regex(/^[0-9]{1,32}$/)
|
||||
.describe('Nanosecond timestamp encoded as an unsigned decimal string');
|
||||
|
||||
export const VoiceDebugLoggingEventSchema = z
|
||||
.object({
|
||||
type: createStringType(1, 128).describe('Client-side diagnostic event type'),
|
||||
timestamp_ns: VoiceDebugLoggingTimestampNs.describe('Client wall-clock Unix timestamp in nanoseconds'),
|
||||
monotonic_ns: VoiceDebugLoggingTimestampNs.optional().describe('Client monotonic timestamp in nanoseconds'),
|
||||
data: z.record(z.string(), z.unknown()).optional().describe('Event-specific diagnostic payload'),
|
||||
})
|
||||
.passthrough();
|
||||
|
||||
export type VoiceDebugLoggingEventSchema = z.infer<typeof VoiceDebugLoggingEventSchema>;
|
||||
|
||||
export const VoiceDebugLoggingEventsBodySchema = z.object({
|
||||
session_id: createStringType(1, 128).describe('Active voice debug logging session id'),
|
||||
connection_id: createStringType(1, 128).optional().describe('Client voice connection id'),
|
||||
participant_identity: createStringType(1, 256).optional().describe('LiveKit participant identity'),
|
||||
events: z.array(VoiceDebugLoggingEventSchema).min(1).max(200).describe('NDJSON batch events to store'),
|
||||
});
|
||||
|
||||
export type VoiceDebugLoggingEventsBodySchema = z.infer<typeof VoiceDebugLoggingEventsBodySchema>;
|
||||
|
||||
export const VoicePresenceHeartbeatBodySchema = z.object({
|
||||
connection_id: createStringType(1, 128).describe('Client voice connection id'),
|
||||
});
|
||||
|
||||
export type VoicePresenceHeartbeatBodySchema = z.infer<typeof VoicePresenceHeartbeatBodySchema>;
|
||||
|
||||
export const StreamUpdateBodySchema = z.object({
|
||||
region: createStringType(RTC_REGION_ID_MIN_LENGTH, RTC_REGION_ID_MAX_LENGTH)
|
||||
.optional()
|
||||
|
||||
@@ -47,46 +47,6 @@ export const CallEligibilityResponse = z.object({
|
||||
|
||||
export type CallEligibilityResponse = z.infer<typeof CallEligibilityResponse>;
|
||||
|
||||
export const VoiceDebugLoggingStatusResponse = z.object({
|
||||
active: z.boolean().describe('Whether clients in this channel should currently send voice diagnostics'),
|
||||
session_id: z.string().nullable().describe('Current debug logging session id, if active'),
|
||||
activated_by_user_id: SnowflakeStringType.nullable().describe('Staff user that activated the session, if active'),
|
||||
started_at_ms: z.number().int().nonnegative().nullable().describe('Session start Unix timestamp in milliseconds'),
|
||||
expires_at_ms: z
|
||||
.number()
|
||||
.int()
|
||||
.nonnegative()
|
||||
.nullable()
|
||||
.describe('Session expiration Unix timestamp in milliseconds'),
|
||||
poll_interval_ms: Int32Type.describe('Recommended client polling interval in milliseconds'),
|
||||
upload_interval_ms: Int32Type.describe('Recommended client telemetry batch upload interval in milliseconds'),
|
||||
});
|
||||
|
||||
export type VoiceDebugLoggingStatusResponse = z.infer<typeof VoiceDebugLoggingStatusResponse>;
|
||||
|
||||
export const VoiceDebugLoggingEventsResponse = z.object({
|
||||
accepted: z.boolean().describe('Whether the telemetry batch was accepted for storage'),
|
||||
active: z.boolean().describe('Whether the server still considers this logging session active'),
|
||||
stored_event_count: Int32Type.describe('Number of events written to diagnostics storage'),
|
||||
});
|
||||
|
||||
export type VoiceDebugLoggingEventsResponse = z.infer<typeof VoiceDebugLoggingEventsResponse>;
|
||||
|
||||
export const VoicePresenceHeartbeatResponse = z.object({
|
||||
ok: z.boolean().describe('Whether the heartbeat was accepted'),
|
||||
heartbeat_interval_ms: Int32Type.describe('Recommended client heartbeat interval in milliseconds'),
|
||||
heartbeat_ttl_ms: Int32Type.describe('Server-side heartbeat expiration window in milliseconds'),
|
||||
expires_at_ms: z.number().int().nonnegative().describe('Unix timestamp in milliseconds when this heartbeat expires'),
|
||||
});
|
||||
|
||||
export type VoicePresenceHeartbeatResponse = z.infer<typeof VoicePresenceHeartbeatResponse>;
|
||||
|
||||
export const VoicePresenceHeartbeatEndResponse = z.object({
|
||||
ok: z.boolean().describe('Whether the heartbeat was ended'),
|
||||
});
|
||||
|
||||
export type VoicePresenceHeartbeatEndResponse = z.infer<typeof VoicePresenceHeartbeatEndResponse>;
|
||||
|
||||
export const ChannelResponse = z.object({
|
||||
id: SnowflakeStringType.describe('The unique identifier (snowflake) for this channel'),
|
||||
guild_id: SnowflakeStringType.optional().describe('The ID of the guild this channel belongs to'),
|
||||
|
||||
Reference in new issue
Block a user