fix(ai-moderation): matikan hot requeue loop saat upload attachment in-flight

Batch race guard balikin {ok:true, rows:[]} tanpa sinyal saat semua target
masih upload-pending -> processor klasifikasi semua incomplete -> fanout ke
individual queue -> di situ requeue + reschedule 250ms -> balik ke batch:
hot loop ~300ms sepanjang upload (10 siklus/3 dtk di log prod 08:13).

Fix: worker batch kini return uploadPendingIds eksplisit; classifier pure
baru (partitionBatchOutcome) partisi completed/upload_pending/incomplete/
parse_failed/api_failed; target upload-pending DEFERRED dengan poll backoff
linear (AI_ANALYSIS_UPLOAD_POLL_MS 1500 base, cap AI_ANALYSIS_MAX_UPLOAD_POLL_MS
8000), tidak pernah masuk fanout; tail shouldScheduleNext tak menimpa defer.
Test: tests/batchOutcomeClassifier.test.ts (8 kasus, pure tanpa DB/Piscina).
This commit is contained in:
asepharyana
2026-08-25 10:37:11 +07:00
parent 9ef7d005fb
commit ecbf2617e4
5 changed files with 343 additions and 27 deletions
@@ -254,6 +254,12 @@ export const configSchema = z
.positive()
.default(10000),
AI_ANALYSIS_ERROR_COOLDOWN_MS: z.coerce.number().positive().default(30000),
// Upload-pending batch poll (2026-08-25): when a batch is deferred because
// attachments are still uploading, the processor re-schedules with this
// base delay (linear ramp per consecutive poll, capped) instead of the
// 250ms debounce — the old path hot-looped ~300ms for the whole upload.
AI_ANALYSIS_UPLOAD_POLL_MS: z.coerce.number().positive().default(1500),
AI_ANALYSIS_MAX_UPLOAD_POLL_MS: z.coerce.number().positive().default(8000),
// ── AI Analysis Batch ───────────────────────────────────────────────
AI_ANALYSIS_MAX_BATCH_SIZE: z.coerce.number().int().positive().default(200),