Skip to content

feat/36 - fix: 주문 생성 부분도 비동기로 변경 - #37

Merged
ji-circle merged 4 commits into
devfrom
feat/36-async-stock-reserve-consumer
May 17, 2026
Merged

ji-circle merged 4 commits into
devfrom
feat/36-async-stock-reserve-consumer

Conversation

@ji-circle

@ji-circle ji-circle commented May 15, 2026

Copy link
Copy Markdown
Contributor

📝 작업 내용

이번 PR에서 작업한 내용을 설명해주세요.

  • 주문 생성 부분도 비동기로 변경

🚀 주요 변경 사항

완료한 이슈 번호
Close #36
관련된 이슈 번호 (닫고 싶지 않은 경우)
Related to #

✅ 자체 체크리스트 (필수)

  • ./gradlew build 실행 결과 정상 (인증샷 첨부)
  • IntelliJ HTTP Client 테스트 완료 (인증샷 첨부)
  • 팀 내 컨벤션 준수 및 불필요한 로그, import 제거
  • 중요한 변경 사항이 팀에 공유되었는지

📸 테스트 인증샷

빌드 결과 및 IntelliJ HTTP Client 실행 화면을 여기에 첨부해 주세요.

스크린샷 2026-05-16 오전 2 05 37 스크린샷 2026-05-16 오전 2 05 46 스크린샷 2026-05-16 오전 2 08 10 스크린샷 2026-05-16 오전 2 09 40

💬 리뷰어 전달사항 (선택)

특별히 봐주었으면 하는 부분이나 논의가 필요한 점을 적어주세요.



📎 참고 자료

관련 문서, 레퍼런스 링크 등이 있다면 여기에 첨부해주세요.

Summary by CodeRabbit

  • New Features

    • 주문 생성 시 자동 재고 예약, ORDER_APPROVED/ORDER_REJECTED 이벤트 발행 지원
    • 다중 품목 선점 잠금으로 동시성 제어 강화
    • Outbox에 보상/거절용 독립 트랜잭션 적재 기능 추가
  • Refactor

    • Kafka 소비자 라우팅 통합 및 DLT 구독 목록 정비
    • 내부 REST 엔드포인트 제거로 책임을 서비스/페이로드 처리로 이관
    • 통합 커맨드 토픽 및 메시지 타입 매핑 정비
  • Style/Validation

    • 주문 관련 메시지/이벤트 DTO에 입력 유효성 검사(Null/빈값/범위) 추가

Review Change Stack

@ji-circle ji-circle added the enhancement New feature or request label May 15, 2026
@github-actions
github-actions Bot requested a review from githyj-jang May 15, 2026 19:02
@coderabbitai

coderabbitai Bot commented May 15, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: f8b8905f-3700-4642-a4c7-6888d1152a31

📥 Commits

Reviewing files that changed from the base of the PR and between 635776c and 0b50806.

📒 Files selected for processing (1)
  • src/main/java/com/michelet/inventory/infrastructure/messaging/OrderEventConsumer.java

📝 Walkthrough

Walkthrough

Kafka의 주문 생성 메시지를 받아 OrderEventConsumer → StockLockFacade(정렬 기반 멀티락) → StockCommandService(트랜잭션 재고 차감, 멱등성 검사) 흐름으로 처리하고 결과를 Outbox의 ORDER_APPROVED/ORDER_REJECTED로 적재합니다.

Changes

주문 생성 비동기 처리 및 다중 재고 차감 흐름

Layer / File(s) Summary
주문 메시지 계약 및 이벤트 DTO 정의
src/main/java/com/michelet/inventory/infrastructure/messaging/dto/OrderCreatedMessage.java, OrderApprovedEvent.java, OrderRejectedEvent.java
OrderCreatedMessage는 eventId, reservationId, List 필드를 포함하며 각 필드 null/빈 검증을 compact constructor에서 수행합니다. OrderItemDto는 optionId(null 불가), quantity(>=1) 검증을 포함합니다. OrderApprovedEvent/OrderRejectedEvent는 생성자 유효성 검증을 수행합니다.
Outbox 헬퍼 및 스케줄러 확장
src/main/java/com/michelet/inventory/application/InventoryOutboxHelper.java, InventoryOutboxScheduler.java
InventoryOutboxHelper에 validateInputs 공통화와 REQUIRES_NEW 전파의 appendIndependent를 추가했습니다. InventoryOutboxScheduler는 EVENT_ORDER_APPROVED/ORDER_REJECTED 상수, 토픽 주입, deserializePayload/resolveTopic 분기를 확장했습니다.
주문 생성 시점 재고 차감 처리
src/main/java/com/michelet/inventory/application/StockCommandService.java
processOrderCreation 메서드가 메시지 멱등성 검사, 항목별 Stock.reserve, 품절 전이 시 PRODUCT_STATUS_CHANGED Outbox 적재, 변경된 Stocks 일괄 저장, ProcessedEvent 기록 및 ORDER_APPROVED Outbox 적재를 트랜잭션으로 수행합니다.
데드락 회피 다중 재고 락 획득
src/main/java/com/michelet/inventory/application/StockLockFacade.java
reserveOrderStocksWithLock 메서드는 optionId를 정렬해 Redisson RLock을 순차로 tryLock(5초)로 획득하며 실패 시 CONCURRENCY_ERROR를 던집니다. 모든 락 획득 시 processOrderCreation을 호출하고 finally에서 역순 해제합니다.
주문 생성 이벤트 소비 및 예외 처리 라우팅
src/main/java/com/michelet/inventory/infrastructure/messaging/OrderEventConsumer.java
클래스 레벨 @KafkaListener + @KafkaHandler 구조로 전환되어 consumeOrderCreated가 추가되었습니다. IllegalArgumentException은 재throw(DLT), ConcurrencyFailureException은 재시도용 RuntimeException으로 래핑, BusinessException은 appendIndependent(ORDER_REJECTED)로 기록하고 전파하지 않습니다. 기본 unknown handler도 추가되었습니다.
메시징 인프라 및 설정 업데이트
src/main/java/com/michelet/inventory/infrastructure/messaging/DeadLetterConsumer.java, src/main/resources/application.yml, src/test/resources/application-test.yml
DeadLetterConsumer의 DLT 구독 목록을 inventory-command DLT 포함으로 갱신했고, application.yml에 JSON 타입 매핑(OrderCreatedEventPayload→OrderCreatedMessage)과 inventory-command / order-approved / order-rejected 토픽 설정을 추가했습니다. 테스트 설정에 inventory-command 토픽 매핑을 추가했습니다.
테스트 임포트 변경
src/test/...
테스트에서 Reserve/Restore DTO 임포트 경로를 com.michelet.inventory.application.dto로 변경했습니다.

Sequence Diagram

sequenceDiagram
  participant Kafka as Kafka (order-created)
  participant Consumer as OrderEventConsumer
  participant Lock as StockLockFacade
  participant Command as StockCommandService
  participant Repo as StockRepository
  participant Outbox as InventoryOutbox

  Kafka->>Consumer: OrderCreatedMessage
  Consumer->>Lock: reserveOrderStocksWithLock(msg)
  Lock->>Lock: 정렬된 optionId 리스트 생성
  Lock->>Lock: sequential tryLock(stock:{optionId}, 5s)
  Lock->>Command: processOrderCreation(msg)
  Command->>Repo: 멱등성 검사(ProcessedEvent)
  Command->>Repo: Stock.reserve(optionId, qty)
  alt 품절 발생
    Command->>Repo: Product.status = SOLDOUT
    Command->>Outbox: append(PRODUCT_STATUS_CHANGED)
  end
  Command->>Repo: saveAll(Stocks)
  Command->>Repo: save(ProcessedEvent)
  alt 전체 성공
    Command->>Outbox: append(ORDER_APPROVED)
  else 비즈니스 실패
    Command-->>Consumer: BusinessException
    Consumer->>Outbox: appendIndependent(ORDER_REJECTED)
  end
  Lock->>Lock: finally: 역순 unlock
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • githyj-jang
  • Jinyoung-Kim96
  • qldo
  • Sehi55
  • jihxonx

Poem

🐰 깡충깡충 메시지 왔네,
옵션 정렬해 락을 잡네.
멱등 확인하고 재고 줄여,
승인·거절은 Outbox에 담네.
당근처럼 빠른 배포 오길.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목은 주문 생성 부분을 비동기로 변경하는 내용을 명확히 반영하고 있으며, 변경 사항의 핵심을 잘 요약하고 있습니다.
Linked Issues check ✅ Passed 모든 연결 이슈 #36의 코딩 요구사항이 충족되었습니다: OrderEventConsumer 구현, 정렬 기반의 StockLockFacade 구현, ProcessedEvent를 통한 멱등성 보장, ORDER_APPROVED/ORDER_REJECTED 이벤트 Outbox 적재가 모두 구현되었습니다.
Out of Scope Changes check ✅ Passed ReserveStockRequest/RestoreStockRequest의 패키지 이동, InternalStockController 제거, InventoryOutboxHelper의 appendIndependent 메서드 추가 등이 모두 비동기 주문 생성 처리 구현을 위한 필요한 변경사항입니다.
Docstring Coverage ✅ Passed Docstring coverage is 82.35% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/36-async-stock-reserve-consumer

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

coderabbitai[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

@qldo qldo left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

확인하였습니다

@ji-circle
ji-circle merged commit 081faf3 into dev May 17, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEAT] 비동기 주문 생성 이벤트 수신 및 다중 재고 차감 처리 로직 구현

2 participants