개요
트랜잭션 내에서 비멱등 외부 PATCH인 restoreHubInventory()를 직접 호출하면,
DB 커밋 실패 또는 프로세스 중단 시 재고가 이중으로 복구될 위험이 있습니다.
문제 상세
OrderCommandServiceImpl의 createOrder() 및 cancelOrder() 메서드에서
restoreInventory(order)가 로컬 트랜잭션 커밋 전에 바로 호출됩니다.
- 외부 PATCH(
restoreHubInventory)가 먼저 실행됨
- 이후 DB 커밋 실패 또는 프로세스 중단이 발생하면, 주문 상태는 저장되지 않은 채 재고만 복구된 상태가 됨
- 동일 요청 재시도 시 복구가 한 번 더 적용되어 재고 불일치 발생 가능
영향 범위
OrderCommandServiceImpl#createOrder() — FeignException catch 블록 (약 63~65번째 줄)
OrderCommandServiceImpl#cancelOrder() — restoreInventory(order) 호출부 (약 102~110번째 줄)
해결 방향 (안)
- After-commit 이벤트/Outbox 패턴: 재고 복구 요청을 DB 커밋 완료 후 이벤트로 발행하여 외부 PATCH가 정확히 한 번만 수행되도록 보장
- 멱등성 보장:
orderId 기반의 복구 로그(restore-log) 테이블을 두어, 외부 호출 전 중복 여부를 확인 후 적용
참고
개요
트랜잭션 내에서 비멱등 외부 PATCH인
restoreHubInventory()를 직접 호출하면,DB 커밋 실패 또는 프로세스 중단 시 재고가 이중으로 복구될 위험이 있습니다.
문제 상세
OrderCommandServiceImpl의createOrder()및cancelOrder()메서드에서restoreInventory(order)가 로컬 트랜잭션 커밋 전에 바로 호출됩니다.restoreHubInventory)가 먼저 실행됨영향 범위
OrderCommandServiceImpl#createOrder()—FeignExceptioncatch 블록 (약 63~65번째 줄)OrderCommandServiceImpl#cancelOrder()—restoreInventory(order)호출부 (약 102~110번째 줄)해결 방향 (안)
orderId기반의 복구 로그(restore-log) 테이블을 두어, 외부 호출 전 중복 여부를 확인 후 적용참고