Skip to content

feat: 데드레터 큐 소비 추가 — 유실 잡을 즉시 실패로 기록

변재혁 requested to merge feature/DOP-AI_사전지식_DLQ_컨슈머 into develop

ai-file.req.dead 는 지금까지 소비 주체가 없어 7일 뒤 소멸했다. 잡 행도 안 남으므로 사용자 화면에는 영영 "처리 중"으로 보이고, ai-home 의 dispatch-lost sweep 이 임계값(기본 5400초)을 기다린 뒤에야 회수했다.

데드레터를 소비해 마킹만 하면 탐지가 즉시 이뤄진다. 재발행은 하지 않으므로 디스패치 경로는 ai-home retry tick 하나로 유지된다.

사유(x-death.reason)별로 처리를 나눈다. 둘을 같게 다루면 포이즌 메시지 방어가 사라진다.

  • expired : 큐 TTL 만료. 파드에 도달조차 못했으므로 재시도 대상.
  • delivery_limit : 배달 상한 소진. 처리하다 파드가 반복해서 죽었다는 뜻이라 재시도하면 같은 일이 반복된다 → 영구 실패.
  • 불명 : 원인 모른 채 재시도하면 무한 루프가 될 수 있다 → 영구 실패.

이 큐는 read/metadata 와 공유한다. 그쪽은 응답을 돌려주는 동기 RPC 라 호출자가 이미 타임아웃으로 실패 처리를 끝냈고 되살릴 잡 행도 없다 — op 별 카운트만 남기고 버린다.

mark_dead_lettered 는 UPDATE 후 0행이면 INSERT 한다. TTL 만료는 claim 전에 일어나 잡 행이 아예 없는 경우가 대부분이다. 가드 두 개를 둔다 — sweep 이 재발행한 사본이 먼저 성공했는데 원본이 뒤늦게 DLQ 로 떨어질 수 있어, 이미 INDEXED 이거나 유효한 락을 쥔 잡은 덮지 않는다.

마킹 실패는 삼킨다. QueueConsumer 는 예외 시 requeue=False 로 폐기하므로 올리면 기록이 영영 사라진다. 백스톱인 dispatch-lost sweep 이 그대로 살아 있다.

QueueConsumer 에 pass_message 를 추가했다(기본 False, 기존 핸들러 시그니처 불변). 데드레터는 x-death 헤더를 봐야 해 본문만으로는 부족하다.

Co-Authored-By: Claude Opus 5 (1M context) noreply@anthropic.com

Merge request reports