littleshop/LittleShop.Client/Http/RetryPolicyHandler.cs
sysadmin 1f7c0af497 Add LittleShop.Client SDK library with complete API wrapper
Features:
- Complete .NET client SDK for LittleShop API
- JWT authentication with automatic token management
- Catalog service for products and categories
- Order service with payment creation
- Retry policies using Polly for resilience
- Error handling middleware
- Dependency injection support
- Comprehensive documentation and examples

SDK Components:
- Authentication service with token refresh
- Strongly-typed models for all API responses
- HTTP handlers for retry and error handling
- Extension methods for easy DI registration
- Example console application demonstrating usage

Test Updates:
- Fixed test compilation errors
- Updated test data builders for new models
- Corrected service constructor dependencies
- Fixed enum value changes (PaymentStatus, OrderStatus)

Documentation:
- Complete project README with features and usage
- Client SDK README with detailed examples
- API endpoint documentation
- Security considerations
- Deployment guidelines

Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-20 18:15:35 +01:00

39 lines
1.4 KiB
C#

using System.Net;
using Microsoft.Extensions.Logging;
using Polly;
using Polly.Extensions.Http;
namespace LittleShop.Client.Http;
public class RetryPolicyHandler : DelegatingHandler
{
private readonly ILogger<RetryPolicyHandler> _logger;
private readonly IAsyncPolicy<HttpResponseMessage> _retryPolicy;
public RetryPolicyHandler(ILogger<RetryPolicyHandler> logger, int maxRetryAttempts = 3)
{
_logger = logger;
_retryPolicy = HttpPolicyExtensions
.HandleTransientHttpError()
.OrResult(msg => !msg.IsSuccessStatusCode && msg.StatusCode != HttpStatusCode.Unauthorized)
.WaitAndRetryAsync(
maxRetryAttempts,
retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
onRetry: (outcome, timespan, retryCount, context) =>
{
var reason = outcome.Result?.StatusCode.ToString() ?? outcome.Exception?.Message;
_logger.LogWarning(
"Retry {RetryCount} after {TimeSpan}ms due to: {Reason}",
retryCount, timespan.TotalMilliseconds, reason);
});
}
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
return await _retryPolicy.ExecuteAsync(async () =>
await base.SendAsync(request, cancellationToken));
}
}