Conversation
WalkthroughMailConsumerAsyncProcessor에 MailLogBatchService 의존성이 추가되었고, QuizException 처리 시 실패 로그를 저장하도록 로직이 확장되었습니다. 예외 발생 시 mailLogBatchService.saveFailLog(...)를 호출한 뒤 기존과 같이 Redis 메시지를 ack 및 삭제하고 null을 반환합니다. 생성자 시그니처가 해당 서비스 추가로 변경되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant P as MailConsumerAsyncProcessor
participant T as TodayQuizService
participant M as MailLogBatchService
participant R as RedisStreamsClient
rect rgb(245,248,255)
note over P: 구독 레코드 처리 시작
P->>T: 오늘의 퀴즈 조회
T-->>P: QuizException 발생
end
rect rgb(255,245,245)
note over P,M: 변경된 예외 처리 경로
P->>M: saveFailLog(subscription, null, now, "No quizzes available")
P->>R: ackAndDel(recordId)
P-->>P: return null
end
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related PRs
Suggested reviewers
Poem
✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
cs25-batch/src/main/java/com/example/cs25batch/batch/component/processor/MailConsumerAsyncProcessor.java (2)
11-11: 시간 소스 하드코딩 제거(테스트 용이성/일관된 타임존): Clock 주입 권장LocalDateTime.now() 대신 Clock을 주입받아 사용하면 테스트 및 타임존 일관성이 좋아집니다.
@@ -import java.time.LocalDateTime; +import java.time.LocalDateTime; +import java.time.Clock; @@ - private final MailLogBatchService mailLogBatchService; + private final MailLogBatchService mailLogBatchService; + private final Clock clock; @@ - mailLogBatchService.saveFailLog(subscription, null, LocalDateTime.now(), "No quizzes available"); + mailLogBatchService.saveFailLog(subscription, null, LocalDateTime.now(clock), "No quizzes available");Clock 빈이 없다면 구성에
@Bean Clock clock() { return Clock.systemDefaultZone(); }추가를 고려해 주세요.Also applies to: 26-26, 55-55
55-55: 원인 메시지 하드코딩 최소화"No quizzes available" 문자열을 상수/enum(예: MailFailCause.NO_QUIZZES_AVAILABLE)로 통일하거나 QuizException의 에러 코드로부터 매핑하면 오타/다국어/집계 쿼리 시 유리합니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
cs25-batch/src/main/java/com/example/cs25batch/batch/component/processor/MailConsumerAsyncProcessor.java(3 hunks)
🔇 Additional comments (1)
cs25-batch/src/main/java/com/example/cs25batch/batch/component/processor/MailConsumerAsyncProcessor.java (1)
5-5: MailLogBatchService 트랜잭션 전파 및 빈 등록 확인됨
saveFailLog 메서드에@Transactional(propagation = Propagation.REQUIRES_NEW)가 적용되어 별도 트랜잭션이 보장되며,@RequiredArgsConstructor기반 생성자 주입을 통해MailConsumerAsyncProcessor에서 정상 인젝션됩니다.
| //문제 출제 실패로 인한 예외 발생 시, 기존 Queue에 있는 데이터 삭제 | ||
| mailLogBatchService.saveFailLog(subscription, null, LocalDateTime.now(), "No quizzes available"); | ||
| redisClient.ackAndDel(recordId); | ||
| return null; | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
ACK 보장: 로그 저장 실패 시에도 메시지를 반드시 ack/del 하도록 finally로 이동
현재는 saveFailLog에서 예외가 나면 ack가 호출되지 않아 동일 메시지가 재처리될 수 있습니다. ack를 finally로 옮기고, recordId null 가드 및 로깅을 추가해 주세요.
다음 패치를 제안합니다:
- } catch(QuizException e){
- //문제 출제 실패로 인한 예외 발생 시, 기존 Queue에 있는 데이터 삭제
- mailLogBatchService.saveFailLog(subscription, null, LocalDateTime.now(), "No quizzes available");
- redisClient.ackAndDel(recordId);
- return null;
- }
+ } catch (QuizException e) {
+ // 문제 출제 실패 시: 실패 로그 저장 후, 메시지는 항상 정리
+ try {
+ mailLogBatchService.saveFailLog(subscription, null, LocalDateTime.now(), "No quizzes available");
+ } catch (Exception logEx) {
+ log.error("Fail log persist failed. subscriptionId={}, recordId={}", subscriptionId, recordId, logEx);
+ } finally {
+ if (recordId != null) {
+ redisClient.ackAndDel(recordId);
+ } else {
+ log.warn("Missing recordId. subscriptionId={}", subscriptionId);
+ }
+ }
+ return null;
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| //문제 출제 실패로 인한 예외 발생 시, 기존 Queue에 있는 데이터 삭제 | |
| mailLogBatchService.saveFailLog(subscription, null, LocalDateTime.now(), "No quizzes available"); | |
| redisClient.ackAndDel(recordId); | |
| return null; | |
| } | |
| } catch (QuizException e) { | |
| // 문제 출제 실패 시: 실패 로그 저장 후, 메시지는 항상 정리 | |
| try { | |
| mailLogBatchService.saveFailLog(subscription, null, LocalDateTime.now(), "No quizzes available"); | |
| } catch (Exception logEx) { | |
| log.error("Fail log persist failed. subscriptionId={}, recordId={}", subscriptionId, recordId, logEx); | |
| } finally { | |
| if (recordId != null) { | |
| redisClient.ackAndDel(recordId); | |
| } else { | |
| log.warn("Missing recordId. subscriptionId={}", subscriptionId); | |
| } | |
| } | |
| return null; | |
| } |
🤖 Prompt for AI Agents
In
cs25-batch/src/main/java/com/example/cs25batch/batch/component/processor/MailConsumerAsyncProcessor.java
around lines 54 to 58, the call to mailLogBatchService.saveFailLog can throw and
prevent redisClient.ackAndDel(recordId) from running, causing duplicate
reprocessing; move the ack/del into a finally block so it always runs, surround
saveFailLog with its own try/catch to log failures (including exception details)
but not rethrow, and in the finally check recordId for null before calling
redisClient.ackAndDel(recordId) and log a warning if recordId is null or ack/del
fails.
🔎 작업 내용
Summary by CodeRabbit