- Added eager selfbot voice connection establishment to ensure video capture works seamlessly during voice channel joins. - Introduced a manual video watch command for selfbots to allow operators to initiate screen recording of other members' streams. - Enhanced video recording functionality to split recordings into segments based on user activity, similar to voice recordings. - Fixed mobile navigation issues by extending the navbar to include all items and ensuring responsive form controls. - Standardized error handling across frontend components to improve user experience during failures.
66 lines
3.7 KiB
Markdown
66 lines
3.7 KiB
Markdown
# Spec: Voice auto-reconnect (persistent state + rejoin on drop)
|
|
|
|
## Goal
|
|
Setelah `VoiceController.connect()` berhasil, state "sedang merekam di <guild>/<channel>"
|
|
disimpan di Postgres. Kalau gateway restart/reboot, atau koneksi voice drop tidak
|
|
disengaja (dikeluarkan/moved/server restart), gateway otomatis join ulang ke channel
|
|
yang sama.
|
|
|
|
## Requirement mapping (user's ask)
|
|
- "autoreconnect ke channel yg sama jika server restart atau reboot" → reconnect on
|
|
startup (ready handler) + keep DB record across graceful shutdown.
|
|
- "state nya persistent di db" → `voice_auto_reconnect` table.
|
|
- "rejoin jika tidak sengaja dikeluarkan" → watchdog on `Disconnected`/`Destroyed`
|
|
(kick / moved / voice server restart) → full rejoin with backoff.
|
|
- Manual leave (`/voice disconnect`, dashboard disconnect) MUST NOT rejoin.
|
|
|
|
## Design decisions
|
|
1. **New table** `voice_auto_reconnect` (dedicated, not `ui_state`):
|
|
- `guild_id` text PK
|
|
- `channel_id` text NOT NULL
|
|
- `channel_name` text
|
|
- `connected_at` bigint epoch-ms
|
|
- `updated_at` bigint epoch-ms
|
|
DAO: `voiceAutoReconnectRepo.ts` — `upsert(record)`, `list()`, `delete(guildId)`.
|
|
2. **Write on connect**: `VoiceController.connect()` → after `startRecording` success →
|
|
`upsert`. IDEMPOTENT (upsert per guild).
|
|
3. **Clear on manual leave**: `handleVoiceDisconnect` (all) + `handleVoiceDisconnectGuild`
|
|
pass `clearPersisted: true`. Graceful shutdown `disconnect()` keeps the record.
|
|
4. **Rejoin on startup**: bootstrap `ready` → `await voiceController.autoReconnect()`
|
|
(list persisted → connect each, non-fatal on failure).
|
|
5. **Rejoin on unexpected drop**: monitor per-connection; on `Disconnected`/`Destroyed`
|
|
with `!intentional` → schedule rejoin `connect(guildId, persistedChannelId)` with
|
|
backoff (min 2s, max 30s, max 5 attempts). Track `rejoinAttempts`, reset on success.
|
|
6. **Intentional flag**: `disconnectGuild(guildId, { clearPersisted?, intentional? })`.
|
|
- shutdown `disconnect()` → `{ intentional: true, clearPersisted: false }`.
|
|
- manual `disconnect()` (dashboard) → `{ clearPersisted: true }`, sets intentional.
|
|
- manual `disconnectGuild` → `{ clearPersisted: true }`, sets intentional.
|
|
The monitor checks `intentional` before rejoin; `clearPersisted` only deletes the row.
|
|
|
|
## Files touched
|
|
- `services/discord-gateway/src/shared/database/schema.ts` — add `pgVoiceAutoReconnectTable`
|
|
+ types.
|
|
- `services/discord-gateway/src/shared/database/voiceAutoReconnectRepo.ts` (NEW) — DAO.
|
|
- `services/discord-gateway/src/modules/voice-recording/voiceController.ts` — upsert on
|
|
connect; monitor + rejoin; `autoReconnect()`; `disconnect/disconnectGuild` opts.
|
|
- `services/discord-gateway/src/modules/command-handler/voice.handler.ts` — manual
|
|
disconnect/disconnectGuild pass `clearPersisted: true`.
|
|
- `services/discord-gateway/src/app/bootstrap.ts` — call `voiceController.autoReconnect()`
|
|
in `ready`.
|
|
- `services/discord-gateway/drizzle/migrations/0020_add_voice_auto_reconnect.sql` +
|
|
`meta/_journal.json` entry (apply manually per gmw-ops).
|
|
|
|
## Edge cases
|
|
- Channel deleted / guild lost while persisted → `connect()` throws (channel not found)
|
|
→ log + delete persisted row (don't retry forever).
|
|
- Rejoin attempts exhausted → keep row (so next restart retries) + log.
|
|
- Multiple guilds: per-guild monitor, per-guild persisted row.
|
|
- Graceful shutdown order: shutdown sets intentional=true (so no rejoin during teardown)
|
|
but keeps row.
|
|
|
|
## Verification
|
|
- `pnpm typecheck && pnpm build && pnpm lint` in `services/discord-gateway`.
|
|
- Apply migration `0020` manually; verify table exists.
|
|
- CI `Build & Deploy (Nix)` green; gateway deploy lands.
|
|
- Manual: connect via dashboard → check `voice_auto_reconnect` row; simulate drop →
|
|
confirm rejoin; manual disconnect → row cleared. |