Files
GMW/docs/specs/2026-08-30_voice-autoreconnect-persistent-spec.md
T
asepharyana b3418ad799 feat: Implement video capture improvements and mobile navigation fixes
- 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.
2026-09-11 18:56:28 +07:00

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.