-
Notifications
You must be signed in to change notification settings - Fork 858
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
Add default retry predicates to user provided ones #5724
Conversation
… user specified predicates. Add a configuration to opt-out, to have the retry strategy use only the use user-provided predicates.
core/aws-core/src/main/java/software/amazon/awssdk/awscore/retry/AwsRetryStrategy.java
Outdated
Show resolved
Hide resolved
...k-core/src/main/java/software/amazon/awssdk/core/internal/retry/SdkDefaultRetryStrategy.java
Outdated
Show resolved
Hide resolved
…elated to default retry predicates in AwsDefaultClientBuilder
...retries/src/main/java/software/amazon/awssdk/retries/internal/DefaultAwareRetryStrategy.java
Outdated
Show resolved
Hide resolved
...retries/src/main/java/software/amazon/awssdk/retries/internal/DefaultAwareRetryStrategy.java
Outdated
Show resolved
Hide resolved
...retries/src/main/java/software/amazon/awssdk/retries/internal/DefaultAwareRetryStrategy.java
Outdated
Show resolved
Hide resolved
...retries/src/main/java/software/amazon/awssdk/retries/internal/DefaultAwareRetryStrategy.java
Outdated
Show resolved
Hide resolved
* Identify the Builder has having the specified set of predicate added to it. | ||
* @param defaultPredicatesName the name of the set of predicate | ||
*/ | ||
default void markDefaultAdded(String defaultPredicatesName) { |
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.
Another option for design might be to model "defaults" explicitly, and make this addDefaults(RetryStrategyDefaults), so that we enforce that defaults are always added before they are marked as added. We may not need shouldAddDefaults
at that point, because the "should I add this?" can be done within the retry strategy and not rely on the caller to make the proper decision.
The drawback for that is that we can't avoid the round-trip to a builder if there are no defaults to be added. Not sure what the cost of that is.
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.
right I see what you mean. The caller would just attempt to add the default every time, which would just be a noop within the retry strategy if those defaults were already added. It's not a big change, I can see the benefit of doing it this way.
…tegyDefaults interface
…' into olapplin/default-retry-predicate
Quality Gate passedIssues Measures |
default void markDefaultAdded(String defaultPredicatesName) { | ||
|
||
} | ||
void markDefaultAdded(String defaultPredicatesName); |
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.
Is this method needed anymore?
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.
It is if we want to avoid having the core retry classes reference BaseRetryStrategy
like you proposed eariler, which I think is the better approach. For example, AwsRetryStrategy
needs to be able to mark defaults as being added when instantiated directly, to not duplicate them when the default client builder tries to add them later at client build time.
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.
Got it, I imagined AwsRetryStrategy
using addDefaults
on instantiation to ensure they're marked as already included. I can see why that's weird now. For some reason I also imagined addDefaults
being on the builder, not on the retry strategy itself.
/** | ||
* @return The unique name that identifies this set of predicates | ||
*/ | ||
String name(); |
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.
If we implement equals()
and hashCode()
, we don't even need name()
.
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.
mmmhh, Implementations of this interface have no fields, there is nothing to compare to for equals and hash code. We could make the implementations not anonymous and used their name, is that what you're proposing? For SdkDefaultRetryStrategy
it would be something like:
private static final class SdkRetryStrategyDefaults implements RetryStrategyDefaults {
@Override
public void applyDefaults(RetryStrategy.Builder<?, ?> builder) {
configureStrategy(builder);
markDefaultsAdded(builder);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
return o != null && getClass() == o.getClass();
}
@Override
public int hashCode() {
return getClass().getName().hashCode();
}
}
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.
That or just use identity equality and singletons, but I suppose that names are less opaque.
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.
I think I slightly prefer singleton and identity, lets got with that. We wouldn't need to implement hashCode and equals then.
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.
changed my mind, lets just keep name()
, it's simpler
@@ -66,6 +71,8 @@ public abstract class BaseRetryStrategy implements RetryStrategy { | |||
this.treatAsThrottling = Validate.paramNotNull(builder.treatAsThrottling, "treatAsThrottling"); | |||
this.exceptionCost = Validate.paramNotNull(builder.exceptionCost, "exceptionCost"); | |||
this.tokenBucketStore = Validate.paramNotNull(builder.tokenBucketStore, "tokenBucketStore"); | |||
this.defaultsAdded = Validate.paramNotNull(builder.defaultsAdded, "defaultsAdded"); |
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.
You need to copy the set here instead of using the same as the builder, or, better yet, copy and pass it trough Collections.unmodifiableSet
. Otherwise you end up sharing state that you shouldn't. For instance:
RetryStategy.Builder builder = standardRetryStrategy().toBuilder();
addSomeFooDefaults(builder);
RetryStategy strategyA = builder.build();
addSomeBarDefaults(builder);
RetryStategy strategyB = builder.build();
After this, both, strategyA
and strategyB
think they have both, Foo
and Bar
defaults whereas only strategyA
does.
Add default retry predicates to retry strategies on top of user provided predicates.
Motivation and Context
Currently, the SDK will only add default retry predicates when user do not specified any, effectively overriding defaults whenever a single other predicate is defined by user.
Modifications
boolean useClientDefaults()
method has been added to the RetryStrategy and builder interface to check whether this strategy should add the default predicates or not.DefaultAwsClientBuilderTest
to junit 5Testing
Added unit tests
Types of changes