-
Notifications
You must be signed in to change notification settings - Fork 950
Add perMethod
, perHost
, perPath
and builder to RetryConfigMapping
#6243
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
base: main
Are you sure you want to change the base?
Add perMethod
, perHost
, perPath
and builder to RetryConfigMapping
#6243
Conversation
d338fc6
to
087b025
Compare
After the main part of the review I will add the javadocs :) |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #6243 +/- ##
============================================
+ Coverage 74.46% 74.69% +0.23%
- Complexity 22234 22546 +312
============================================
Files 1963 1976 +13
Lines 82437 83184 +747
Branches 10764 10821 +57
============================================
+ Hits 61385 62135 +750
+ Misses 15918 15897 -21
- Partials 5134 5152 +18 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
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 do think RetryConfig#noRetry
will be useful, and I also appreciate the extensive test coverage.
Left a comment on APIs added to RetryConfigMapping
static <T extends Response> RetryConfigMappingBuilder<T> builder() { | ||
return new RetryConfigMappingBuilder<>(); | ||
} |
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.
Thanks for the initiative. I agree intuitively, it makes sense that retry and circuitbreaker share similar APIs.
Having said this, I do think retry is a little different from circuitbreaker in the sense that CircuitBreaker
share a common mutable configuration across requests. For this reason, a mapping
structure is used to cache the CircuitBreaker
s used per host/method/path.
On the other hand, RetryConfig
is an immutable object which decides how each request will be retried (in case there is a retry). Hence, there is no real reason we should be caching the returned RetryConfig
s. It may be worth checking the discussion at #3145 as well.
I do think there is value in pre-parsing method/host/path parameters so that users don't have to extract each value from the ctx
though.
e.g.
static <T extends Response> RetryConfigMapping<T> of(RetryConfigFactory<T> retryConfigFactory) {
}
I'm not sure of the usefulness of the builder()
or per*()
apis though since users can simply choose to ignore certain fields of the RetryConfigFactory
anyways.
e.g. users can simply choose not to use the path
RetryConfigMapping.of((host, method, path) -> {
if ("asdf".equals(host)) {
return RetryConfig.noRetry();
}
...
});
Let me know what you think.
cc. other maintainers @line/dx
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.
Thanks for your review @jrhee17.
On the other hand, RetryConfig is an immutable object which decides how each request will be retried (in case there is a retry). Hence, there is no real reason we should be caching the returned RetryConfigs.
Ah, so you're effectively saying that RetryConfigMapping
doesn't necessarily need a keyFactory
in RetryConfigMapping.of
:
static <T extends Response> RetryConfigMapping<T> of(
BiFunction<? super ClientRequestContext, Request, String> keyFactory, // Could be removed and we could just recreate the `RetryConfig`s for every request as they are immutable.
BiFunction<? super ClientRequestContext, Request, RetryConfig<T>> retryConfigFactory) {
return new KeyedRetryConfigMapping<>(keyFactory, retryConfigFactory);
}
and that we could offer an "uncached" version like:
// Returns a mapping that regenerates the `RetryConfig` on every request. Would not work with
// `CircuitBreaker`s, as multiple requests hitting the same host may need to mutate the same
// `CircuitBreaker`.
static <T extends Response> RetryConfigMapping<T> of(
BiFunction<? super ClientRequestContext, Request, RetryConfig<T>> retryConfigFactory) {
return new KeyedRetryConfigMapping<>(retryConfigFactory);
}
Since this API is not currently offered, and because RetryConfigMapping mentions caching twice, I assumed there was a performance reason for caching — for example, reducing GC pressure or handling expensive factory methods.
If it’s just for ergonomics, I like your suggestion as it avoids specifying the keyFactory
. However, given that we already cache in KeyedRetryConfigMapping
, and considering that we have CircuitBreakerMapping
alongside it, I would lean towards using a per*-style approach.
I'm also happy to hear input from the other maintainers.
Motivation:
The motivation of this PR is explained in the associated issue.
Modifications:
perMethod
,perHost
,perPath
andperHostAndMethod
toRetryConfigMapping
to enable retry configuration on a per method, host and path basis. This API is analogous toCircuitBreakerMapping
.RetryConfig.noRetry
for being more concise when signalling that no retry is expected, especially in theper*
methods.RetryConfigMapping.builder
andRetryConfigMappingBuilder
. This API is analogous toCircuitBreakerMappingBuilder
.CircuitBreakerMappingUtil
toRequestContextUtil
RetryConfigMapping
Result:
RetryConfigMapping
on a per method, path, or host basis #6242RetryConfigMapping.of
is deprecated.