[RxJava] RxJava retryWhen으로 예외발생시 일정시간 간격으로 재시도 처리하기(retryWithDelay)

2021. 12. 30. 11:26·Android/RxJava
반응형

Rxjava를 사용할 때 예외처리 과정에서 retryWhen()을 사용하면 재시도를 구현할 수 있습니다.

이번 포스트에서는 retryWhen 메소드에 대해 정리해보겠습니다.

retryWhen의 마블 다이어그램

retryWhen의 마블 다이어그램을 해석

먼저, Observable에서 에러가 발생됩니다. 그러면 retryWhen을 타게 되는데

retryWhen에서 데이터가 발행되면 -> upstream을 재실행합니다. 

retryWhen에서 에러가 발행되면 -> 최종적으로 error를 발행합니다.

Flowable의 retryWhen 구현부

public abstract class Flowable<T> implements Publisher<T> {

	// ...
    
	@CheckReturnValue
    @NonNull
    @BackpressureSupport(BackpressureKind.FULL)
    @SchedulerSupport(SchedulerSupport.NONE)
    public final Flowable<T> retryWhen(
            final Function<? super Flowable<Throwable>, ? extends Publisher<?>> handler) {
        ObjectHelper.requireNonNull(handler, "handler is null");

        return RxJavaPlugins.onAssembly(new FlowableRetryWhen<T>(this, handler));
    }
}
public interface Function<T, R> {
    /**
     * Apply some calculation to the input value and return some other value.
     * @param t the input value
     * @return the output value
     * @throws Exception on error
     */
    R apply(@NonNull T t) throws Exception;
}

retryWhen함수는 Rxjava에서 제공하는 Function인터페이스인 handler 인자로 받습니다.

그리고 handler는 제네릭으로 Flowable<Throwable>과 Publisher<*>를 받게 됩니다.

 

결국, Function의 apply()함수는 Flowable<Throwable>을 매개변수로 받고, Publisher<*>를 return하게 됩니다.

 

Function<Flowable<Throwable>, Publisher<*>>를 상속한 RetryWithDelaySingle 이용

Function<Flowable<Throwable>, Publisher<*>>를 상속한 RetryWithDelaySingle을 만들어줍니다.

apply() 함수에서는 timer()를 이용해서 retryCount 만큼 delayMillis의 딜레이마다 데이터를 던지게 만들어주고

retryCount가 maxRetries를 넘어가면 error를 던지도록 만들어줍니다.

 

import io.reactivex.Flowable
import io.reactivex.functions.Function
import org.reactivestreams.Publisher
import java.util.concurrent.TimeUnit

class RetryWithDelaySingle(private val maxRetries: Int, private val retryDelayMillis: Int) : Function<Flowable<Throwable>, Publisher<*>> {

    constructor(retryDelayMillis: Int) : this(5, retryDelayMillis)

    private var retryCount = 0

    override fun apply(flowable: Flowable<Throwable>): Flowable<*> = flowable
        .flatMap { throwable ->
            if (maxRetries < 0 || ++retryCount <= maxRetries) {
                // When this Observable calls onNext, the original
                // Observable will be retried (i.e. re-subscribed).
                Flowable.timer(retryDelayMillis.toLong(), TimeUnit.MILLISECONDS)
            } else Flowable.error(throwable)
        }
}

일정시간의 간격으로 5번의 재시도 후에 error를 던지도록 해줍니다.

fun main() {
    Single.error<Throwable>(IllegalArgumentException())
        .doOnError {
            println("error")
        }
        .retryWhen(RetryWithDelaySingle(5, 500))
        .subscribe({
            println("onSuccess()")
        }, {
            println("onError()")
        })
    Thread.sleep(2500L)
}

실행결과

첫번째 실행 이후, 뒤에 5번의 재시도를 실행하고, 최종적으로 onError()를 던지는 것을 확인할 수 있습니다.

 

retryWhen에서 delay()와 take()를 이용

fun main() {
    Single.error<Throwable>(IllegalArgumentException())
        .doOnError {
            println("error")
        }
        .retryWhen {
            it
                .delay(500, TimeUnit.MILLISECONDS)
                .take(5)
        }
        .subscribe({
            println("onSuccess()")
        }, {
            println("onError()")
        })
    Thread.sleep(5000L)
}

람다식을 사용할 경우에는 간단하게 Publisher<*>를 반환해주면 되므로, 위와 같이 delay와 take를 조합하여 간단하게 만들어 줄 수 있습니다.

실행결과도 예제1과 같은 동작을 수행하게 됩니다.

실행결과

 

감사합니다!

반응형
'Android/RxJava' 카테고리의 다른 글
  • [RxJava] flatMap의 원리 및 Observable 스트림 종료 후 다시 이어가기
  • [RxJava] 조합 연산자(Combining Operators)
  • [RxJava] 분류 연산자(Filtering Operators)
  • [RxJava] 변환 연산자(Transforming Operators)
seunghwaan
seunghwaan
공부한 내용을 정리하는 개발 기록 블로그
    반응형
  • seunghwaan
    SH's Devlog
    seunghwaan
  • 전체
    오늘
    어제
    • 분류 전체보기 (148)
      • Android (62)
        • Basic (17)
        • Kotlin(Java) (14)
        • UI & Animation (1)
        • Compose (2)
        • Coroutines (1)
        • Dependency Injection (6)
        • RxJava (8)
        • BLE (3)
        • TDD (2)
        • JetPack (1)
        • NextStep (4)
        • Error Log (3)
      • Flutter (14)
        • Basic (5)
        • Dart (1)
        • State Management (2)
        • Widgets (4)
        • Error and Tips (2)
      • iOS (8)
        • Basic (0)
        • Swift (8)
      • Web Frontend (4)
        • JavaScript(TS) (4)
        • React (0)
      • CS(Computer Science) (18)
        • Network (4)
        • Database (10)
        • Design Pattern (1)
        • Computer Architecture (3)
        • Operating System (0)
      • Cloud (6)
        • AWS (6)
      • DevOps (25)
        • GIT (4)
        • CI CD (8)
        • Linux (4)
        • Docker (9)
        • Error Log (0)
      • 코딩테스트 (10)
        • DB (6)
        • 알고리즘 (4)
      • Backend (1)
        • Spring (1)
      • Mac Tip (0)
      • Language (0)
        • English (0)
        • Japanese (0)
      • Temporary (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    Kotlin
    di
    CI
    Network
    시작하세요! 도커
    네트워크
    FLUTTER
    컴퓨터공학
    cs
    BLE
    database
    CICD
    gradle
    error
    Dependency Injection
    AWS
    IOS
    JavaScript
    Computer Science
    RxJava
    상태 관리
    Dagger
    Linux
    Jenkins
    Swift
    MySQL
    Algorithm
    docker
    cognito
    Android
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
seunghwaan
[RxJava] RxJava retryWhen으로 예외발생시 일정시간 간격으로 재시도 처리하기(retryWithDelay)
상단으로

티스토리툴바