如何使用Polly实现仅在错误码403002出现时重试3次deviceClient.SendEventAsync操作
Got it, let's break down how to implement this Polly retry logic for your specific scenario. You’re already parsing the error code correctly in your try-catch, so we just need to move that logic into Polly’s policy definition to clean things up and separate retry concerns from your business code.
Step 1: Create a Helper to Check Retry Eligibility
First, extract your error code validation into a reusable method. This will tell Polly whether an exception should trigger a retry:
private bool ShouldRetryOn403002(Exception ex) { // Get the inner exception message where your error JSON lives var errorMessage = ex.InnerException?.Message; if (string.IsNullOrEmpty(errorMessage)) return false; try { // Deserialize the error message and check the code dynamic error = JsonConvert.DeserializeObject(errorMessage); return error != null && error.errorCode == 403002; } catch (JsonException) { // If deserialization fails, this isn't the 403002 error we care about return false; } }
Step 2: Build an Async Retry Policy
Since your SendEventAsync is an asynchronous method, you must use Polly's async-aware policies (don’t use the synchronous WaitAndRetry—it won’t work correctly with await). We’ll define a policy that retries only when our helper returns true, with configurable delays:
// Pull these values from your config (e.g., appsettings.json) for flexibility int maxRetryAttempts = 3; Func<int, TimeSpan> retryDelayStrategy = attempt => TimeSpan.FromSeconds(Math.Pow(2, attempt)); // Exponential backoff (2s, 4s, 8s) // Or use a fixed delay: _ => TimeSpan.FromSeconds(3) var retryPolicy = Policy .Handle<Exception>(ex => ShouldRetryOn403002(ex)) .WaitAndRetryAsync( retryCount: maxRetryAttempts, sleepDurationProvider: retryDelayStrategy, onRetry: (exception, timespan, retryAttempt, context) => { // Log each retry for visibility _logger.LogWarning( $"Retry {retryAttempt}/{maxRetryAttempts} triggered for error code 403002. Waiting {timespan.TotalSeconds:F1}s before next attempt."); });
Step 3: Wrap Your Async Operation with the Policy
Replace your existing try-catch block with Polly’s ExecuteAsync method. Polly will handle retries automatically, and only throw an exception if retries are exhausted or the error isn’t eligible for retry:
try { // Execute your send operation wrapped in the retry policy await retryPolicy.ExecuteAsync(async () => { await deviceClient.SendEventAsync(new Message()); }); } catch (Exception ex) { // This catches: // 1. Errors that aren't 403002 (no retries attempted) // 2. 403002 errors that failed all retry attempts _logger.LogError($"Operation failed after retries: {ex.Message}", ex); // Re-throw if you need to propagate the error upstream throw; }
Optional: Externalize Configuration
To make your retry strategy configurable without changing code, add settings to appsettings.json:
"RetrySettings": { "MaxRetryAttempts": 3, "InitialDelaySeconds": 2 }
Then inject IConfiguration and read the values:
var maxRetryAttempts = _configuration.GetValue<int>("RetrySettings:MaxRetryAttempts"); var initialDelay = TimeSpan.FromSeconds(_configuration.GetValue<double>("RetrySettings:InitialDelaySeconds")); var retryDelayStrategy = attempt => initialDelay * Math.Pow(2, attempt);
This approach keeps your business code clean, centralizes retry logic, and gives you flexibility to adjust retry behavior via config.
内容的提问来源于stack exchange,提问作者user584018

