개발 일기장/TWIL

20.03.30 ~ 20.04.03 TWIL

희랍인 조르바 2020. 4. 4. 16:01

rxJava로 retry 처리

스케줄러가 돌아가면서 외부업체 api를 날리다 실패했을 경우 retry가 필요할 것 같아, retry로직을 작성했다. 처음에 생각한 코드는 다음과 같다.


publc class BookingRequestService {

    private final BookingApiService bookingApiService;

    public Booking(BookingApiService bookingApiService) {
        this.bookingApiService = bookingApiService;
    }

    private static final String MAX_RETRY = 3;

    public BookingResponse requestBooking() {
        int reqeustCount = 1;
        while(requestCount <= MAX_RETRY) {
        
            try {
                return bookingApiService.requestBooking();
            } catch(RestClientException e) {
                log.error("api 요청 중 실패, 요청 횟수 : {}회", reqeustCount, e);
                reqeustCount++;
            }
            
        }
    }
}    

 

rxJava로 retry를 굳이 처리한 이유는 프로젝트 내부에서 rxJava를 적용한 곳이 있고, 코드를 봤을 때 rxJava는 retry를 라이브러리로 제공하고 있어 더 깔끔하게 처리할 수 있고, 위와 같은 retry 코드를 여러 곳에 작성하면 길고 중복된 코드를 줄이기 위함이었다.

 


publc class BookingRequestService {

    private final BookingApiService bookingApiService;

    public Booking(BookingApiService bookingApiService) {
        this.bookingApiService = bookingApiService;
    }

    private static final String MAX_RETRY = 3;

    public BookingResponse requestBooking(OrderForm orderForm) {
        return Maybe.fromCallable(() -> bookingApiService.requestBooking(orderForm))
                .retry((retryCount, throwable) -> isRetry(retryCount, throwable, orderForm.getBookingId()))
                .blockingGet();
    }

    private boolean isRetry(Integer retryCount, Throwable throwable, String bookingId) {
        if (retryCount > MAX_RETRY) {
            return false;
        }
        if(!(throwable instanceof RestClientException)) {
            return false;
        }
        logger.info("api 요청 중 실패, 요청 횟수 : {}회, booking Id : {} ", retryCount, bookingId);
        return true;
    }


}    

rxJava를 배운적은 없지만 알아먹을 수 있었던 건 카카오 때 Spring WebFlux에서 사용하는 reactor를 잠깐 써본 경험이 있어서 알아먹을 수 있었다. (개념적으로 많이 유사하다)

 

Maybe는 rxJava에서 나오는 개념으로 Single의 값이 발행되거나, null이거나 exception이 떨어질 수 있음을 나타내는 클래스이다. Maybe는 지연 연산 및 로딩으로 수행한다.

참고: Maybe javaDoc

 

Maybe.fromCallable이 아닌 Maybe.just를 사용할 경우, null이 떨어지면 NPE(Null Pointer Exception)가 떨어진다. fromCallable을 사용할 경우, 빈 값이 오고, NPE가 발생하지 않는다. retry하면서 NPE를 체크할 필요가 없었기에 fromCallable을 사용했다.

참고: Maybe null handling 참고 사이트

 

(사실 이 코드를 작성한 시간보다 다른 영향 가는 부분 체크하는데 시간을 훨씬 많이썼다......)