#167 feat: 결제 실패 시 예약 취소 outbox 패턴 구현 - #168
Conversation
Summary of ChangesHello @git-mesome, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! 이 PR은 결제 실패 시 예약 취소 처리를 위한 강력한 Outbox 패턴을 도입하여 시스템의 견고성과 외부 시스템과의 이벤트 일관성을 크게 향상시킵니다. 또한, 기존 티켓 발급 Outbox 로직을 새로운 공통 추상화에 맞춰 리팩토링함으로써 Outbox 패턴 구현의 재사용성과 확장성을 확보했습니다. 전반적으로 비동기 처리의 안정성을 높이고 코드 구조를 개선하는 데 중점을 두었습니다. Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
결제 실패 시 예약 취소를 위한 아웃박스 패턴을 성공적으로 구현한 좋은 PR입니다. 공통 아웃박스 로직을 AbstractOutboxRetryUseCase와 OutboxRepository로 추상화하여 코드 재사용성과 유지보수성을 높인 점이 인상적입니다. 관련 테스트 코드 추가와 패키지 구조 리팩토링도 잘 이루어졌습니다.
코드 품질을 더욱 향상시키기 위해 몇 가지 제안 사항을 남깁니다.
- 변경된 아키텍처를 반영하도록 관련 문서를 업데이트하는 것을 권장합니다.
PaymentTransactionService에 존재하는 일부 중복 코드를 리팩토링하면 좋을 것 같습니다.- 데이터베이스 스키마의 주석에 있는 사소한 불일치를 수정하면 혼동을 줄일 수 있습니다.
전반적으로 결제 서비스의 안정성을 높이는 훌륭한 기여라고 생각합니다.
There was a problem hiding this comment.
Pull request overview
This PR implements a reservation cancellation outbox pattern to ensure that when payment fails, the associated reservation is automatically canceled in a reliable, server-driven manner. The implementation includes refactoring the existing ticket issue outbox to use shared abstractions, adding a new PaymentFailedEvent, and creating the complete infrastructure for reservation cancellation via outbox pattern with retry logic.
Changes:
- Added
PaymentFailedEventdomain event and event publishing inPayment.fail()method - Created abstract outbox infrastructure (
AbstractOutboxRetryUseCase,OutboxRepository,OutboxTarget) to reduce duplication - Implemented reservation cancel outbox pattern with
ReservationCancelOutboxService,ReservationCancelRetryUseCase,ReservationCancelAdaptor, and supporting repository/entity classes - Refactored ticket issue outbox to use new abstractions (moved from
application/ticketissuetoapplication/payment/outbox/ticketissue) - Added comprehensive tests for the new reservation cancel functionality
- Added database schema for
reservation_cancel_outboxtable
Reviewed changes
Copilot reviewed 52 out of 53 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| payment/src/main/java/wisoft/nextframe/payment/domain/payment/Payment.java | Added PaymentFailedEvent publishing in fail() method |
| payment/src/main/java/wisoft/nextframe/payment/domain/payment/event/PaymentFailedEvent.java | New domain event for payment failure |
| payment/src/main/java/wisoft/nextframe/payment/application/payment/PaymentTransactionService.java | Added event publishing for failed payment scenarios |
| payment/src/main/java/wisoft/nextframe/payment/application/payment/handler/PaymentEventHandler.java | Added handler for PaymentFailedEvent to trigger reservation cancellation |
| payment/src/main/java/wisoft/nextframe/payment/application/payment/outbox/*.java | New abstract base classes for outbox pattern |
| payment/src/main/java/wisoft/nextframe/payment/application/payment/outbox/cancel/*.java | Complete implementation of reservation cancel outbox |
| payment/src/main/java/wisoft/nextframe/payment/application/payment/outbox/ticketissue/*.java | Refactored ticket issue outbox to use new abstractions |
| payment/src/main/java/wisoft/nextframe/payment/application/payment/port/output/ReservationCancelClient.java | New port interface for reservation cancellation |
| payment/src/main/java/wisoft/nextframe/payment/infra/payment/outbox/cancel/*.java | Infrastructure implementations for reservation cancel outbox |
| payment/src/main/java/wisoft/nextframe/payment/infra/payment/schedule/*.java | Schedulers for outbox retry processing |
| payment/src/test/resources/schema-test.sql | Added reservation_cancel_outbox table definition |
| payment/src/test/java/wisoft/nextframe/payment/**/*.java | Test updates for package restructuring and new functionality |
| gradlew, gradle/wrapper/* | Gradle wrapper downgrade (unrelated to feature) |
| payment/.claude/* | Claude AI configuration files (unrelated to feature) |
Comments suppressed due to low confidence (1)
payment/src/test/java/wisoft/nextframe/payment/application/payment/PaymentEventHandlerTest.java:42
- The PaymentEventHandlerTest only tests the PaymentApprovedEvent handler, but doesn't include tests for the new PaymentFailedEvent handler (onPaymentFailed method). Add a test case to verify that when a PaymentFailedEvent is received, the ReservationCancelOutboxService.cancelOrEnqueue method is called with the correct parameters.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- 예약 취소(ReservationCancel) outbox 기능 추가 - ticketissue outbox를 application/payment/outbox/ 하위로 이동 - 공통 outbox 추상화 (AbstractOutboxRetryUseCase, OutboxRepository) - PaymentFailedEvent 도메인 이벤트 추가 - ReservationCancelClient 포트 추가 #167 test: 예약 취소 outbox 관련 테스트 추가 - ReservationCancelOutboxRepositoryImplTest 추가 - ReservationCancelSchedulerTest 추가 - 테스트 패키지 구조 main과 동일하게 정리
…t NOT NULL 위반 수정 - PaymentTransactionService의 실패 처리 로직을 handlePaymentFailure()로 추출하고, 공통 저장/이벤트 발행 로직을 saveAndPublishEvents()로 분리 - TicketIssue/ReservationCancel outbox의 failAndBackoff()에서 FAILED 상태 전환 시 nextRetryAt를 null로 설정하던 NOT NULL 제약 조건 위반 수정 - CLAUDE.md를 현재 outbox 추상화 구조에 맞게 갱신
b009fd0 to
a73570f
Compare
🛠️ 설명 (Description)
결제 실패 시 예약 서비스에 예약 취소 요청을 신뢰성 있게 전달하기 위해 Outbox 패턴을 구현했습니다.
이를 위해
PaymentFailedEvent를 도입하고, 결제 실패 시 해당 이벤트를 발행하여PaymentEventHandler에서 예약 취소 Outbox를 트리거하도록 했습니다.기존 티켓 발급 Outbox 패턴과 재사용성을 높이기 위해 Outbox 패턴의 공통 추상화를 도입하고, 기존 티켓 발급 Outbox 구현체도 이 추상화를 따르도록 리팩토링했습니다.
✅ 테스트 계획 (Test Plan)
PaymentTransactionService에서 결제 실패 (금액 불일치, PG 응답 실패) 시PaymentFailedEvent가 발행되는지 확인하는 테스트.PaymentEventHandler가PaymentFailedEvent를 수신하고ReservationCancelOutboxService.cancelOrEnqueue를 올바르게 호출하는지 확인하는 테스트.ReservationCancelOutboxService가 Outbox 엔트리를PENDING으로 저장하고, 외부 호출 성공 시SUCCESS로, 실패 시PENDING상태를 유지하며lastError를 업데이트하는지 확인하는 테스트.ReservationCancelRetryUseCase가PENDING상태의 Outbox 엔트리를 조회하여 재시도하고, 성공/실패 시 상태를 업데이트하는 테스트.AbstractOutboxRetryUseCase및OutboxRepository공통 인터페이스를 사용한 티켓 발급 Outbox의 리팩토링 후에도 기존 로직이 정상 동작하는지 확인하는 테스트.ReservationCancelClient(예약 서비스 모의 클라이언트)를 통해 실제 예약 취소 API 호출 흐름을 검증하는 테스트.📝 변경 사항 요약 (Summary)
PaymentTransactionService의applyConfirmResult메서드에서 결제 실패 시PaymentFailedEvent를 발행하도록 변경.payment/application/payment/handler/PaymentEventHandler.java에PaymentFailedEvent를 구독하는onPaymentFailed메서드 추가.onPaymentFailed메서드에서ReservationCancelOutboxService.cancelOrEnqueue를 호출하여 예약 취소 Outbox 흐름 시작.onPaymentApproved메서드에서ticketIssueOutboxService변수명 변경.payment/application/payment/outbox/패키지에AbstractOutboxRetryUseCase,OutboxRepository,OutboxTarget인터페이스를 추가하여 Outbox 패턴의 재시도 로직 및 저장소 로직을 일반화.payment/application/payment/outbox/cancel/패키지에 다음 클래스 추가:ReservationCancelOutboxService: 예약 취소 요청을 처리하고, 외부 시스템 호출 실패 시 Outbox에 기록하여 재시도하도록 관리.ReservationCancelOutboxRepository: 예약 취소 Outbox 데이터를 영속화하기 위한 인터페이스.ReservationCancelOutboxTarget: 예약 취소 Outbox의 대상 데이터를 정의하는 레코드.ReservationCancelRetryUseCase:AbstractOutboxRetryUseCase를 상속받아 예약 취소 재시도 로직을 구현.ReservationCancelExternalCallFailedException,ReservationCancelTemporarilyUnavailableException: 예약 취소 관련 예외 정의.payment/application/payment/port/output/ReservationCancelClient.java인터페이스 추가: 외부 예약 서비스와 연동하기 위한 포트 정의.wisoft.nextframe.payment.application.ticketissue패키지를wisoft.nextframe.payment.application/payment/outbox/ticketissue로 변경.TicketIssueOutboxService,TicketIssueRetryUseCase,TicketIssueOutboxRepository,TicketIssueOutboxTarget, 관련 예외 클래스)을 새로운 공통 Outbox 추상화를 사용하도록 변경 및 리팩토링.TicketIssueResult클래스 패키지 이동.TicketingClient인터페이스에서TicketIssueResult임포트 경로 업데이트..claude디렉토리와CLAUDE.md,settings.local.json파일 추가: Claude Code AI 툴을 위한 프로젝트 가이드 및 설정 파일.🔗 관련 이슈 (Related Issues)
☑️ 체크리스트 (Checklist)
👀 리뷰어를 위한 참고 사항 (Notes for Reviewers)
AbstractOutboxRetryUseCase를 도입하여 Outbox 패턴의 재시도 로직을 일반화하고, 기존 티켓 발급 Outbox에도 적용했습니다. 이 추상화의 적절성과 재사용성에 대한 의견을 주시면 좋겠습니다.PaymentTransactionService에서 도메인 이벤트를 발행하는 시점이 트랜잭션 커밋 이전이 아닌, 상태 변경 및 저장 후에AFTER_COMMIT리스너에서 처리되도록 한 점에 유의해주세요..claude디렉토리는 Claude AI 툴을 위한 가이드 및 설정 파일입니다. 코드 로직과는 무관합니다.➕ 추가 정보 (Additional Information)
N/A