Repository navigation
[feat] 인증 이메일 작업 영속화 및 재시작·다중 서버 재시도 복구 - #271
Merged
Merged
Conversation
- 토큰과 이메일 작업을 원자적으로 저장하고 DB 선점·시도 이력으로 복구 - 최대 4회 지수 백오프와 SMTP 오류 분류, 오래된 선점자의 완료 갱신 차단 - 인증 링크 암호화와 최종 payload 삭제, 중복 발송 한계 및 배포 절차 명시 - 재시작·동시 실행·실제 DB 기록 실패·쿨다운 회귀 테스트 추가 검증: 전체 324 tests, assemble, Checkstyle main/test, Spotless, UTF-8, Gitleaks 통과 Related #270
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the
|
10 of 12 tasks
- 기존 emailTaskExecutor에서 최대 3개 소비 작업만 실행하고 실행 후 DB 선점 - 메일 비활성화 시 작업 생성·처리·키 검증을 함께 제외해 로컬 Noop 흐름 유지 - 무효 작업 정리 뒤에도 20건 배치 한도 안에서 다음 후보 조회 - 복호화 실패를 SMTP 오류와 분리하고 복구 판단을 위한 암호문 보존 - 실행기 포화·작업 실패·공용 스케줄러 격리·설정·DB 회귀 테스트 13개 추가 검증: 전체 337 tests, assemble, Checkstyle main/test, Spotless, UTF-8, Gitleaks 통과 Related #270
- 주기마다 소비 작업 하나를 요청하고 실제 작업 발견 시에만 최대 3개로 확장 - 기존 실행기·동시 실행 제한·DB 선점·20건 배치 한도 유지 - 미사용 Trace 발송 fixture와 RetryConfig, 중복 비활성화 설정 검증 제거 - 유휴 조회·작업 발견 알림·슬롯 반환 검증을 현재 실행 흐름에 맞게 조정 검증: 전체 338 tests, assemble, Checkstyle main/test, Spotless, UTF-8, Gitleaks 통과 Related #270
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
✨ Feature PR
🔗 이슈 링크 (필수)
🧩 이 PR의 변경사항 (필수)
전체 중 위치 (Stacked PR 시)
develop브랜치가 없어 최근 기능 PR과 동일하게main을 기준으로 합니다.이 PR에서 변경한 것
기존 AFTER_COMMIT + @Async/@retryable은 프로세스 종료 시 작업과 횟수를 잃었습니다. 이제 BEFORE_COMMIT에서 인증 토큰과 암호화된 이메일 작업을 같은 트랜잭션에 저장합니다. 저장 실패 시 토큰도 롤백합니다.
Flyway V15:
email_jobs와email_job_attempts. 상태 5종, 시도 횟수, 마지막 시도/다음 재시도/lease 시각과 시도별 결과를 저장합니다.시작 시와 주기 실행에서 PENDING·기한 도래 RETRY_WAIT·오래된 SENDING을 조회합니다.
FOR UPDATE SKIP LOCKED로 선점/횟수 증가/이력 생성을 먼저 커밋하고 SMTP는 트랜잭션 밖에서 호출합니다.최초 시도 포함 최대 4회, 5→10→20초 백오프. 네트워크/SMTP 4xx는 재시도, 5xx·인증·주소/메시지 오류는 즉시 실패합니다. 코드 없는 MailSendException은 한도 내 재시도합니다.
시도 번호를 완료 UPDATE 조건으로 사용해 오래된 워커가 새 선점 결과를 덮어쓰지 못하게 합니다. 최종 실패와 불명 발송 이력은 DB에 남습니다.
자동 재시도는 토큰을 새로 만들지 않습니다. 기존 3분 수동 재전송 제한을 유지하고, 만료/사용/재전송으로 무효화된 토큰은 선점 시 발송 대상에서 제외합니다.
인증 링크는 AES-GCM으로 암호화하고 종료된 작업에서는 삭제합니다. 복호화 실패만
FAILED/PAYLOAD_DECRYPT_FAILED로 구분하여 암호문을 보존하며 자동 재발송하지 않습니다. 작업 ID는 DB/로그에 남기며, 복구 시도의 새 Trace는 저장된 생산 Trace에 Span Link로 연결합니다.공용 스케줄러는 기존
emailTaskExecutor에 소비 작업을 전달합니다. 주기 실행은 소비 작업 하나를 요청하며 실제 발송할 작업을 발견했을 때만 최대 3개까지 늘립니다. 실행기에서 실제 시작된 뒤 DB 작업을 선점하므로 유휴 상태의 주기별 빈 조회 3회를 줄입니다. 무효 작업 정리도 20건 배치 한도에 포함하되 다음 후보 조회를 계속합니다.APP_MAIL_ENABLED=false에서는 작업 생성·처리·키 검증을 모두 끄고 기존 Noop 개발 흐름을 유지합니다. 기존 대기 작업을 성공 처리하거나 삭제하지 않습니다.APP_EMAIL_JOBS_POLLING_ENABLED=false만 설정하면 작업 저장은 유지합니다.미사용 Trace 발송 fixture/RetryConfig와 중복된 비활성화 빈 검증을 제거했습니다. 실제 DB 보존 검증은 유지하고, 유휴 조회·첫 작업 발견 알림·동시 실행 상한을 검증합니다. 새 의존성이나 추가 DB 스키마 변경은 없습니다.
✅ 이 PR이 커버하는 AC (필수)
Covers (이 PR에서 완료)
Not covered (후속 작업)
🧪 테스트 결과 (필수)
로컬
./gradlew spotlessApply test assemble checkstyleMain checkstyleTest spotlessCheck --no-daemon python3 scripts/verify-utf8.py bash scripts/secret-scan.shCI
ef294334의 GitHub Actions #41295476127: Backend Build & Test 및 Observability IaC Validation 성공.BeachConditionSchedulerTracingIntegrationTest.skips_recordBoundedReasonsAndContinue가 기대한 span 미관측으로 1회 실패했습니다. 해당 클래스의 로컬 분리 실행과 동일 커밋의 실패 작업 재실행은 통과했습니다. 원인은 확정하지 않았으며 테스트 대기/폴링 추가나 해당 코드 변경은 하지 않았습니다.Smoke 테스트
🧭 영향 범위 체크 (필수)
APP_EMAIL_JOBS_PAYLOAD_KEY, polling/lease 설정, SMTP timeoutopenssl rand -base64 32로 생성해 Secret으로 관리하며, 예시 파일에는 실키를 넣지 않았습니다.💬 리뷰 포인트 (필수)
EmailJobStore: 선점 트랜잭션과 완료 조건/이력 원자성.EmailEventListener/EmailJobService: 토큰 트랜잭션과 작업 저장의 원자성.EmailJobScheduler: 기존 실행기 재사용·3개 제한·제출 거절/실패 후 슬롯 반환.EmailJobWorker/SmtpFailureClassifier: DB 횟수와 오류 분류, SMTP 결과와 DB 기록 오류 분리.SUCCEEDED는 SMTP 수락이지 받은편지함 도착이 아닙니다.FAILED/ATTEMPTS_EXHAUSTED_UNKNOWN을 보존하며 추가 발송하지 않습니다. 선점 이후 토큰이 무효화되면 이미 시작한 SMTP 전송을 취소할 수 없습니다.📌 공통 체크리스트
feature/270-durable-email-jobs브랜치 및feat: 내용커밋 규칙