✨ 리팩토링 대상
EmailRetryService / NotificationHistoryService / notification_history 테이블의 이메일 재전송 포기 기준
📢 리팩토링 이유
폴링 스케줄러(5분 주기) 기반의 maxRetry=N 방식은 재시도 유효 시간이 N × 5분으로 고정됩니다.
maxRetry=3이면 15분 만에 재시도를 포기하므로, SES 최소 장애 지속 시간(~3시간)보다 훨씬 짧아 사실상 재전송이 불가능한 상태가 됩니다.
폴링 주기 5분, maxRetry=3:
00:00 실패 → fail_count=1
00:05 실패 → fail_count=2
00:10 실패 → fail_count=3 → 포기 ← SES 장애는 아직 진행 중
재시도 포기 기준을 허용 윈도우(다음 복습 주기 이전) 기반의 deadline 컬럼으로 전환하여, SES 장애 지속 시간 전체를 재시도 유효 범위로 확보합니다.
리팩토링 기능 명세
📕 래퍼런스
✨ 리팩토링 대상
EmailRetryService/NotificationHistoryService/notification_history테이블의 이메일 재전송 포기 기준📢 리팩토링 이유
폴링 스케줄러(5분 주기) 기반의
maxRetry=N방식은 재시도 유효 시간이N × 5분으로 고정됩니다.maxRetry=3이면 15분 만에 재시도를 포기하므로, SES 최소 장애 지속 시간(~3시간)보다 훨씬 짧아 사실상 재전송이 불가능한 상태가 됩니다.재시도 포기 기준을 허용 윈도우(다음 복습 주기 이전) 기반의
deadline컬럼으로 전환하여, SES 장애 지속 시간 전체를 재시도 유효 범위로 확보합니다.리팩토링 기능 명세
notification_history테이블에deadline DATETIME NULL컬럼 추가 (Flyway 마이그레이션)NotificationHistory엔티티에deadline필드 추가NotificationHistoryRepository에updateStatusWithIncrementFailCount쿼리 추가 (deadline 설정 + fail_count 증가)NotificationHistoryService.updateStatus: FAILED 전환 시 다음 주기 조회 → deadline 계산 후 설정 (마지막 주기는 scheduledAt + 24h)ReviewCycleRepository에findAllRetryableCycles쿼리 추가 (status = FAILED AND deadline > NOW())EmailRetryService:findAllRetryableCycles기반으로 재시도 대상 조회로 전환EmailRetryScheduler:fixedDelay = 300_000ms(5분)고정 간격 재시도 등록📕 래퍼런스