-
Notifications
You must be signed in to change notification settings - Fork 2.2k
5945 retrypolicy response headers #6196
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
5945 retrypolicy response headers #6196
Conversation
sdk/core/azure-core/src/main/java/com/azure/core/http/policy/RetryPolicy.java
Outdated
Show resolved
Hide resolved
sdk/core/azure-core/src/main/java/com/azure/core/http/HttpHeaderName.java
Outdated
Show resolved
Hide resolved
| */ | ||
| public RetryPolicy(RetryStrategy retryStrategy, HttpHeaderName retryAfterHeader) { | ||
| this.retryStrategy = Objects.requireNonNull(retryStrategy, "'retryStrategy' cannot be null"); | ||
| this.retryAfterHeader = Objects.requireNonNull(retryAfterHeader, "'retryAfterHeader' cannot be null"); |
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.
This can be null. If the header is not provided, then the retry strategy will be used to determine the delay. If provided, the delay will be determined based on the header value. Also, you will need the TimeUnit as well. Can't assume the unit is always milliseconds. For e.g. the default HTTP header Retry-After returns delay in seconds.
| String retryHeaderValue = null; | ||
|
|
||
| if (!isNullOrEmpty(retryAfterHeader)) { | ||
| retryHeaderValue = response.getHeaderValue(retryAfterHeader); |
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.
retryAfterHeader : This could be null when user do not want to use any response header for retry.
| this.retryAfterTimeUnit = retryAfterTimeUnit; | ||
| if (!isNullOrEmpty(retryAfterHeader)) { | ||
| Objects.requireNonNull(retryAfterTimeUnit, "'retryAfterTimeUnit' cannot be null."); | ||
| } |
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.
retryAfterHeader : This could be null when user do not want to use any response header for retry. This is change of behavior from GA release, In GA we check for value of header 'retry-after-ms' by default. This is discussed with Srikanta
sdk/core/azure-core/src/main/java/com/azure/core/http/HttpHeaders.java
Outdated
Show resolved
Hide resolved
sdk/core/azure-core/src/main/java/com/azure/core/http/policy/RetryPolicy.java
Outdated
Show resolved
Hide resolved
sdk/core/azure-core/src/main/java/com/azure/core/http/policy/RetryPolicy.java
Outdated
Show resolved
Hide resolved
sdk/core/azure-core/src/main/java/com/azure/core/http/policy/RetryPolicy.java
Outdated
Show resolved
Hide resolved
sdk/core/azure-core/src/main/java/com/azure/core/http/HttpHeaders.java
Outdated
Show resolved
Hide resolved
sdk/core/azure-core/src/main/java/com/azure/core/http/HttpHeaders.java
Outdated
Show resolved
Hide resolved
sdk/core/azure-core/src/main/java/com/azure/core/http/policy/RetryPolicy.java
Outdated
Show resolved
Hide resolved
|
just brain storming: what do you guys think about offloading the entire retry delay computation logic to strategies? Instead of adding more Ctrs overloads to RetryPolicy. Something like: public interface RetryStrategy {
default Duration Duration calculateRetryDelay(HttpResponse httpResponse, int retryAttempts) {
// Look up RFC defined and Azure well known heades such as:
// retry-after-ms, x-ms-retry-after-ms in a specific order that is agreed across SDKS
//
// case1: there is retry header
Duration delay = httpResponse.headers.get('retry-after-ms') | httpResponse.headers.get('x-ms-retry-after-ms')
return delay;
// case 2: there is no retry header
return calculateRetryDelay(retryAttempts);
}
Duration calculateRetryDelay(int retryAttempts);
}This way, if someone want customization, they could override |
|
Hi guys, Currently The proposed change appends the new header in addition to the legacy one in order to maintain a backwards compatibility. This way tracing will start working. // Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
package com.azure.core.http.policy;
import com.azure.core.http.HttpPipelineCallContext;
import com.azure.core.http.HttpPipelineNextPolicy;
import com.azure.core.http.HttpResponse;
import reactor.core.publisher.Mono;
import java.util.UUID;
/**
* The pipeline policy that puts a UUID in the request header. Azure uses the request id as
* the unique identifier for the request.
*/
public class RequestIdPolicy implements HttpPipelinePolicy {
private static final String REQUEST_ID_HEADER = "client-request-id";
private static final String LEGACY_REQUEST_ID_HEADER = "x-ms-client-request-id";
@Override
public Mono<HttpResponse> process(HttpPipelineCallContext context, HttpPipelineNextPolicy next) {
String requestId = context.getHttpRequest().getHeaders().getValue(REQUEST_ID_HEADER);
if (requestId == null) {
String randomUUID = UUID.randomUUID().toString();
context.getHttpRequest().getHeaders().put(REQUEST_ID_HEADER, randomUUID);
//also set the legacy header for backwards compatibility.
context.getHttpRequest().getHeaders().put(LEGACY_REQUEST_ID_HEADER, randomUUID);
}
return next.process();
}
}Edit: |
sdk/core/azure-core/src/main/java/com/azure/core/http/policy/RetryPolicy.java
Outdated
Show resolved
Hide resolved
sdk/core/azure-core/src/main/java/com/azure/core/http/policy/RetryPolicy.java
Outdated
Show resolved
Hide resolved
sdk/core/azure-core/src/main/java/com/azure/core/http/policy/RetryPolicyOptions.java
Outdated
Show resolved
Hide resolved
sdk/core/azure-core/src/main/java/com/azure/core/http/policy/RetryPolicyOptions.java
Outdated
Show resolved
Hide resolved
...pconfiguration/src/main/java/com/azure/data/appconfiguration/ConfigurationClientBuilder.java
Outdated
Show resolved
Hide resolved
sdk/core/azure-core/src/main/java/com/azure/core/http/policy/RetryPolicy.java
Outdated
Show resolved
Hide resolved
...pconfiguration/src/main/java/com/azure/data/appconfiguration/ConfigurationClientBuilder.java
Outdated
Show resolved
Hide resolved
...pconfiguration/src/main/java/com/azure/data/appconfiguration/ConfigurationClientBuilder.java
Outdated
Show resolved
Hide resolved
| public RetryPolicyOptions(RetryStrategy retryStrategy, String retryAfterHeader, ChronoUnit retryAfterTimeUnit) { | ||
|
|
||
| if (Objects.isNull(retryStrategy)) { | ||
| this.retryStrategy = new ExponentialBackoff(); |
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.
This overload should throw NPE if retryStrategy is null.
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 tried to avoid many variations on constructor. Strategy cannot be null, Thus defaulting to ExponentialBackoff . Following constructor was removed.
public RetryPolicyOptions( String retryAfterHeader, ChronoUnit retryAfterTimeUnit) ;
trying to manage between many variations in constructor or few constructor.
sdk/core/azure-core/src/main/java/com/azure/core/http/policy/RetryPolicyOptions.java
Outdated
Show resolved
Hide resolved
|
I realise this has already been merged, but I'm not convinced of the value of the RetryPolicyOptions type. It seems to present more API complexity for not much more gain - unless I'm missing something? |
|
@hemanttanwar I'm keen to discuss the comment I raised yesterday. Is there an argument for the RetryPolicyOptions type? |
|
bringing up: #6196 (comment) |
|
My proposal earlier was: Offload the entire retry delay computation logic to strategies Instead of adding more Ctrs overloads to RetryPolicy. Something like: public interface RetryStrategy {
default Duration Duration calculateRetryDelay(HttpResponse httpResponse, int retryAttempts) {
// Look up RFC defined and Azure well known heades such as:
// retry-after-ms, x-ms-retry-after-ms in a specific order that is agreed across SDKS
//
// case1: there is retry header
Duration delay = httpResponse.headers.get('retry-after-ms') | httpResponse.headers.get('x-ms-retry-after-ms')
return delay;
// case 2: there is no retry header
return calculateRetryDelay(retryAttempts);
}
Duration calculateRetryDelay(int retryAttempts);
}This way, if someone want customization, they could override \cc @srnagar |
|
basically any method in RetryPolicy DEFAULT_RETRY_POLICY = new RetryPolicy(new ExponentialBackoff() {
@Override
public Duration calculateRetryDelay(HttpResponse httpResponse, int retryAttempts)) {
String delay = httpResponse.getHeaderValue("retry-after-ms");
if (delay != null) {
return Duration.ofMillis(Long.parseLong(delay));
} else {
return calculateRetryDelay(retryAttempts);
}
}
});
policies.add(retryPolicy == null ? DEFAULT_RETRY_POLICY : retryPolicy);
policies.addAll(this.policies);
HttpPolicyProviders.addAfterRetryPolicies(policies); |
|
I like @anuchandy 's proposed suggestion. Maybe opening up an issue so this doesn't get lost in this merged PR. |
|
sure, created an issue #6363 to triage. |
Currently, RetryPolicy uses retry-after-ms to determine the delay duration. However, different Azure services return the delay duration in different response headers.
So, we should look into supporting different headers for delay duration.
For e.g. AppConfig uses retry-after-ms while CosmosDB uses x-ms-retry-after-ms.
RetryPolicy should also allow a customized list of HTTP status codes that are retryable.
#5945
Fixes #5945