-
Notifications
You must be signed in to change notification settings - Fork 915
Add standard retry strategy #3931
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -41,7 +41,10 @@ | |
*/ | ||
@ThreadSafe | ||
@SdkPublicApi | ||
public interface RetryStrategy extends ToCopyableBuilder<RetryStrategy.Builder, RetryStrategy> { | ||
public interface RetryStrategy< | ||
B extends CopyableBuilder<B, T> & RetryStrategy.Builder<B, T>, | ||
T extends ToCopyableBuilder<B, T> & RetryStrategy<B, T>> | ||
extends ToCopyableBuilder<B, T> { | ||
/** | ||
* Invoked before the first request attempt. | ||
* | ||
|
@@ -86,36 +89,39 @@ public interface RetryStrategy extends ToCopyableBuilder<RetryStrategy.Builder, | |
* <p>This is useful for modifying the strategy's behavior, like conditions or max retries. | ||
*/ | ||
@Override | ||
Builder toBuilder(); | ||
B toBuilder(); | ||
|
||
/** | ||
* Builder to create immutable instances of {@link RetryStrategy}. | ||
*/ | ||
interface Builder extends CopyableBuilder<Builder, RetryStrategy> { | ||
interface Builder< | ||
B extends Builder<B, T> & CopyableBuilder<B, T>, | ||
T extends ToCopyableBuilder<B, T> & RetryStrategy<B, T>> | ||
extends CopyableBuilder<B, T> { | ||
/** | ||
* Configure the strategy to retry when the provided predicate returns true, given a failure exception. | ||
*/ | ||
Builder retryOnException(Predicate<Throwable> shouldRetry); | ||
B retryOnException(Predicate<Throwable> shouldRetry); | ||
|
||
/** | ||
* Configure the strategy to retry when a failure exception class is equal to the provided class. | ||
*/ | ||
default Builder retryOnException(Class<? extends Throwable> throwable) { | ||
default B retryOnException(Class<? extends Throwable> throwable) { | ||
return retryOnException(t -> t.getClass() == throwable); | ||
} | ||
|
||
/** | ||
* Configure the strategy to retry when a failure exception class is an instance of the provided class (includes | ||
* subtypes). | ||
*/ | ||
default Builder retryOnExceptionInstanceOf(Class<? extends Throwable> throwable) { | ||
default B retryOnExceptionInstanceOf(Class<? extends Throwable> throwable) { | ||
return retryOnException(t -> throwable.isAssignableFrom(t.getClass())); | ||
} | ||
|
||
/** | ||
* Configure the strategy to retry when a failure exception or one of its cause classes is equal to the provided class. | ||
*/ | ||
default Builder retryOnExceptionOrCause(Class<? extends Throwable> throwable) { | ||
default B retryOnExceptionOrCause(Class<? extends Throwable> throwable) { | ||
return retryOnException(t -> { | ||
if (t.getClass() == throwable) { | ||
return true; | ||
|
@@ -135,7 +141,7 @@ default Builder retryOnExceptionOrCause(Class<? extends Throwable> throwable) { | |
* Configure the strategy to retry when a failure exception or one of its cause classes is an instance of the provided | ||
* class (includes subtypes). | ||
*/ | ||
default Builder retryOnExceptionOrCauseInstanceOf(Class<? extends Throwable> throwable) { | ||
default B retryOnExceptionOrCauseInstanceOf(Class<? extends Throwable> throwable) { | ||
return retryOnException(t -> { | ||
if (throwable.isAssignableFrom(t.getClass())) { | ||
return true; | ||
|
@@ -155,7 +161,7 @@ default Builder retryOnExceptionOrCauseInstanceOf(Class<? extends Throwable> thr | |
* Configure the strategy to retry the root cause of a failure (the final cause) a failure exception is equal to the | ||
* provided class. | ||
*/ | ||
default Builder retryOnRootCause(Class<? extends Throwable> throwable) { | ||
default B retryOnRootCause(Class<? extends Throwable> throwable) { | ||
return retryOnException(t -> { | ||
boolean shouldRetry = false; | ||
Throwable cause = t.getCause(); | ||
|
@@ -171,7 +177,7 @@ default Builder retryOnRootCause(Class<? extends Throwable> throwable) { | |
* Configure the strategy to retry the root cause of a failure (the final cause) a failure exception is an instance of to | ||
* the provided class (includes subtypes). | ||
*/ | ||
default Builder retryOnRootCauseInstanceOf(Class<? extends Throwable> throwable) { | ||
default B retryOnRootCauseInstanceOf(Class<? extends Throwable> throwable) { | ||
return retryOnException(t -> { | ||
boolean shouldRetry = false; | ||
Throwable cause = t.getCause(); | ||
|
@@ -191,17 +197,12 @@ default Builder retryOnRootCauseInstanceOf(Class<? extends Throwable> throwable) | |
* | ||
* <p>The default value for the standard and adaptive retry strategies is 3. | ||
*/ | ||
Builder maxAttempts(int maxAttempts); | ||
|
||
/** | ||
* Configure the predicate to allow the strategy categorize a Throwable as throttling exception. | ||
*/ | ||
Builder treatAsThrottling(Predicate<Throwable> treatAsThrottling); | ||
Comment on lines
-194
to
-199
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is only needed for |
||
B maxAttempts(int maxAttempts); | ||
|
||
/** | ||
* Build a new {@link RetryStrategy} with the current configuration on this builder. | ||
*/ | ||
@Override | ||
RetryStrategy build(); | ||
T build(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
/* | ||
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"). | ||
* You may not use this file except in compliance with the License. | ||
* A copy of the License is located at | ||
* | ||
* http://aws.amazon.com/apache2.0 | ||
* | ||
* or in the "license" file accompanying this file. This file is distributed | ||
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either | ||
* express or implied. See the License for the specific language governing | ||
* permissions and limitations under the License. | ||
*/ | ||
|
||
package software.amazon.awssdk.retries.api.internal; | ||
|
||
import software.amazon.awssdk.annotations.SdkInternalApi; | ||
import software.amazon.awssdk.retries.api.AcquireInitialTokenRequest; | ||
import software.amazon.awssdk.utils.Validate; | ||
|
||
/** | ||
* Implementation of the {@link AcquireInitialTokenRequest} interface. | ||
*/ | ||
@SdkInternalApi | ||
public final class AcquireInitialTokenRequestImpl implements AcquireInitialTokenRequest { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added this implementation here in the SPI package as decided in a previous review. See the decision log here. |
||
|
||
private final String scope; | ||
|
||
private AcquireInitialTokenRequestImpl(String scope) { | ||
this.scope = Validate.paramNotNull(scope, "scope"); | ||
} | ||
|
||
@Override | ||
public String scope() { | ||
return scope; | ||
} | ||
|
||
/** | ||
* Creates a new {@link AcquireInitialTokenRequestImpl} instance with the given scope. | ||
*/ | ||
public static AcquireInitialTokenRequest create(String scope) { | ||
return new AcquireInitialTokenRequestImpl(scope); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
/* | ||
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"). | ||
* You may not use this file except in compliance with the License. | ||
* A copy of the License is located at | ||
* | ||
* http://aws.amazon.com/apache2.0 | ||
* | ||
* or in the "license" file accompanying this file. This file is distributed | ||
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either | ||
* express or implied. See the License for the specific language governing | ||
* permissions and limitations under the License. | ||
*/ | ||
|
||
package software.amazon.awssdk.retries.api.internal; | ||
|
||
import java.time.Duration; | ||
import software.amazon.awssdk.annotations.SdkInternalApi; | ||
import software.amazon.awssdk.retries.api.AcquireInitialTokenResponse; | ||
import software.amazon.awssdk.retries.api.RetryToken; | ||
import software.amazon.awssdk.utils.Validate; | ||
|
||
/** | ||
* Implementation of the {@link AcquireInitialTokenResponse} interface. | ||
*/ | ||
@SdkInternalApi | ||
public final class AcquireInitialTokenResponseImpl implements AcquireInitialTokenResponse { | ||
private final RetryToken token; | ||
private final Duration delay; | ||
|
||
private AcquireInitialTokenResponseImpl(RetryToken token, Duration delay) { | ||
this.token = Validate.paramNotNull(token, "token"); | ||
this.delay = Validate.paramNotNull(delay, "delay"); | ||
} | ||
|
||
@Override | ||
public RetryToken token() { | ||
return token; | ||
} | ||
|
||
@Override | ||
public Duration delay() { | ||
return delay; | ||
} | ||
|
||
/** | ||
* Creates a new {@link AcquireInitialTokenResponseImpl} instance with the given token and suggested delay values. | ||
*/ | ||
public static AcquireInitialTokenResponse create(RetryToken token, Duration delay) { | ||
return new AcquireInitialTokenResponseImpl(token, delay); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need this to be able to have to different classes extending from the builder and keep the ability to chain the builder calls.