最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c# - Preventing existing polly policy from being invoked for certain results - Stack Overflow

programmeradmin5浏览0评论

I have a predefined IAsyncPolicy<HttpResponseMessage> policy coming from an external assembly. I want to apply this policy to a Http Client, BUT I want to exclude one of the cases this policy typically handles.

Take the example below:

  • I cannot influence how the baseline policy is created (external library)
  • I need to wire things up so that this policy is NOT invoked if the http client returns StatusCode.Forbidden

How can I do this?

 void Configure(IHttpClientBuilder builder)
 {
   var policy = GetBaselinePolicy();

   // TODO: Do something here to *not* have policy handle HttpStatusCode.Forbidden.. only what?

   builder.AddPolicyHandler(policy);
 }

 // Assume you CANNOT change this function here
 IAsyncPolicy<HttpResponseMessage> GetBaselinePolicy() {
   return Policy<HttpResponseMessage>
     .HandleResult(x => x.StatusCode is HttpStatusCode.Forbidden or HttpStatusCode.Gone)
     .WaitAndRetryForeverAsync(_ => TimeSpan.FromSeconds(1));
 }

I've found Policy.WrapAsync, but best from what I've seen so far, this unconitionally chains policies, i.e. one way or the other the call would find its way to the baseline policy and be retried there forever.

I have a predefined IAsyncPolicy<HttpResponseMessage> policy coming from an external assembly. I want to apply this policy to a Http Client, BUT I want to exclude one of the cases this policy typically handles.

Take the example below:

  • I cannot influence how the baseline policy is created (external library)
  • I need to wire things up so that this policy is NOT invoked if the http client returns StatusCode.Forbidden

How can I do this?

 void Configure(IHttpClientBuilder builder)
 {
   var policy = GetBaselinePolicy();

   // TODO: Do something here to *not* have policy handle HttpStatusCode.Forbidden.. only what?

   builder.AddPolicyHandler(policy);
 }

 // Assume you CANNOT change this function here
 IAsyncPolicy<HttpResponseMessage> GetBaselinePolicy() {
   return Policy<HttpResponseMessage>
     .HandleResult(x => x.StatusCode is HttpStatusCode.Forbidden or HttpStatusCode.Gone)
     .WaitAndRetryForeverAsync(_ => TimeSpan.FromSeconds(1));
 }

I've found Policy.WrapAsync, but best from what I've seen so far, this unconitionally chains policies, i.e. one way or the other the call would find its way to the baseline policy and be retried there forever.

Share Improve this question edited Apr 1 at 18:25 Peter Csala 22.9k16 gold badges48 silver badges93 bronze badges asked Apr 1 at 11:42 BogeyBogey 5,8045 gold badges36 silver badges75 bronze badges 1
  • Did my proposed solution work for you? – Peter Csala Commented 2 days ago
Add a comment  | 

1 Answer 1

Reset to default 0

You can basically early exit with a fallback policy

IAsyncPolicy<HttpResponseMessage> GetEarlyExitPolicy()
=> Policy<HttpResponseMessage>
         .HandleResult(x => x.StatusCode is HttpStatusCode.Forbidden)
         .FallbackAsync(_ => Task.FromResult(new HttpResponseMessage((HttpStatusCode)0));

So, whenever you receive a Forbidden then you change the original result with a bogus one. The status code is intentionally out of the normal range to ease the detection.

Here is a working example:

public class Program
{
    public static async Task Main()
    {
        var x = Policy.WrapAsync(GetBaselinePolicy(), GetEarlyExitPolicy());
        var res = await x.ExecuteAsync(() => Task.FromResult(new HttpResponseMessage(HttpStatusCode.Forbidden)));
        res.Dump();
    }
    
    static IAsyncPolicy<HttpResponseMessage> GetBaselinePolicy() {
       return Policy<HttpResponseMessage>
         .HandleResult(x => x.StatusCode is HttpStatusCode.Forbidden or HttpStatusCode.Gone)
         .WaitAndRetryForeverAsync(_ => { "retry".Dump(); return TimeSpan.FromSeconds(1);});
    }
    
    static IAsyncPolicy<HttpResponseMessage> GetEarlyExitPolicy() {
       return Policy<HttpResponseMessage>
         .HandleResult(x => x.StatusCode is HttpStatusCode.Forbidden)
         .FallbackAsync(_ => { "fallback".Dump(); return Task.FromResult(new HttpResponseMessage((HttpStatusCode)0)); });
    }
}
发布评论

评论列表(0)

  1. 暂无评论