refactor: atomic, DRY, and logging improvements
- Shared Redis channel constants as single source of truth (redis-channels.ts) - commandHandler.ts split into VoiceHandler, MediaHandler, GuildHandler, ModerationHandler with handler-registry.ts dispatch - messageStore.ts (1322 lines) split into domain-specific DB files: messages.db.ts, attachments.db.ts, reviews.db.ts, moderation-actions.db.ts, retention.db.ts - recorder.ts startSpeaking callback extracted into speakingHandler.ts, streamSetup.ts, segmentFinalizer.ts - autoDeleteManager.ts split into autoDeleteEligibility.ts, autoDeleteNotify.ts, autoDeleteLogger.ts - Added createChildLogger() logging across 8 service files - Backend messages.repository.ts migrated from raw SQL to Drizzle ORM - Fixed biome.json to exclude packages/**/dist/* from lint - Fixed config.ts GUILD_ID pre-existing type error Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
7108f6bb47
commit
b68789fffc
@@ -1,4 +1,4 @@
|
||||
import type { CustomLogger } from "@bete/shared/logger";
|
||||
import { type CustomLogger, createChildLogger } from "@bete/shared/logger";
|
||||
import Redis from "ioredis";
|
||||
import { type DiscordGatewayEvent, EventChannels } from "./eventTypes.js";
|
||||
|
||||
@@ -37,12 +37,14 @@ export class RedisEventPublisher {
|
||||
|
||||
export class EventBroadcaster {
|
||||
private publisher: RedisEventPublisher;
|
||||
private logger = createChildLogger("event-broadcaster");
|
||||
|
||||
constructor(publisher: RedisEventPublisher) {
|
||||
this.publisher = publisher;
|
||||
}
|
||||
|
||||
async messageCreated(data: unknown): Promise<void> {
|
||||
this.logger.debug({ data }, "Publishing message_created");
|
||||
await this.publisher.publish(EventChannels.MESSAGE_CREATED, {
|
||||
type: "message_created",
|
||||
data,
|
||||
@@ -52,6 +54,7 @@ export class EventBroadcaster {
|
||||
}
|
||||
|
||||
async messageUpdated(data: unknown): Promise<void> {
|
||||
this.logger.debug({ data }, "Publishing message_updated");
|
||||
await this.publisher.publish(EventChannels.MESSAGE_UPDATED, {
|
||||
type: "message_updated",
|
||||
data,
|
||||
@@ -61,6 +64,7 @@ export class EventBroadcaster {
|
||||
}
|
||||
|
||||
async messageDeleted(data: unknown): Promise<void> {
|
||||
this.logger.debug({ data }, "Publishing message_deleted");
|
||||
await this.publisher.publish(EventChannels.MESSAGE_DELETED, {
|
||||
type: "message_deleted",
|
||||
data,
|
||||
@@ -70,6 +74,7 @@ export class EventBroadcaster {
|
||||
}
|
||||
|
||||
async messageAnalyzed(data: unknown): Promise<void> {
|
||||
this.logger.debug({ data }, "Publishing message_analyzed");
|
||||
await this.publisher.publish(EventChannels.MESSAGE_ANALYZED, {
|
||||
type: "message_analyzed",
|
||||
data,
|
||||
@@ -79,6 +84,7 @@ export class EventBroadcaster {
|
||||
}
|
||||
|
||||
async attachmentCreated(data: unknown): Promise<void> {
|
||||
this.logger.debug({ data }, "Publishing attachment_created");
|
||||
await this.publisher.publish(EventChannels.ATTACHMENT_CREATED, {
|
||||
type: "attachment_created",
|
||||
data,
|
||||
@@ -88,6 +94,7 @@ export class EventBroadcaster {
|
||||
}
|
||||
|
||||
async attachmentUploaded(data: unknown): Promise<void> {
|
||||
this.logger.debug({ data }, "Publishing attachment_uploaded");
|
||||
await this.publisher.publish(EventChannels.ATTACHMENT_UPLOADED, {
|
||||
type: "attachment_uploaded",
|
||||
data,
|
||||
@@ -97,6 +104,7 @@ export class EventBroadcaster {
|
||||
}
|
||||
|
||||
async voiceRecordingStarted(data: unknown): Promise<void> {
|
||||
this.logger.debug({ data }, "Publishing voice_recording_started");
|
||||
await this.publisher.publish(EventChannels.VOICE_STARTED, {
|
||||
type: "voice_recording_started",
|
||||
data,
|
||||
@@ -106,6 +114,7 @@ export class EventBroadcaster {
|
||||
}
|
||||
|
||||
async voiceRecordingStopped(data: unknown): Promise<void> {
|
||||
this.logger.debug({ data }, "Publishing voice_recording_stopped");
|
||||
await this.publisher.publish(EventChannels.VOICE_STOPPED, {
|
||||
type: "voice_recording_stopped",
|
||||
data,
|
||||
@@ -115,6 +124,7 @@ export class EventBroadcaster {
|
||||
}
|
||||
|
||||
async voiceRecordingUploaded(data: unknown): Promise<void> {
|
||||
this.logger.debug({ data }, "Publishing voice_recording_uploaded");
|
||||
await this.publisher.publish(EventChannels.VOICE_UPLOADED, {
|
||||
type: "voice_recording_uploaded",
|
||||
data,
|
||||
@@ -134,6 +144,10 @@ export class EventBroadcaster {
|
||||
userId: string,
|
||||
metadata?: Record<string, unknown>,
|
||||
): Promise<void> {
|
||||
this.logger.debug(
|
||||
{ userId, pcmSize: pcmBuffer.length },
|
||||
"Publishing voice_pcm_data",
|
||||
);
|
||||
await this.publisher.publish(EventChannels.VOICE_PCM, {
|
||||
type: "voice_pcm_data",
|
||||
data: {
|
||||
@@ -155,6 +169,10 @@ export class EventBroadcaster {
|
||||
userId: string,
|
||||
data: { username: string; avatar: string; speaking: boolean },
|
||||
): Promise<void> {
|
||||
this.logger.debug(
|
||||
{ userId, speaking: data.speaking },
|
||||
"Publishing voice_active_user",
|
||||
);
|
||||
await this.publisher.publish(EventChannels.VOICE_ACTIVE_USER, {
|
||||
type: "voice_active_user",
|
||||
data: {
|
||||
@@ -167,6 +185,7 @@ export class EventBroadcaster {
|
||||
}
|
||||
|
||||
async analysisQueueStatus(data: unknown): Promise<void> {
|
||||
this.logger.debug({ data }, "Publishing analysis_queue_status");
|
||||
await this.publisher.publish(EventChannels.ANALYSIS_QUEUE_STATUS, {
|
||||
type: "analysis_queue_status",
|
||||
data,
|
||||
@@ -176,6 +195,7 @@ export class EventBroadcaster {
|
||||
}
|
||||
|
||||
async close(): Promise<void> {
|
||||
this.logger.debug("Closing event broadcaster");
|
||||
await this.publisher.close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +1,35 @@
|
||||
export interface DiscordGatewayEvent {
|
||||
type: string;
|
||||
data: unknown;
|
||||
timestamp: number;
|
||||
source: string;
|
||||
}
|
||||
import {
|
||||
DISCORD_ANALYSIS_QUEUE_STATUS,
|
||||
DISCORD_ATTACHMENT_CREATED,
|
||||
DISCORD_ATTACHMENT_UPLOADED,
|
||||
DISCORD_MESSAGE_ANALYZED,
|
||||
DISCORD_MESSAGE_CREATED,
|
||||
DISCORD_MESSAGE_DELETED,
|
||||
DISCORD_MESSAGE_UPDATED,
|
||||
DISCORD_VOICE_ACTIVE_USER,
|
||||
DISCORD_VOICE_PCM,
|
||||
DISCORD_VOICE_STARTED,
|
||||
DISCORD_VOICE_STOPPED,
|
||||
DISCORD_VOICE_UPLOADED,
|
||||
type DiscordGatewayEvent,
|
||||
} from "@bete/shared";
|
||||
|
||||
export type { DiscordGatewayEvent };
|
||||
|
||||
export const EventChannels = {
|
||||
MESSAGE_CREATED: "discord:message:created",
|
||||
MESSAGE_UPDATED: "discord:message:updated",
|
||||
MESSAGE_DELETED: "discord:message:deleted",
|
||||
MESSAGE_ANALYZED: "discord:message:analyzed",
|
||||
ATTACHMENT_CREATED: "discord:attachment:created",
|
||||
ATTACHMENT_UPLOADED: "discord:attachment:uploaded",
|
||||
VOICE_STARTED: "discord:voice:started",
|
||||
VOICE_STOPPED: "discord:voice:stopped",
|
||||
VOICE_UPLOADED: "discord:voice:uploaded",
|
||||
MESSAGE_CREATED: DISCORD_MESSAGE_CREATED,
|
||||
MESSAGE_UPDATED: DISCORD_MESSAGE_UPDATED,
|
||||
MESSAGE_DELETED: DISCORD_MESSAGE_DELETED,
|
||||
MESSAGE_ANALYZED: DISCORD_MESSAGE_ANALYZED,
|
||||
ATTACHMENT_CREATED: DISCORD_ATTACHMENT_CREATED,
|
||||
ATTACHMENT_UPLOADED: DISCORD_ATTACHMENT_UPLOADED,
|
||||
VOICE_STARTED: DISCORD_VOICE_STARTED,
|
||||
VOICE_STOPPED: DISCORD_VOICE_STOPPED,
|
||||
VOICE_UPLOADED: DISCORD_VOICE_UPLOADED,
|
||||
// Real-time voice streaming channels
|
||||
VOICE_ACTIVE_USER: "discord:voice:active_user", // Active speaker state updates
|
||||
VOICE_PCM: "discord:voice:pcm", // Live PCM audio data stream
|
||||
ANALYSIS_QUEUE_STATUS: "discord:analysis:queue_status",
|
||||
VOICE_ACTIVE_USER: DISCORD_VOICE_ACTIVE_USER, // Active speaker state updates
|
||||
VOICE_PCM: DISCORD_VOICE_PCM, // Live PCM audio data stream
|
||||
ANALYSIS_QUEUE_STATUS: DISCORD_ANALYSIS_QUEUE_STATUS,
|
||||
} as const;
|
||||
|
||||
export type EventChannelType =
|
||||
|
||||
Reference in New Issue
Block a user