Skip to content

AI 연동 실패 경로 4곳이 전제하는 재스캔이 존재하지 않는다 — 실행 주체 결정 필요 #99

Description

@minyongP

AI 연동의 실패 경로 네 곳이 "재스캔이 복구한다"를 안전망으로 전제하는데, 재스캔이 코드에 없다. @Scheduled@EnableScheduling도 레포 전체에 없다.

이 이슈는 결정 대기다. 사실을 잊지 않도록 남기는 것이고, 실행 주체가 정해지기 전에는 구현 티켓을 만들지 않는다. 담당자는 추적용이며 구현 소유를 뜻하지 않는다.

재스캔을 전제하는 네 곳

위치 전제
AiIntegrationConfig.java:68 호출 큐 포화 시 요청을 버린다 — "PENDING이 남아 재스캔이 다시 집는다"
AiProcessClient.java:90 모든 실패를 삼킨다(401 포함) — "재스캔이 흡수한다"
ContextAiRequestedListener.java:50 "PENDING은 이미 커밋되어 있어 재스캔이 같은 Context를 다시 집는다"
ContextAiStateRepository.java:13 상태 행이 없으면 "재스캔도 후보로 잡지 못한다"

AiProcessClient.java:30·:57에도 같은 전제가 javadoc으로 적혀 있다.

없는 것

  • 재스캔 스케줄러 — @Scheduled / @EnableScheduling 0건
  • retry / circuit breaker — Resilience4j 미도입, build.gradle에 관련 의존성 없음
  • 있는 것은 타임아웃뿐이다: pinlog.ai.process.connect-timeout=1s, read-timeout=3s

증상

한 번 실패한 Context는 영구히 PENDING으로 남는다. 임베딩과 키워드가 절대 만들어지지 않고, 자연어 검색이 그 Context를 영원히 찾지 못한다. 상태만 보면 "처리 대기 중"이라 정상과 구별되지 않는다.

특히 PINLOG_AI_INTERNAL_SECRET이 비어 있으면 FastAPI가 전부 401을 주는데, AiProcessClient가 그것도 삼키고 WARN 로그만 남긴다. 즉 시크릿 주입이 빠진 채로 배포되면 아무 Context도 처리되지 않으면서 에러 응답은 하나도 나오지 않는다.

스키마가 이미 정해 둔 것

ai.context_ai_state(V100__ai_tables.sql)를 보면 몇 가지는 결정거리가 아니다.

  • CHECK (retry_count BETWEEN 0 AND 3)최대 재시도는 3회로 DB가 못 박아 뒀다
  • updated_at TIMESTAMPTZ NOT NULL DEFAULT now() — stale 판정의 시계로 쓸 값이 이미 있다
  • embedding_statuskeyword_status독립 전이한다. 한쪽만 PENDING인 행이 정상적으로 존재한다
  • 상태는 PENDING·PROCESSING·COMPLETED·FAILED·CANCELLED 다섯

실행 주체가 미확정이다 — 이 이슈가 결정 대기인 이유

문서 근거가 갈린다.

  • 백엔드 쪽: S15P11A705-102의 쓰기 책임 매트릭스가 백엔드에 PENDING·CANCELLED·retry_count·**Finalizer FAILED**를 배정한다. Finalizer가 백엔드 몫이면 재스캔도 백엔드로 읽힌다.
  • AI 쪽: S15P11A705-121(AI 레포 결함 티켓) 본문이 "인증 실패가 재스캔 주기마다 무한 재시도된다"고 쓴다. AI 레포에 docs/spec/failure-recovery.md라는 재시도·복구 계약 문서가 따로 있다.
  • 미결이라고 적힌 곳: S15P11A705-97 확인 요청 4가 "stale 판정 기준(상태·시간), recovery 실행 주체·주기, idempotency, 동시성 잠금, 최대 재시도·dead-letter/관측 방식을 확정한다"고 그대로 미뤄 두었다.

S15P11A705-102는 제외 범위에 "재스캔 Scheduler·FAILED Finalizer — 별건"이라고 적고 미뤘다. 그 별건이 아직 티켓으로 존재하지 않는다.

정해야 할 것

  1. 실행 주체 — 백엔드 스케줄러인가, AI 워커인가, 별도 Job인가. 이 답이 나머지를 좌우한다.
  2. 대상 상태 범위PENDING만인가, PROCESSING까지 회수하는가. PROCESSING-102 매트릭스상 AI 워커가 쓰는 상태라, 백엔드가 회수하면 남의 상태를 덮는다. 파트 간 합의가 필요하다.
  3. stale 기준 시간과 주기 — AI 후처리가 실제로 얼마나 걸리는지에 달려 있어 AI 파트 수치가 필요하다. 이 레포는 정책 수치를 @ConfigurationProperties로 빼는 선례가 있다(S15P11A705-120 Feed 가중치).
  4. 동시 실행 방지 — 여러 파드가 같은 행을 집지 않게 하는 방식.
  5. 관측 — 영구 PENDING이 쌓이는 것을 무엇이 알려주는가. 지금은 알려주는 것이 없다.

범위 밖

  • S15P11A705-121의 FastAPI 재시도·오류 분류 정정은 AI 레포 작업이며 이 이슈와 별개다. 다만 3번(기준 시간)이 그쪽 결론과 맞물린다.
  • 재시도 상한 자체는 스키마가 3회로 고정했으므로 논의 대상이 아니다.

Metadata

Metadata

Assignees

Labels

bug잘못된 동작 (fix)

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions