"코드가 실행되다가 서버가 죽거나 행(Hang)이 걸려서, PG사에서 돈은 나갔는데 내 DB는 그대로라면?"
prepareOrderForPayment: DB 상태를 IN_PROGRESS로 변경.
public Payment executePayment(String paymentKey, Long orderNo, BigDecimal amount, Long productNo, Integer count) {
orderService.prepareOrderForPayment(orderNo, amount); // pending -> payment_in_progress
PaymentResult paymentResult;
try {
paymentResult = paymentClient.approve(paymentKey, orderNo, amount); // PG 사 통신을 통해 결제 : 여기서 개오래걸려서 밑에 실행 안되면?
} catch (Exception e) {
orderService.rollbackToPending(orderNo); // payment_in_progress -> pending : 이거 실패하면?
throw e;
}
switch (paymentResult.status()) {
case "DONE" -> {
return paymentService.completePayment(orderNo, paymentResult); // payment_in_progress -> paid / payment 저장
}
case "ABORTED" -> {
paymentService.registerFailedPayment(orderNo, paymentResult); // 실패한 결제 이력 payment 저장
orderService.rollbackToPending(orderNo); // payment_in_progress -> pending
throw PaymentFailedException.aborted(paymentKey, orderNo, paymentResult.failureMessage());
}
case "EXPIRED" -> {
paymentService.registerFailedPayment(orderNo, paymentResult); // 실패한 결제 이력 payment 저장
purchaseFacade.cancel(orderNo, productNo, count); // payment_in_progress -> canceled / stock 복구
throw PaymentFailedException.expired(paymentKey, orderNo, paymentResult.failureMessage());
}
default -> throw PaymentFailedException.invalid(paymentKey, orderNo, paymentResult.status());
}
}
paymentClient.approve: PG사에 요청을 보냄. (성공 → 고객 돈 출금)
— 여기서 서버 터짐 / CPU 100%로 스레드 멈춤 —
completePayment: 이 코드는 영원히 실행되지 않음.
catch 블록: 당연히 실행되지 않음.
paymentClient.approve()에서 무한정 대기하는 것을 막기 위해 Timeout 설정을 걸어주자.
→ 하지만 이것은 지연을 막을 뿐, 서버가 죽는 것은 못 막는다.