HttpClient Decorator Pattern Scenarios

This page captures practical runtime scenarios harvested from the legacy demo and mapped to the current package-first API surface.

Resilience Configuration with Seconds-Based Aliases

The current package supports both TimeSpan-style settings and legacy seconds-based aliases under HttpRequestResultPollyOptions.

{
  "HttpRequestResultPollyOptions": {
    "MaxRetryAttempts": 3,
    "RetryDelaySeconds": 1,
    "CircuitBreakerThreshold": 5,
    "CircuitBreakerDurationSeconds": 30
  }
}

Equivalent TimeSpan form:

{
  "HttpRequestResultPollyOptions": {
    "MaxRetryAttempts": 3,
    "RetryDelay": "00:00:01",
    "CircuitBreakerThreshold": 5,
    "CircuitBreakerDuration": "00:00:30"
  }
}

Circuit Breaker Scenario

builder.Services.AddHttpClientUtility(options =>
{
    options.EnableResilience = true;
    options.ResilienceOptions.MaxRetryAttempts = 3;
    options.ResilienceOptions.CircuitBreakerThreshold = 5;
    options.ResilienceOptions.CircuitBreakerDuration = TimeSpan.FromSeconds(30);
});

var result = await httpService.HttpSendRequestResultAsync(new HttpRequestResult<StatusPayload>
{
    RequestPath = "https://api.example.com/status",
    RequestMethod = HttpMethod.Get
});

if (!result.IsSuccessStatusCode)
{
    logger.LogWarning("Request failed with {StatusCode}; retries applied by Polly", result.StatusCode);
}

Concurrent Calls Scenario

using WebSpark.HttpClientUtility.Concurrent;

var requests = new List<HttpRequestResult<ApiResult>>
{
    new() { RequestPath = "https://api.example.com/a", RequestMethod = HttpMethod.Get },
    new() { RequestPath = "https://api.example.com/b", RequestMethod = HttpMethod.Get },
    new() { RequestPath = "https://api.example.com/c", RequestMethod = HttpMethod.Get }
};

var concurrent = serviceProvider.GetRequiredService<IConcurrentHttpRequestResultService>();
var responses = await concurrent.ProcessRequestListAsync(requests, maxConcurrentRequests: 3);

Notes