Files
GMW/.hermes/plans/2026-08-24-attachment-delay-fix.md
T
asepharyana 842610b1af fix(ai-moderation): bedah delay attachment ~330s -> target <20s
Root cause (trace msg 1541417073245290638):
- Race-guard upload-pending balik results:[] diperlakukan sbg SUKSES
  -> row yatam 'processing' sampai cleanup 300s mengembalikan
- Vision gagal 3x utk GIF besar (SSE truncation) tanpa fallback

Fix:
- Sinyal eksplisit uploadPending dari worker race guard
- Classifier murni classifyIndividualWorkerResult(): upload_pending ->
  requeue pending + reschedule segera (250ms), bukan error palsu;
  empty-results ok:true kini error transien (bug silent-success mati)
- llmVision fallback stream:false sekali saat SSE truncation
- Safety-net cleanup stuck processing 300s -> 120s
2026-08-24 22:05:28 +07:00

57 lines
3.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Spec: Perbaiki Delay Attachment 162s→<20s (GMW AI Analysis)
Tanggal: 2026-08-24 · Repo `~/GMW` · Service discord-gateway
## Evidence (audit produksi)
Klaster pesan attachment delay ~330400 detik. Trace pesan `1541417073245290638` (.gif):
19:01:08 dibuat → 19:01:09 batch incomplete → fan-out individual → **guard upload-pending
mengembalikan `results:[]`** → diperalakukan sukses (`complete ... (undefined)`) → row
tertahan `ai_status='processing'` **tanpa penanggung jawab** → 19:06:12 cleanup mengembalikan
ke `pending` (tepat 300s) → baru dianalisis. Plus vision gagal 3× utk GIF besar
("Stream ended before producing a non-ping SSE event") → degradasi teks.
## Root causes
- **A (fatal)**: `individualFallbackProcessor.processIndividualFallback` memperlakukan
`ok:true + results:[]` sebagai sukses. Race-guard upload di `ai-analysis-worker.processIndividual`
sengaja balik `results:[]` (desain lama) → pesan yatim `processing` sampai cleanup 300s.
- **B**: `llmVision` hanya mencoba `stream:true`; kegagalan SSE truncation pada gambar besar
= 3 retry sia-sia (semua jalur sama) → bukti media hilang.
- **C**: safety-net cleanup 300s terlalu lambat sbg satu-satunya pemulih `processing`.
## Fix
1. **F1 — sinyal eksplisit upload-pending**: `IndividualOkResponse` + field opsional
`uploadPending?: boolean`. Worker set `uploadPending:true` saat race guard kena.
2. **F2 — processor menangani 3 kondisi** via helper murni baru
`classifyIndividualWorkerResult(result): "success" | "upload_pending" | "incomplete" | "error"`
(modul baru `fallbackResultClassifier.ts`, zero-dep agar mudah dites):
- `upload_pending` → tulis ulang row ke `pending` (pola sama dgn revert apiFailed di
batchProcessor) + broadcast + **re-schedule analisis percakapan segera**
(dynamic import batchScheduler, pola anti-siklus yg sudah ada) → retry dalam ~250ms
begitu upload beres. Bukan error, tidak naikkan CB counter.
- `incomplete` (flags analysis_incomplete) → perilaku lama (exhausted path).
- `error` / `results kosong tanpa penjelasan` → throw transien (retry oleh recovery),
BUKAN sukses palsu. Log "(undefined)" hilang.
3. **F3 — vision non-stream fallback**: di `llmVision`, jika error match
`/Stream ended before producing a non-ping SSE|stream ended/i` → coba SEKALI lagi dengan
`stream:false` (router agregasi penuh; timeout tetap 60s). Konversi hard-fail jadi sukses.
4. **F4 — turunkan safety net**: default `revertStuckProcessingMessages` 300000 → 120000 ms.
## File disentuh
- `src/modules/ai-moderation/fallbackResultClassifier.ts` (BARU, pure)
- `src/modules/ai-moderation/ai-analysis-worker.ts` (tipe + set flag uploadPending)
- `src/modules/ai-moderation/individualFallbackProcessor.ts` (konsumsi classifier + reschedule)
- `src/modules/ai-moderation/llmClient.ts` (fallback non-stream di llmVision)
- `src/modules/message-capture/messagesCleanup.ts` (default 120s)
## Verifikasi
- Test baru `tests/fallbackResultClassifier.test.ts` (4 klasifikasi + edge kosong).
- Gate: tsc --noEmit, biome error-level, vitest run semua hijau.
- Deploy GHA sukses; pasca-deploy: pesan attachment baru p50 < 20s
(`SELECT percentile_cont(0.5) ... WHERE metadata attachments>0 AND created_at > deploy`),
tidak ada lagi "complete ... (undefined)".