실패한 활동 재시도 - AWS Flow Framework 자바용

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

실패한 활동 재시도

잠시 연결이 끊기는 등 일시적인 이유로 활동이 실패하는 경우가 가끔 있습니다. 딴 때는 활동이 성공할 수 있으므로 많은 경우 활동 실패를 처리하는 적절한 방법은 활동을 재시도하는 것입니다. 시도 횟수는 여러 번이 될 수 있습니다.

활동 재시도와 관련해 다양한 전략이 있지만, 워크플로의 세부 내용에 따라 가장 좋은 전략이 무엇인지 결정됩니다. 그러한 전략은 다음과 같은 세 가지 기본 범주로 구분됩니다.

  • 성공할 때까지 재시도하는 전략은 활동이 완료될 때까지 계속해서 재시도하는 것입니다.

  • 기하급수적 재시도 전략에서는 활동이 완료되거나 프로세스가 최대 시도 횟수와 같이 지정된 중단 지점에 이를 때까지 재시도 사이의 시간 간격을 기하급수적으로 늘립니다.

  • 사용자 지정 재시도 전략에서는 시도가 실패한 후에 활동을 재시도할지 여부, 재시도한다면 재시도 방법을 결정합니다.

다음 단원에서는 이러한 전략을 구현하는 방법에 관해 설명합니다. 예시 워크플로 작업자는 모두 단일 활동인 unreliableActivity를 사용하는데, 이 활동에서는 임의로 다음 중 하나를 수행합니다.

  • 즉시 완료

  • 의도적으로 제한 시간 값을 초과하여 실패

  • 의도적으로 IllegalStateException을 발생시켜 실패

성공할 때까지 재시도하는 전략

가장 단순한 재시도 전략은 결국 성공할 때까지 활동 재시도가 실패할 때마다 계속 재시도하는 것입니다. 기본 패턴은 다음과 같습니다.

  1. 워크플로의 진입점 메서드에서 중첩된 TryCatch 또는 TryCatchFinally 클래스 구현합니다.

  2. doTry에서 활동을 실행합니다.

  3. 이 활동이 실패한 경우, 프레임워크에서 doCatch를 호출하면 진입점 메서드가 다시 실행됩니다.

  4. 활동이 성공적으로 완료될 때까지 2-3단계를 반복합니다.

다음 워크플로에서는 성공할 떄까지 재시도하는 전략을 구현합니다. 이 워크플로 인터페이스는 RetryActivityRecipeWorkflow에서 구현되고 이 워크플로의 진입점인 runUnreliableActivityTillSuccess라는 메서드가 한 개 있습니다. 워크플로 작업자는 RetryActivityRecipeWorkflowImpl에서 다음과 같이 구현됩니다.

public class RetryActivityRecipeWorkflowImpl implements RetryActivityRecipeWorkflow { @Override public void runUnreliableActivityTillSuccess() { final Settable<Boolean> retryActivity = new Settable<Boolean>(); new TryCatch() { @Override protected void doTry() throws Throwable { Promise<Void> activityRanSuccessfully = client.unreliableActivity(); setRetryActivityToFalse(activityRanSuccessfully, retryActivity); } @Override protected void doCatch(Throwable e) throws Throwable { retryActivity.set(true); } }; restartRunUnreliableActivityTillSuccess(retryActivity); } @Asynchronous private void setRetryActivityToFalse( Promise<Void> activityRanSuccessfully, @NoWait Settable<Boolean> retryActivity) { retryActivity.set(false); } @Asynchronous private void restartRunUnreliableActivityTillSuccess( Settable<Boolean> retryActivity) { if (retryActivity.get()) { runUnreliableActivityTillSuccess(); } } }

워크플로는 다음과 같이 작동합니다.

  1. runUnreliableActivityTillSuccess에서는 활동이 실패했는지 여부와 재시도할지 여부를 나타내는 데 사용되는 retryActivity라는 Settable<Boolean> 객체를 생성합니다. Settable<T>Promise<T>에서 파생된 것으로서 거의 동일한 방식으로 작동하지만, Settable<T> 객체의 값은 사용자가 수동으로 설정해 줍니다.

  2. runUnreliableActivityTillSuccess에서는 익명의 중첩된 TryCatch 클래스를 구현하여 unreliableActivity 활동에서 발생하는 모든 예외를 처리합니다. 비동기식 코드에서 발생하는 예외를 처리하는 방법에 관한 자세한 내용은 오류 처리 단원을 참조하십시오.

  3. doTry에서는 activityRanSuccessfully라는 Promise<Void> 객체를 반환하는 unreliableActivity 활동을 실행합니다.

  4. doTry에서는 다음과 같이 파라미터가 두 개인 비동기식 setRetryActivityToFalse 메서드를 호출합니다.

    • activityRanSuccessfully에서는 unreliableActivity 활동에서 반환하는 Promise<Void> 객체를 받아들입니다.

    • retryActivity에서는 retryActivity 객체를 받아들입니다.

    unreliableActivity가 완료되면 activityRanSuccessfully가 준비 상태가 되고 setRetryActivityToFalse에서는 retryActivity를 false로 설정합니다. 완료되지 않으면 activityRanSuccessfully는 결코 준비 상태가 되지 않고 setRetryActivityToFalse는 실행되지 않습니다.

  5. unreliableActivity에서 예외가 발생하면 프레임워크에서는 doCatch를 호출하여 예외 객체를 전달합니다. doCatchretryActivity를 true로 설정합니다.

  6. runUnreliableActivityTillSuccess에서는 비동기식 restartRunUnreliableActivityTillSuccess 메서드를 호출한 후 이 메서드에 retryActivity 객체를 전달합니다. retryActivityPromise<T> 유형이므로 restartRunUnreliableActivityTillSuccess에서는 retryActivity가 준비 상태가 될 때까지 실행을 연기합니다. 실행은 TryCatch가 완료된 후에 이뤄집니다.

  7. retryActivity가 준비 상태가 되면 restartRunUnreliableActivityTillSuccess에서 값을 추출합니다.

    • 값이 false이면 재시도가 성공한 것입니다. restartRunUnreliableActivityTillSuccess는 아무것도 하지 않고 재시도 시퀀스는 종료됩니다.

    • 값이 true이면 재시도가 실패한 것입니다. restartRunUnreliableActivityTillSuccess에서 runUnreliableActivityTillSuccess를 호출하여 다시 활동을 실행합니다.

  8. unreliableActivity가 완료될 때까지 1-7단계가 반복됩니다.

참고

doCatch에서는 예외를 처리하지 않고 단지 retryActivity 객체를 true로 설정하여 활동이 실패하였음을 나타냅니다. 재시도는 비동기식 restartRunUnreliableActivityTillSuccess 메서드에서 처리하는데, 이 메서드에서는 TryCatch가 완료될 때까지 실행을 연기합니다. 이 접근 방식을 사용하는 이유는 doCatch에서 활동을 재시도하면 이를 취소할 수 없기 때문입니다. restartRunUnreliableActivityTillSuccess에서 활동을 재시도하면 사용자는 취소 가능한 활동을 실행할 수 있습니다.

기하급수적 재시도 전략

기하급수적 재시도 전략의 경우 지정된 시간, 즉 N초 후 프레임워크에서 실패한 활동을 다시 실행합니다. 이 시도가 실패하면 프레임워크에서는 2N초 후에, 이어서 4N초 후에 실행하는 식으로 계속해서 활동을 다시 실행합니다. 대기 시간이 상당히 길어질 수 있으므로 일반적으로 무한정 재시도를 계속하는 것보다는 일정 시점에서 중단하는 것이 좋습니다.

프레임워크에서는 다음과 같이 기하급수적 재시도 전략을 구현할 수 있는 세 가지 방식을 제공합니다.

  • @ExponentialRetry 주석은 가장 단순한 접근 방식이지만, 컴파일 시간에 재시도 구성 옵션을 설정해야 합니다.

  • RetryDecorator 클래스를 통해 런타임에 재시도 구성을 설정하고 필요에 따라 이를 변경할 수 있습니다.

  • AsyncRetryingExecutor 클래스를 통해 런타임에 재시도 구성을 설정하고 필요에 따라 이를 변경할 수 있습니다. 뿐만 아니라 프레임워크에서는 사용자 구현 AsyncRunnable.run 메서드를 호출하여 매번 재시도를 실행합니다.

모든 접근 방식에서는 다음 구성 옵션을 지원합니다. 이 옵션에서 시간 값은 초 단위입니다.

  • 최초 재시도 대기 시간

  • 다음과 같이 재시도 간격을 계산하는 데 사용되는 백오프 계수

    retryInterval = initialRetryIntervalSeconds * Math.pow(backoffCoefficient, numberOfTries - 2)

    기본값은 2.0입니다.

  • 최대 재시도 횟수. 기본값은 무제한입니다.

  • 최대 재시도 간격. 기본값은 무제한입니다.

  • 만료 시간. 프로세스의 총 시간이 이 값을 초과하면 재시도가 중단됩니다. 기본값은 무제한입니다.

  • 재시도 프로세스를 트리거할 예외. 기본적으로 모든 예외가 재시도 프로세스를 트리거합니다.

  • 재시도를 트리거하지 않을 예외. 기본적으로 어떤 예외도 배제되지 않습니다.

다음 단원에서는 기하급수적 재시도 전략을 구현하는 다양한 방법에 관해 설명합니다.

@ExponentialRetry을 이용한 기하급수적 재시도

활동에 대해 기하급수적 재시도 전략을 구현하는 가장 간단한 방법은 인터페이스 정의에서 활동에 대해 @ExponentialRetry 주석을 붙이는 것입니다. 활동이 실패하면 프레임워크에서는 지정된 옵션 값에 따라 재시도 프로세스를 자동으로 처리합니다. 기본 패턴은 다음과 같습니다.

  1. @ExponentialRetry를 적절한 활동에 붙이고 재시도 구성을 지정합니다.

  2. 주석이 달린 활동이 실패하면 프레임워크에서는 주석의 인수에서 지정한 구성에 따라 활동을 자동으로 재시도합니다.

ExponentialRetryAnnotationWorkflow 워크플로 작업자는 @ExponentialRetry 주석을 사용하여 기하급수적 재시도 전략을 구현합니다. 이 작업자는 다음과 같이 인터페이스 정의가 ExponentialRetryAnnotationActivities에 구현되는 unreliableActivity 활동을 사용합니다.

@Activities(version = "1.0") @ActivityRegistrationOptions( defaultTaskScheduleToStartTimeoutSeconds = 30, defaultTaskStartToCloseTimeoutSeconds = 30) public interface ExponentialRetryAnnotationActivities { @ExponentialRetry( initialRetryIntervalSeconds = 5, maximumAttempts = 5, exceptionsToRetry = IllegalStateException.class) public void unreliableActivity(); }

@ExponentialRetry옵션에서는 다음과 같은 전략을 지정합니다.

  • 활동에서 IllegalStateException이 발생한 경우에만 재시도합니다.

  • 초기 대기 시간 5초를 사용합니다.

  • 재시도를 5회 이내로 제한합니다.

이 워크플로 인터페이스는 RetryWorkflow에서 구현되고 이 워크플로의 진입점인 process라는 메서드가 한 개 있습니다. 워크플로 작업자는 ExponentialRetryAnnotationWorkflowImpl에서 다음과 같이 구현됩니다.

public class ExponentialRetryAnnotationWorkflowImpl implements RetryWorkflow { public void process() { handleUnreliableActivity(); } public void handleUnreliableActivity() { client.unreliableActivity(); } }

워크플로는 다음과 같이 작동합니다.

  1. process에서는 동기식 handleUnreliableActivity 메서드를 실행합니다.

  2. handleUnreliableActivity에서는 unreliableActivity 활동을 실행합니다.

IllegalStateException 예외가 발생하여 활동이 실패하면 프레임워크에서는 ExponentialRetryAnnotationActivities에 지정된 재시도 전략을 자동으로 실행합니다.

RetryDecorator 클래스를 이용한 기하급수적 재시도

@ExponentialRetry는 사용하기 간편합니다. 그러나 구성이 정적이고 컴파일 시에 설정되므로 프레임워크에서는 활동이 실패할 때마다 동일한 재시도 전략을 사용합니다. 런타임에 구성을 지정하고 필요에 따라 이를 변경할 수 있게 해주는 RetryDecorator 클래스를 사용하여 더 유연한 기하급수적 재시도 전략을 구현할 수 있습니다. 기본 패턴은 다음과 같습니다.

  1. 재시도 구성을 지정하는 ExponentialRetryPolicy 객체를 만들고 구성합니다.

  2. RetryDecorator 객체를 만들고 1단계의 ExponentialRetryPolicy 객체를 생성자에게 전달합니다.

  3. 활동 클라이언트의 클래스 이름을 RetryDecorator 객체의 장식 메서드에 전달하여 장식자 객체를 활동에 추가합니다.

  4. 활동을 실행합니다.

활동이 실패하면 프레임워크에서는 ExponentialRetryPolicy 객체의 구성에 따라 활동을 재시도합니다. 이 객체를 수정하여 필요에 따라 재시도 구성을 변경할 수 있습니다.

참고

@ExponentialRetry주석 및 RetryDecorator 클래스는 상호 배타적입니다. @ExponentialRetry 주석에서 지정한 재시도 정책을 동적으로 재정의하는 데 RetryDecorator를 사용할 수는 없습니다.

다음 워크플로 구현에서는 RetryDecorator 클래스를 사용하여 기하급수적 재시도 전략을 구현하는 방법을 보여줍니다. 이 구현에서는 @ExponentialRetry 주석이 없는 unreliableActivity 활동을 사용합니다. 이 워크플로 인터페이스는 RetryWorkflow에서 구현되고 이 워크플로의 진입점인 process라는 메서드가 한 개 있습니다. 워크플로 작업자는 DecoratorRetryWorkflowImpl에서 다음과 같이 구현됩니다.

public class DecoratorRetryWorkflowImpl implements RetryWorkflow { ... public void process() { long initialRetryIntervalSeconds = 5; int maximumAttempts = 5; ExponentialRetryPolicy retryPolicy = new ExponentialRetryPolicy( initialRetryIntervalSeconds).withMaximumAttempts(maximumAttempts); Decorator retryDecorator = new RetryDecorator(retryPolicy); client = retryDecorator.decorate(RetryActivitiesClient.class, client); handleUnreliableActivity(); } public void handleUnreliableActivity() { client.unreliableActivity(); } }

워크플로는 다음과 같이 작동합니다.

  1. process에서는 다음 방법으로 ExponentialRetryPolicy 객체를 생성 및 구성합니다.

    • 초기 재시도 간격을 생성자에게 전달

    • 객체의 withMaximumAttempts 메서드를 호출하여 최대 시도 횟수를 5로 설정. ExponentialRetryPolicy에서는 다른 구성 옵션을 지정하는 데 사용할 수 있는 다른 with 객체를 노출합니다.

  2. process에서는 retryDecorator이라는 RetryDecorator 객체를 만들고 1단계의 ExponentialRetryPolicy 객체를 생성자에게 전달합니다.

  3. process에서는 retryDecorator.decorate 메서드를 호출한 후 이 메서드에 활동 클라이언트의 클래스 이름을 전달하여 활동에 장식자를 추가합니다.

  4. handleUnreliableActivity에서는 활동을 실행합니다.

활동이 실패하면 프레임워크에서는 1단계에서 지정한 구성에 따라 활동을 재시도합니다.

참고

ExponentialRetryPolicy 클래스의 with 메서드 중 몇 가지, 즉 setBackoffCoefficient, setMaximumAttempts, setMaximumRetryIntervalSecondssetMaximumRetryExpirationIntervalSeconds는 사용자가 호출하여 언제든지 해당 구성 옵션을 변경할 수 있는 해당 set 메서드가 있습니다.

AsyncRetryingExecutor 클래스를 이용한 기하급수적 재시도

RetryDecorator 클래스에서는 재시도 프로세스 구성과 관련해 @ExponentialRetry보다 더 많은 유연성을 제공하지만, 프레임워크에서는 ExponentialRetryPolicy 객체의 현재 구성에 따라 여전히 재시도를 자동으로 실행합니다. 더 유연한 접근 방식은 AsyncRetryingExecutor 클래스를 사용하는 것입니다. 런타임에 재시도 프로세스를 구성할 수 있게 해줄 뿐 아니라 프레임워크에서는 단순히 활동을 실행하는 대신에 사용자 구현 AsyncRunnable.run 메서드를 호출하여 각 재시도를 실행합니다.

기본 패턴은 다음과 같습니다.

  1. 재시도 구성을 지정할 ExponentialRetryPolicy 객체를 만들고 구성합니다.

  2. AsyncRetryingExecutor 객체를 생성하여 이 객체에 ExponentialRetryPolicy 객체와 워크플로 클록의 인스턴스를 전달합니다.

  3. 익명의 중첩된 TryCatch 또는 TryCatchFinally 클래스를 구현합니다.

  4. 익명의 AsyncRunnable 클래스를 구현하고 run 메서드를 재정의하여 활동 실행을 위한 사용자 지정 코드를 구현합니다.

  5. doTry를 재정의하여 AsyncRetryingExecutor 객체의 execute 메서드를 호출한 후 이 메서드에 단계 4의 AsyncRunnable 클래스를 전달합니다. AsyncRetryingExecutor 객체에서는 AsyncRunnable.run을 호출하여 활동을 실행합니다.

  6. 활동이 실패하면 AsyncRetryingExecutor 객체에서는 1단계에서 지정한 재시도 정책에 따라 AsyncRunnable.run 메서드를 다시 호출합니다.

다음 워크플로에서는 AsyncRetryingExecutor 클래스를 사용하여 기하급수적 재시도 전략을 구현하는 방법을 보여줍니다. 이 워크플로에서는 앞서 설명한 DecoratorRetryWorkflow 워크플로 동일한 unreliableActivity 활동을 사용합니다. 이 워크플로 인터페이스는 RetryWorkflow에서 구현되고 이 워크플로의 진입점인 process라는 메서드가 한 개 있습니다. 워크플로 작업자는 AsyncExecutorRetryWorkflowImpl에서 다음과 같이 구현됩니다.

public class AsyncExecutorRetryWorkflowImpl implements RetryWorkflow { private final RetryActivitiesClient client = new RetryActivitiesClientImpl(); private final DecisionContextProvider contextProvider = new DecisionContextProviderImpl(); private final WorkflowClock clock = contextProvider.getDecisionContext().getWorkflowClock(); public void process() { long initialRetryIntervalSeconds = 5; int maximumAttempts = 5; handleUnreliableActivity(initialRetryIntervalSeconds, maximumAttempts); } public void handleUnreliableActivity(long initialRetryIntervalSeconds, int maximumAttempts) { ExponentialRetryPolicy retryPolicy = new ExponentialRetryPolicy(initialRetryIntervalSeconds).withMaximumAttempts(maximumAttempts); final AsyncExecutor executor = new AsyncRetryingExecutor(retryPolicy, clock); new TryCatch() { @Override protected void doTry() throws Throwable { executor.execute(new AsyncRunnable() { @Override public void run() throws Throwable { client.unreliableActivity(); } }); } @Override protected void doCatch(Throwable e) throws Throwable { } }; } }

워크플로는 다음과 같이 작동합니다.

  1. process에서는 handleUnreliableActivity 메서드를 호출한 후 이 메서드에 구성 설정을 전달합니다.

  2. handleUnreliableActivity에서는 1단계의 구성 설정을 사용하여 ExponentialRetryPolicyretryPolicy를 만듭니다.

  3. handleUnreliableActivity에서는 AsyncRetryExecutor 객체인 executor를 생성하여 2단계의 ExponentialRetryPolicy 객체와 워크플로 클록의 인스턴스를 생성자에게 전달합니다.

  4. handleUnreliableActivity에서는 익명의 중첩된 TryCatch 클래스를 구현하고 doTrydoCatch 메서드를 재정의하여 재시도를 실행하고 모든 예외를 처리합니다.

  5. doTry에서는 익명의 AsyncRunnable 클래스를 구현하고 run 메서드를 재정의하여 unreliableActivity 실행을 위한 사용자 지정 코드를 구현합니다. 간소화를 위해 run에서는 활동을 수행할 뿐이지만 사용자는 상황에 따라 적절하게 더 정교한 접근 방식을 구현할 수 있습니다.

  6. doTry에서는 executor.execute를 호출한 후 이 메서드에 AsyncRunnable 객체를 전달합니다. execute에서는 AsyncRunnable 객체의 run 메서드를 호출하여 활동을 실행합니다.

  7. 활동이 실패하면 실행기에서는 retryPolicy 객체 구성에 따라 run을 다시 호출합니다.

TryCatch 클래스를 사용하여 오류를 처리하는 방법에 관한 자세한 내용은 AWS Flow Framework for Java 예외 단원을 참조하십시오.

사용자 지정 재시도 전략

실패한 활동을 재시도하기 위한 가장 유연한 접근 방식은 사용자 지정 전략으로서, 성공할 때까지 재시도하는 전략과 흡사하게 이 전략에서는 재시도를 실행하는 비동기식 메서드를 반복적으로 호출합니다. 그러나 사용자는 단순히 활동을 다시 실행하는 대신에 연속적인 재시도 실행 여부 및 방법을 결정하는 사용자 지정 로직을 구현합니다. 기본 패턴은 다음과 같습니다.

  1. 활동이 실패했는지 여부를 나타내는 데 사용되는 Settable<T> 상태 객체를 생성합니다.

  2. 중첩된 TryCatch 또는 TryCatchFinally 클래스를 구현합니다.

  3. doTry에서는 활동을 실행합니다.

  4. 활동이 실패하면 doCatch에서는 상태 객체가 활동이 실패했음을 나타내도록 설정합니다.

  5. 비동기식 실패 처리 메서드를 호출한 후 이 메서드에 상태 객체를 전달합니다. 이 메서드에서는 TryCatch 또는 TryCatchFinally가 완료될 때까지 실행을 연기합니다.

  6. 실패 처리 메서드에서는 활동을 재시도할지 여부, 그리고 재시도한다면 언제할지 그 시점을 결정합니다.

다음 워크플로에서는 사용자 지정 재시도 전략을 구현하는 방법을 보여줍니다. 이 워크플로에서는 DecoratorRetryWorkflowAsyncExecutorRetryWorkflow 워크플로와 동일한 unreliableActivity 활동을 사용합니다. 이 워크플로 인터페이스는 RetryWorkflow에서 구현되고 이 워크플로의 진입점인 process라는 메서드가 한 개 있습니다. 워크플로 작업자는 CustomLogicRetryWorkflowImpl에서 다음과 같이 구현됩니다.

public class CustomLogicRetryWorkflowImpl implements RetryWorkflow { ... public void process() { callActivityWithRetry(); } @Asynchronous public void callActivityWithRetry() { final Settable<Throwable> failure = new Settable<Throwable>(); new TryCatchFinally() { protected void doTry() throws Throwable { client.unreliableActivity(); } protected void doCatch(Throwable e) { failure.set(e); } protected void doFinally() throws Throwable { if (!failure.isReady()) { failure.set(null); } } }; retryOnFailure(failure); } @Asynchronous private void retryOnFailure(Promise<Throwable> failureP) { Throwable failure = failureP.get(); if (failure != null && shouldRetry(failure)) { callActivityWithRetry(); } } protected Boolean shouldRetry(Throwable e) { //custom logic to decide to retry the activity or not return true; } }

워크플로는 다음과 같이 작동합니다.

  1. process에서는 비동기식 callActivityWithRetry 메서드를 실행합니다.

  2. callActivityWithRetry에서는 활동이 실패했는지 여부를 나타내는 데 사용되는 실패라는 이름의 Settable<Throwable> 객체를 생성합니다. Settable<T>Promise<T>에서 파생된 것으로서 거의 동일한 방식으로 작동하지만, Settable<T> 객체의 값은 사용자가 수동으로 설정해 줍니다.

  3. callActivityWithRetry에서는 익명의 중첩된 TryCatchFinally 클래스를 구현하여 unreliableActivity에서 발생하는 모든 예외를 처리합니다. 비동기식 코드에서 발생하는 예외를 처리하는 방법에 관한 자세한 내용은 AWS Flow Framework for Java 예외 단원을 참조하십시오.

  4. doTry에서는 unreliableActivity를 실행합니다.

  5. unreliableActivity에서 예외가 발생하면 프레임워크에서는 doCatch를 호출하여 예외 객체를 전달합니다. doCatch에서는 failure를 예외 객체로 설정합니다. 이로써 활동이 실패하였음을 나타내고 객체를 준비 상태로 둡니다.

  6. doFinally에서는 failure가 준비 상태인지를 점검합니다. 준비 상태는 failuredoCatch에서 설정한 경우에만 true가 됩니다.

    • failure가 준비 상태인 경우 doFinally는 아무 것도 하지 않습니다.

    • failure가 준비 상태가 아니면 완료된 활동과 doFinally에서는 실패를 null로 설정합니다.

  7. callActivityWithRetry에서는 비동기식 retryOnFailure 메서드를 호출한 후 이 메서드에 실패를 전달합니다. 실패는 Settable<T> 유형이므로 callActivityWithRetry에서는 실패가 준비 상태가 될 때까지 실행을 연기합니다. 실행은 TryCatchFinally가 완료된 후에 이루어집니다.

  8. retryOnFailure에서는 실패에서 값을 가져옵니다.

    • 실패가 null로 설정되어 있으면 재시도가 성공한 것입니다. retryOnFailure는 아무것도 하지 않고, 이로써 재시도 프로세스는 종료됩니다.

    • 실패가 예외 객체로 설정되고 shouldRetry에서 true를 반환하면 retryOnFailure에서는 callActivityWithRetry를 호출하여 활동을 재시도합니다.

      shouldRetry에서는 실패한 활동을 재시도할지 여부를 결정하는 사용자 지정 로직을 구현합니다. 간소화를 위해 shouldRetry에서는 항상 true를 반환하고 retryOnFailure에서는 즉시 활동을 실행하지만 사용자는 필요에 따라 더 정교한 로직을 구현할 수 있습니다.

  9. unreliableActivity가 완료되거나 shouldRetry에서 프로세스를 중단하기로 결정할 때까지 2~8단계가 반복됩니다.

참고

doCatch에서는 재시도 프로세스를 처리하지 않고 단지 활동이 실패하였음을 나타내도록 실패를 설정합니다. 재시도 프로세스는 비동기식 retryOnFailure 메서드에서 처리하는데, 이 메서드에서는 TryCatch가 완료될 때까지 실행을 연기합니다. 이 접근 방식을 사용하는 이유는 doCatch에서 활동을 재시도하면 이를 취소할 수 없기 때문입니다. retryOnFailure에서 활동을 재시도하면 사용자는 취소 가능한 활동을 실행할 수 있습니다.