-
Notifications
You must be signed in to change notification settings - Fork 3
feat : 장애 대응 및 재처리 로직을 적용한 고가용성 알림 시스템 구축 #195
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- `runtimeOnly` 사용 시 실행할 때에만 classpath에 올라가므로, IDE/빌드 환경에 따라 드라이버를 찾지 못하는 경우가 발생함
- mongo db에 트랜잭션을 도입하기 위해서 replica set 설정을 수행하고, 실제로 적용되었는지 확인하기 위해 테스트 수행 - 정상적으로 동작하는 것 확인 - 실제 배포 환경에 있는 mongo db 백업 후 replica set 적용해야 함
- 기존 코드에서는 @transactional 메서드 안에서 DB 저장과 알림 발송이 순차적으로 일어난다. - 알림이 발송된 직후, 커밋 단계에서 데이터베이스 문제 등 예측하지 못한 이유로 트랜잭션이 롤백된다면? - 사용자는 알림을 받았지만, 정작 DB에는 해당 알림 데이터가 존재하지 않는 유령 데이터가 발생한다. - 스프링에서 제공하는 @TransactionalEventListener를 사용하여 트랜잭션 성공 이후 알림이 발송되는 것을 보장하고, 코드의 관심사를 분리했다.
- 메시지를 처리하는 과정에서 DB에 장애가 발생했을 시, 처리되지 않은 메시지가 누적되어 시스템이 과부하되는 것을 방지하기 위해 서킷 브레이커 패턴을 적용했다. - Resilience4j 라이브러리 사용 - 테스트 코드를 통해 실제로 서킷 브레이커가 동작하는지 확인함
- 서킷 브레이커에 대해 잘못 이해하고 있는 부분이 있어서 테스트 코드에 오류가 있었음 - 실제로 발생할만한 예외가 던져지도록 하고, 해당 예외가 fallback 메서드를 통해 NotificationException으로 던져지는 것을 확인하도록 함 - 새로 구현된 NotificationProcessLog document에 데이터가 있으면 서킷 브레이커 테스트 중 에러가 발생함. 추후 이 점 유의해야 함
- consumer에 메시지가 들어오면 로그를 db에 적재 (PENDING) - 이후 메시지 처리 성공 여부에 따라 상태를 업데이트함 (SUCCESS, FAILD) - 실패했던 메시지들은 별도의 스케쥴러에서 다시 재시도 처리함 - 만약 특정 횟수의 시도 이후에도 실패한다면 PERMANENTLY_FAILED로 상태 변경 - 해당 메시지들은 추후 개발자가 직접 처리할 수 있도록 함 (Grafana 등 연동)
WalkthroughMongoDB 레플리카셋 재시작/초기화 및 사용자 생성 스크립트가 추가되었고, Mongo 트랜잭션 빈·알림 파이프라인(퍼블리셔 messageId, JMS 소비자, 프로세스 로그, 재시도 스케줄러, 서킷브레이커, 이벤트 발행) 리팩터링과 관련 의존성·프로퍼티·테스트가 추가/수정되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor Producer as Producer
participant Pub as NotificationEventPublisher
participant JMS as JMS Broker
participant Cons as NotificationQueueConsumer
participant PLog as ProcessLogService
participant Svc as NotificationService
participant Repo as NotificationMongoRepository
participant EVT as ApplicationEventPublisher
participant EL as NotificationEventListener
participant WS as SimpMessagingTemplate
Producer->>Pub: sendMessage(event)
Pub->>JMS: convertAndSend(payload, header: CUSTOM_HEADER_MESSAGE_ID=UUID)
JMS-->>Cons: onMessage(payload, headers)
Cons->>PLog: startProcessing(messageId, payload)
alt allowed to process
Cons->>Svc: createNewNotification(event)
rect rgba(230,245,255,0.6)
note right of Svc: `@CircuitBreaker` + `@Transactional`
Svc->>Repo: save(NotificationDocument)
Repo-->>Svc: saved
end
Svc->>EVT: publish(NotificationSavedEvent)
EVT-->>EL: AFTER_COMMIT
EL->>WS: send to user (NotificationResponse)
Cons->>PLog: finishProcessing(messageId)
else skipped
Cons-->>Cons: skip processing (dedupe)
end
note over Cons: 오류시 PLog.failProcessing(messageId, reason)
sequenceDiagram
autonumber
participant Sch as NotificationRetryScheduler
participant PLog as ProcessLogService
participant JMS as JMS Broker
loop every 5 minutes
Sch->>PLog: findRetryableJobs()
PLog-->>Sch: FAILED logs with retryCount < maxRetries
Sch->>JMS: convertAndSend(payload, header: CUSTOM_HEADER_MESSAGE_ID=existingId)
end
note over Sch: 재시도 시 기존 messageId 재사용(멱등성)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60–90 minutes 주의 깊게 볼 지점:
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
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. Comment |
- AfterEach 추가해서 어떤 시점에 테스트를 실행해도 전부 통과할 수 있도록 함 - 그러나 DB를 매번 초기화하므로 개발, 배포 환경에 영향이 가지 않도록 disabled 해뒀음
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 7
🧹 Nitpick comments (4)
build.gradle (1)
124-126: Resilience4j 의존성 버전 업데이트 권장build.gradle (124-126)의 resilience4j-spring-boot3 및 resilience4j-circuitbreaker 버전을 최신 안정 버전인 2.3.0으로 업그레이드하세요.
scripts/mongo-create-user.sh (1)
4-5: scripts/mongo-create-user.sh: 하드코딩된 자격 증명 제거 권장
현재 이 스크립트는 로컬 개발 환경에서만 호출되며(.github/workflows에 포함되지 않음), 프로덕션/스테이징 환경에서도 사용될 가능성이 있다면MONGO_USER/MONGO_PASSWORD환경 변수로 주입하도록 변경하세요.restart-mongodb-replica.sh (1)
31-33:rm대상 경로는 반드시 따옴표로 감싸주세요.변수에 공백이나 글로빙 문자가 섞이면 의도치 않은 경로가 삭제될 수 있습니다. 안전을 위해 인자를 감싸는 것이 좋습니다.
-rm -rf ${DATA_FILE_PATH} +rm -rf "${DATA_FILE_PATH}"src/main/java/org/ezcode/codetest/infrastructure/notification/publisher/NotificationEventPublisher.java (1)
51-58: 로그에 커스텀 메시지 ID도 함께 남겨주세요.재처리·멱등성 추적 시 큐 헤더와 로그를 매칭해야 합니다. 성공 로그에
customMessageId를 포함하면 추후 사고 분석이 훨씬 수월합니다.- log.info("알림 메시지 전송 성공 ({}) : {}", destination, jsonMessage); + log.info("알림 메시지 전송 성공 (destination={}, messageId={}) : {}", destination, customMessageId, jsonMessage);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (23)
.gitignore(1 hunks)build.gradle(2 hunks)restart-mongodb-replica.sh(1 hunks)scripts/mongo-create-user.sh(1 hunks)scripts/rs-init.sh(1 hunks)src/main/java/org/ezcode/codetest/application/notification/exception/NotificationException.java(1 hunks)src/main/java/org/ezcode/codetest/application/notification/exception/NotificationExceptionCode.java(1 hunks)src/main/java/org/ezcode/codetest/infrastructure/mongo/config/MongoTransactionConfig.java(1 hunks)src/main/java/org/ezcode/codetest/infrastructure/notification/event/NotificationSavedEvent.java(1 hunks)src/main/java/org/ezcode/codetest/infrastructure/notification/model/NotificationProcessLog.java(1 hunks)src/main/java/org/ezcode/codetest/infrastructure/notification/model/NotificationQueueConstants.java(1 hunks)src/main/java/org/ezcode/codetest/infrastructure/notification/publisher/NotificationEventPublisher.java(2 hunks)src/main/java/org/ezcode/codetest/infrastructure/notification/repository/NotificationProcessLogRepository.java(1 hunks)src/main/java/org/ezcode/codetest/infrastructure/notification/service/NotificationEventListener.java(1 hunks)src/main/java/org/ezcode/codetest/infrastructure/notification/service/NotificationQueueConsumer.java(1 hunks)src/main/java/org/ezcode/codetest/infrastructure/notification/service/NotificationRetryScheduler.java(1 hunks)src/main/java/org/ezcode/codetest/infrastructure/notification/service/NotificationService.java(3 hunks)src/main/java/org/ezcode/codetest/infrastructure/notification/service/ProcessLogService.java(1 hunks)src/main/resources/application.properties(1 hunks)src/test/java/org/ezcode/codetest/infrastructure/notification/MongoTransactionTest.java(1 hunks)src/test/java/org/ezcode/codetest/infrastructure/notification/NotificationCircuitBreakTest.java(1 hunks)src/test/java/org/ezcode/codetest/infrastructure/notification/NotificationIntegrationTest.java(1 hunks)src/test/resources/application-test.properties(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (6)
src/main/java/org/ezcode/codetest/infrastructure/notification/service/NotificationRetryScheduler.java (3)
src/main/java/org/ezcode/codetest/infrastructure/notification/model/NotificationQueueConstants.java (1)
NotificationQueueConstants(3-13)src/main/java/org/ezcode/codetest/infrastructure/notification/publisher/NotificationEventPublisher.java (1)
Slf4j(20-63)src/main/java/org/ezcode/codetest/infrastructure/notification/service/NotificationQueueConsumer.java (1)
Slf4j(23-91)
src/main/java/org/ezcode/codetest/infrastructure/notification/service/NotificationQueueConsumer.java (3)
src/main/java/org/ezcode/codetest/infrastructure/notification/model/NotificationQueueConstants.java (1)
NotificationQueueConstants(3-13)src/main/java/org/ezcode/codetest/infrastructure/notification/service/ProcessLogService.java (1)
Service(16-85)src/main/java/org/ezcode/codetest/infrastructure/notification/publisher/NotificationEventPublisher.java (1)
Slf4j(20-63)
src/test/java/org/ezcode/codetest/infrastructure/notification/NotificationIntegrationTest.java (1)
src/main/java/org/ezcode/codetest/infrastructure/notification/model/NotificationQueueConstants.java (1)
NotificationQueueConstants(3-13)
src/main/java/org/ezcode/codetest/infrastructure/notification/service/ProcessLogService.java (2)
src/main/java/org/ezcode/codetest/infrastructure/notification/service/NotificationQueueConsumer.java (1)
Slf4j(23-91)src/main/java/org/ezcode/codetest/infrastructure/notification/service/NotificationRetryScheduler.java (1)
Slf4j(15-38)
src/main/java/org/ezcode/codetest/infrastructure/notification/service/NotificationService.java (3)
src/main/java/org/ezcode/codetest/application/notification/service/NotificationUseCase.java (1)
Service(11-30)src/main/java/org/ezcode/codetest/infrastructure/notification/publisher/NotificationEventPublisher.java (1)
Slf4j(20-63)src/main/java/org/ezcode/codetest/infrastructure/event/publisher/StompMessageService.java (1)
Slf4j(19-135)
src/test/java/org/ezcode/codetest/infrastructure/notification/NotificationCircuitBreakTest.java (2)
src/test/java/org/ezcode/codetest/infrastructure/notification/NotificationIntegrationTest.java (1)
Disabled(35-174)src/test/java/org/ezcode/codetest/infrastructure/notification/MongoTransactionTest.java (1)
SpringBootTest(13-31)
🪛 Shellcheck (0.11.0)
scripts/rs-init.sh
[error] 1-1: Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.
(SC2148)
scripts/mongo-create-user.sh
[error] 1-1: Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.
(SC2148)
restart-mongodb-replica.sh
[error] 1-1: Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.
(SC2148)
🔇 Additional comments (5)
.gitignore (1)
46-46: 변경 사항 확인 완료.MongoDB 레플리카 셋 관련 로컬 데이터 디렉토리를 무시 목록에 추가한 것은 적절합니다. 버전 관리에서 제외되어야 할 디렉토리가 올바르게 설정되었습니다.
src/test/resources/application-test.properties (1)
107-117: Circuit Breaker 테스트 설정 확인 완료.DB 호출에 대한 Circuit Breaker 설정이 테스트 환경에 적절하게 구성되었습니다:
- 슬라이딩 윈도우 크기(10)와 최소 호출 횟수(5)가 적절합니다
- 실패율 임계값(50%)과 대기 시간(10초)이 테스트에 적합합니다
- MongoDB 및 네트워크 관련 예외들이 포괄적으로 등록되었습니다
이 설정은 PR의 장애 대응 아키텍처 목표와 잘 부합합니다.
src/main/java/org/ezcode/codetest/infrastructure/notification/model/NotificationQueueConstants.java (1)
7-8: 상수 추가 확인 완료.멱등성 보장을 위한 커스텀 메시지 ID 헤더 상수가 깔끔하게 추가되었습니다. 기존 코드 패턴을 따르고 있으며 PR의 멱등성 보장 요구사항을 지원합니다.
src/main/java/org/ezcode/codetest/infrastructure/notification/event/NotificationSavedEvent.java (1)
5-11: 이벤트 레코드 정의 확인 완료.
NotificationSavedEvent가 Java record로 깔끔하게 정의되었습니다. 불변성이 보장되며 PR의 트랜잭션 분리 아키텍처(@TransactionalEventListener활용)를 지원하는 적절한 구조입니다.scripts/rs-init.sh (1)
26-27: 이 스크립트는 로컬 개발 전용으로, 프로파일링 레벨 2 유지해도 무방합니다.
src/main/java/org/ezcode/codetest/infrastructure/mongo/config/MongoTransactionConfig.java
Outdated
Show resolved
Hide resolved
.../java/org/ezcode/codetest/infrastructure/notification/service/NotificationQueueConsumer.java
Show resolved
Hide resolved
src/test/java/org/ezcode/codetest/infrastructure/notification/MongoTransactionTest.java
Show resolved
Hide resolved
- MongoDB 트랜잭션 매니저를 transactionManager라는 기본 이름으로 등록하면, JPA 등 다른 데이터소스용 기본 트랜잭션 매니저와 충돌하거나 덮어써서 애플리케이션 부팅 실패 혹은 잘못된 매니저 선택으로 이어질 수 있음
- null 예외 처리 추가해서 커스텀 message id 헤더가 존재하지 않는 메시지가 무한히 재시도 되는 상황을 방지함
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 7
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
restart-mongodb-replica.sh(1 hunks)scripts/mongo-create-user.sh(1 hunks)scripts/rs-init.sh(1 hunks)src/main/java/org/ezcode/codetest/infrastructure/mongo/config/MongoTransactionConfig.java(1 hunks)src/main/java/org/ezcode/codetest/infrastructure/notification/service/NotificationQueueConsumer.java(1 hunks)src/main/java/org/ezcode/codetest/infrastructure/notification/service/NotificationService.java(3 hunks)src/main/java/org/ezcode/codetest/infrastructure/notification/service/ProcessLogService.java(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- scripts/mongo-create-user.sh
- src/main/java/org/ezcode/codetest/infrastructure/mongo/config/MongoTransactionConfig.java
🧰 Additional context used
🧬 Code graph analysis (3)
src/main/java/org/ezcode/codetest/infrastructure/notification/service/ProcessLogService.java (2)
src/main/java/org/ezcode/codetest/infrastructure/notification/service/NotificationQueueConsumer.java (1)
Slf4j(23-95)src/main/java/org/ezcode/codetest/infrastructure/notification/service/NotificationRetryScheduler.java (1)
Slf4j(15-38)
src/main/java/org/ezcode/codetest/infrastructure/notification/service/NotificationQueueConsumer.java (4)
src/main/java/org/ezcode/codetest/infrastructure/notification/model/NotificationQueueConstants.java (1)
NotificationQueueConstants(3-13)src/main/java/org/ezcode/codetest/infrastructure/notification/service/ProcessLogService.java (1)
Service(16-85)src/main/java/org/ezcode/codetest/infrastructure/notification/publisher/NotificationEventPublisher.java (1)
Slf4j(20-63)src/main/java/org/ezcode/codetest/infrastructure/notification/service/NotificationRetryScheduler.java (1)
Slf4j(15-38)
src/main/java/org/ezcode/codetest/infrastructure/notification/service/NotificationService.java (2)
src/main/java/org/ezcode/codetest/infrastructure/notification/service/ProcessLogService.java (1)
Service(16-85)src/main/java/org/ezcode/codetest/application/notification/service/NotificationExecutor.java (1)
Slf4j(15-38)
🔇 Additional comments (4)
src/main/java/org/ezcode/codetest/infrastructure/notification/service/NotificationService.java (2)
86-96: Resilience4j 서킷 오픈 대기시간 설정 확인프로덕션 환경에
resilience4j.circuitbreaker.instances.db-circuit.wait-duration-in-open-state설정이 없어 기본값(60초)이 적용됩니다. 이 기간 동안 JMS 예외가 계속 재시도되어 불필요한 반복이 발생할 수 있으므로application.yml혹은application.properties에 적절한 대기시간을 설정하거나 fallback 동작을 조정하세요.
63-66: 이벤트 리스너는 이미 @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)로 설정되어 있으므로 변경이 필요 없습니다.Likely an incorrect or invalid review comment.
src/main/java/org/ezcode/codetest/infrastructure/notification/service/ProcessLogService.java (1)
37-56: messageId 필드는 @id로 _id에 매핑되어 기본 고유 인덱스가 이미 적용됩니다
별도 @indexed(unique=true) 설정 없이도 중복 삽입 시 DuplicateKeyException이 발생하므로 추가 조치 불필요합니다.scripts/rs-init.sh (1)
3-27: 레플리카셋 포트 매핑 수동 확인 필요
scripts/rs-init.sh가--port 10021로 접속을 시도하지만, 리포지토리 내 Docker Compose나 mongod 설정에서 컨테이너 내부 포트(10021/10022/10023)가 매핑됐는지 확인할 수 없습니다. 관련 파일 경로 및 포트 설정을 수동으로 검증하거나, 스크립트에서 기본 포트(27017) 사용으로 조정할지 검토해주세요.
.../java/org/ezcode/codetest/infrastructure/notification/service/NotificationQueueConsumer.java
Show resolved
Hide resolved
.../java/org/ezcode/codetest/infrastructure/notification/service/NotificationQueueConsumer.java
Show resolved
Hide resolved
.../java/org/ezcode/codetest/infrastructure/notification/service/NotificationQueueConsumer.java
Show resolved
Hide resolved
.../java/org/ezcode/codetest/infrastructure/notification/service/NotificationQueueConsumer.java
Show resolved
Hide resolved
src/main/java/org/ezcode/codetest/infrastructure/notification/service/ProcessLogService.java
Outdated
Show resolved
Hide resolved
src/main/java/org/ezcode/codetest/infrastructure/notification/service/ProcessLogService.java
Outdated
Show resolved
Hide resolved
- finishProcessing, finishProcessing 메서드의 findById()가 비어있다면 `ifPresent` 블록은 아무 일도 하지 않고 넘어감 - 개발자는 에러가 발생했다는 사실조차 모르고 넘어감 -> 조용한 실패(Silent Failure) - finishProcessing에서 로그가 없다는 것은 비즈니스적인 문제(사용자 잘못 등)가 아니라, 시스템 내부의 심각한 상태 불일치를 의미 - 따라서 NotificationException보다는 IllegalStateException이나 SystemException 같은 런타임 예외를 사용하는 것이 의미상 더 적합함
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (3)
src/main/java/org/ezcode/codetest/infrastructure/notification/service/ProcessLogService.java (3)
26-57: 멱등성 및 재시도 로직이 잘 구현되었습니다.중복 메시지 검사와 실패한 작업의 재시도를 적절히 처리하고 있으며, 트랜잭션으로 데이터 정합성을 보장합니다.
선택사항: 방어적 코딩 강화를 위해
messageId와payload에 대한 null/empty 검증을 고려할 수 있습니다.@Transactional(transactionManager = "mongoTransactionManager") public boolean startProcessing(String messageId, String payload) { - + if (messageId == null || messageId.isBlank()) { + throw new IllegalArgumentException("messageId는 null이거나 비어있을 수 없습니다."); + } + if (payload == null || payload.isBlank()) { + throw new IllegalArgumentException("payload는 null이거나 비어있을 수 없습니다."); + } + Optional<NotificationProcessLog> existingLogOpt = processLogRepository.findById(messageId);
59-72: 과거 리뷰 피드백이 반영되어 개선되었습니다.로그 미존재 시 명시적으로 예외를 발생시켜 조용한 실패 문제가 해결되었습니다.
참고: Line 65에서
ProcessLogService.log대신log를 직접 사용하면 더 간결합니다.NotificationProcessLog log = processLogRepository.findById(messageId) .orElseThrow(() -> { - ProcessLogService.log.error("처리 완료할 로그를 찾을 수 없습니다. messageId={}", messageId); + log.error("처리 완료할 로그를 찾을 수 없습니다. messageId={}", messageId); return new IllegalStateException("Process log not found: " + messageId); });
74-85: 과거 리뷰 피드백이 반영되어 개선되었습니다.로그 미존재 시 명시적으로 예외를 발생시켜 실패 상태를 놓치는 문제가 해결되었습니다.
참고: Line 80에서도
ProcessLogService.log대신log를 직접 사용하면 더 간결합니다.NotificationProcessLog log = processLogRepository.findById(messageId) .orElseThrow(() -> { - ProcessLogService.log.error("실패 기록할 로그를 찾을 수 없습니다. messageId={}", messageId); + log.error("실패 기록할 로그를 찾을 수 없습니다. messageId={}", messageId); return new IllegalStateException("Process log not found: " + messageId); });
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/main/java/org/ezcode/codetest/infrastructure/notification/service/ProcessLogService.java(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/main/java/org/ezcode/codetest/infrastructure/notification/service/ProcessLogService.java (1)
src/main/java/org/ezcode/codetest/infrastructure/notification/service/NotificationService.java (1)
Service(25-97)
🔇 Additional comments (2)
src/main/java/org/ezcode/codetest/infrastructure/notification/service/ProcessLogService.java (2)
1-24: 클래스 구조 및 의존성 설정이 적절합니다.서비스 선언, 의존성 주입, 설정값 관리가 Spring 모범 사례를 따르고 있으며 깔끔하게 구현되어 있습니다.
87-92: 재시도 대상 조회 로직이 적절합니다.읽기 전용 트랜잭션을 사용하여 성능을 고려했으며, 재시도 조건이 명확하게 구현되어 있습니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
src/main/resources/application.properties (1)
162-173: Circuit Breaker 임계값 재검토 필요 - 데이터베이스 장애 복구 시간 고려현재 설정에서
minimum-number-of-calls=5+failure-rate-threshold=50의 조합은 단 5개의 호출 중 3개 실패 시 즉시 회로를 개방하게 됩니다. 데이터베이스의 일시적 네트워크 지연이나 연결 풀 고갈 상황에서는 정상 요청까지 차단될 수 있습니다.추천 사항:
minimum-number-of-calls증대: 최소 10~20 으로 상향하여 더 많은 샘플링 후 판단wait-duration-in-open-state재검토: MongoDB 레플리카셋 복구 시간을 고려하여 30s~60s 로 연장 검토 필요 (현재 10s는 DB 재시작 완료 시간에 비해 짧을 수 있음)failure-rate-threshold조정: 50%에서 70% 이상으로 상향하여 진정한 장애만 감지하도록 검토PR의
@Scheduled재시도 로직, ActiveMQ DLQ, 그리고@TransactionalEventListener의 트랜잭션 기반 처리와 함께 고려하여, 회로 차단 전략과 재시도 전략의 상호작용을 검증해주시기 바랍니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/main/resources/application.properties(1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build
개요
배경
변경 사항
이번 PR에서는 다음과 같은 안정성 패턴들을 적용하여 시스템을 개선함.
1. 상태 기반 재처리 (State-Based Retry)
PENDING,SUCCESS,FAILED)를 MongoDBprocess_log컬렉션에 기록함.@Scheduled스케줄러를 구현하여,FAILED상태의 작업을 주기적으로 자동 재시도하도록 구성.2. 서킷 브레이커 (Circuit Breaker)
UseCase계층에 서킷 브레이커를 적용.3. 멱등성 (Idempotency) 보장
custom_message_id라는 고유 헤더를 사용.process_log의 기본 키로 사용하여, 이미 성공적으로 처리된 메시지의 중복 실행을 방지함.4. 트랜잭션과 이벤트의 분리
@TransactionalEventListener를 사용하여, DB 트랜잭션이 성공적으로commit된 후에만 WebSocket 알림 발송 이벤트가 처리되도록 보장.5. 최후의 안전망 (DLQ)
6. 통합 테스트
스크린샷
해결해야 할 문제
Summary by CodeRabbit
새로운 기능
리팩터
작업
테스트
✏️ Tip: You can customize this high-level summary in your review settings.