Skip to content
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

[Question]: How to define a Policy per HttpMessage Method Type (GET, POST etc.) #2403

Closed
sndpyadav34 opened this issue Nov 22, 2024 · 4 comments
Labels
question stale Stale issues or pull requests

Comments

@sndpyadav34
Copy link

What are you wanting to achieve?

I have a common HttpClient that is used or sending multiple requests like GET, POST, PUT etc. I am trying to configure different retry behavior for GET versus POST/PUT calls. Basically I am trying to configure a timeout per retry behavior for GET calls and a transient error behavior for POST/PUT calls.

What code or approach do you have so far?

I defined following two policies. policy1 handles the result of GET requests and handles the TimeoutRejectedException
along with transient errors whereas policy2 handles transient errors for requests other than GET. I then wrap both policies.

Random jitterer = new Random();
 
var policy1 = Polly.Policy
        .HandleResult<HttpResponseMessage>(req => req.RequestMessage.Method == HttpMethod.Get)
        .OrTransientHttpError()
        .Or<BrokenCircuitException>()
        .Or<TimeoutRejectedException>()
        .WaitAndRetryAsync(3,
        sleepDurationProvider: (retryAttempt, ctx) =>
        {
            return TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))
                        + TimeSpan.FromMilliseconds(jitterer.Next(1000, 3000));
        },
        onRetry: (outcome, timespan, retryAttempt, context) =>
        {
            //LogRetry(services, outcome, timespan, retryAttempt, context);
        });
 
var policy2 = Polly.Policy
        .HandleResult<HttpResponseMessage>(req => req.RequestMessage.Method != HttpMethod.Get)
        .OrTransientHttpError()
        .Or<BrokenCircuitException>()
        .WaitAndRetryAsync(3,
        sleepDurationProvider: (retryAttempt, ctx) =>
        {
            return TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))
                        + TimeSpan.FromMilliseconds(jitterer.Next(1000, 3000));
        },
        onRetry: (outcome, timespan, retryAttempt, context) =>
        {
            //LogRetry(services, outcome, timespan, retryAttempt, context);
        });
 
var combinedPolicy = Polly.Policy.WrapAsync(policy1, policy2);

And then while registering the HttpClient I add the retry policy handlers as below:

services.AddHttpClient<IPlatformHttpClient, PlatformHttpClient>()
    .AddPolicyHandler(combinedPolicy)
    .AddPolicyHandler(GetCircuitBreakerPolicy())
    .AddPolicyHandler(Polly.Policy.TimeoutAsync<HttpResponseMessage>(5));

However, with the policies configured like this, I see retries happening for both GET and POST requests. I think it's because of the timeout policy around the HttpClient. Not sure if it's possible to define on a single client like this.

Additional context

No response

@martincostello
Copy link
Member

Here's some code that uses different policies depending on the HTTP method.

Two different policies are added to a policy registry, one for "reads" and one for "writes": https://github.com/martincostello/alexa-london-travel-site/blob/5dc4c38445a6d7e1bb445898f5523b8b5f94eb0f/src/LondonTravel.Site/Extensions/PollyServiceCollectionExtensions.cs

The appropriate policy is then obtained from the registry based on the HTTP method of the current request: https://github.com/martincostello/alexa-london-travel-site/blob/0a6829fc01976f673cf9f26bcbf0dae36d72199a/src/LondonTravel.Site/Extensions/IHttpClientBuilderExtensions.cs#L90

@peter-csala
Copy link
Contributor

Side note

The AddPolicyHandler call registers a PolicyHttpMessageHandler which is a DelegatingHandler. I would suggest to combine all your policies into a single Policy.WrapAsync and register only a single DelegatingHandler instead of three.

.AddPolicyHandler(Policy.WrapAsync(retryForGet, retryForNonGet, circuitBreaker, perRequestTimeout));

Copy link
Contributor

This issue is stale because it has been open for 60 days with no activity. It will be automatically closed in 14 days if no further updates are made.

@github-actions github-actions bot added the stale Stale issues or pull requests label Jan 22, 2025
Copy link
Contributor

github-actions bot commented Feb 6, 2025

This issue was closed because it has been inactive for 14 days since being marked as stale.

@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale Feb 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question stale Stale issues or pull requests
Projects
None yet
Development

No branches or pull requests

3 participants