DOCS/journey/plans/260309_9시_네이버이메일분석_실패은닉_해결계획.md

5.8 KiB

tags
tags
infra
robeing
rb8001
skill-email
naverworks
plans

260309 9시 네이버 이메일 분석 실패 은닉 해결 계획

상위 원칙

관련 문서

목표

  • 네이버 이메일 분석 브리핑에서 메일 조회 실패실제 메일 0건을 분리한다.
  • rb8001 스케줄러가 실패를 성공처럼 기록하지 않도록 한다.
  • 재발 시 auth refresh 지연인지 NAVER WORKS 외부 API 지연인지 로그만으로 구분 가능하게 만든다.
  • expires_at 시간대 정합성 위험을 별도 판단 가능한 상태로 만든다.

문제 정의

  • 현재 rb8001/app/services/skills/naverworks_briefing.pyskill-email /messages 호출 실패를 return []로 삼킨다.
  • 그 결과 process_briefing()는 실패를 No emails in the last 24 hours로 오인하고 종료한다.
  • 이 구조는 상위 SSOT의 Truth First, 근본 원인 직접 수정 우선, 광범위 예외 폴백 금지 원칙과 충돌한다.

범위 고정

1차 수정 대상

  • rb8001/app/services/skills/naverworks_briefing.py
  • skill-email/main.py
  • skill-email/services/naverworks_provider.py

1차 검증 대상

  • rb8001 09:00 스케줄 실행 경로
  • skill-email /messages?provider=naverworks
  • auth-server /auth/naverworks/passport/refresh

2차 판단 대상

  • main_db.naverworks_token.expires_at 컬럼 타입 변경 필요 여부
  • 컨테이너 시간대 통일 여부 또는 만료 판단 로직의 시간대 명시 처리

실행 원칙

  • 실패를 메일 0건으로 대체하지 않는다.
  • except Exception으로 원인성 실패를 일괄 래핑하지 않는다.
  • timeout, 비200 응답, 응답 구조 이상, 토큰 갱신 실패를 구분해 기록한다.
  • 수정 후에는 로그, 헬스체크, 재현 테스트로 실제 실패 표현이 교정됐는지 확인한다.

단계별 계획

1. rb8001에서 실패 은닉을 제거한다

  • _fetch_recent_emails()[] 대신 원인성 예외를 올리도록 바꾼다.
  • 최소 분기 대상:
    • httpx.ReadTimeout
    • httpx.ConnectError
    • 비200 응답
    • 응답 JSON 구조 이상
  • process_briefing()실제 0건일 때만 No emails로 처리하고, 조회 실패는 스케줄러 실패로 남기게 바꾼다.

2. skill-email 단계별 원인 로그를 보강한다

  • /messages 경로에서 provider=naverworks 처리 시 다음 단계 로그를 남긴다.
    • DB 토큰 조회 시작/종료
    • 만료 판단 결과
    • refresh 호출 여부와 응답 코드
    • NAVER WORKS 외부 API 호출 시작/종료와 소요시간
  • 로그는 성공/실패 모두 같은 요청 흐름에서 이어서 대조 가능해야 한다.

3. expires_at 정합성 위험을 코드와 데이터 기준으로 판단한다

  • 현재 naverworks_token.expires_attimestamp without time zone인 상태를 전제로, 실제 만료 판단이 어떤 시간대 기준으로 이뤄지는지 명시한다.
  • skill-email의 만료 비교 시각과 DB 기록 시각이 같은 시간대 기준으로 비교되도록 정리한다.
  • 선택지는 둘 중 하나로 고정한다.
    • 컬럼 타입을 timestamptz로 승격
    • 비교 전후를 모두 명시 timezone 기준으로 변환
  • 이 단계는 폴백 추가가 아니라, 판단 기준을 하나로 고정하는 작업이어야 한다.

4. 재현 검증으로 닫는다

  • 정상 케이스:
    • 현재와 같은 /messages 요청이 정상 응답하고 브리핑이 실제 전송되는지 확인한다.
  • 실패 케이스:
    • 내부적으로 timeout 또는 비정상 응답을 재현했을 때 스케줄러가 실패로 남는지 확인한다.
  • 토큰 만료 케이스:
    • 만료 상태에서 refresh가 정상 수행되면 성공으로 이어지고, refresh 실패 시 원인성 실패로 남는지 확인한다.

검증 계획

1. 코드 검증

  • rb8001return [] 기반 실패 은닉 경로가 남아 있지 않은지 확인한다.
  • skill-email 로그가 단계별로 남는지 확인한다.

2. 로그 검증

  • 성공 케이스에서는 메일 0건조회 성공 0건이 구분된다.
  • 실패 케이스에서는 No emails 대신 timeout, refresh failed, works api failed 같은 원인 로그가 남는다.
  • 스케줄러 로그에는 실패 시 completed successfully가 남지 않는다.

3. 실행 검증

  • rb8001에서 수동 브리핑 실행 시 정상 메일 조회와 Slack 전송이 통과한다.
  • /messages 단건 호출로 성공/실패 응답 시간이 확인된다.
  • auth-server /refreshskill-email /messages를 같은 시각대에 대조해 병목 위치를 구분할 수 있다.

완료 조건

  • 네이버 이메일 조회 실패가 더 이상 No emails로 표시되지 않는다.
  • 9시 브리핑 실패 시 스케줄러와 로그가 모두 실패로 기록된다.
  • skill-email 로그만으로도 DB/refresh/외부 API 중 어느 단계에서 지연됐는지 구분 가능하다.
  • expires_at 만료 판단 기준이 시간대 혼선 없이 하나로 설명 가능하다.