रिट्री लॉजिक तब लागू किया जाता है जब कोई ऑपरेशन विफल होता है। इसे केवल वहीं लागू करें जहां विफल ऑपरेशन का पूरा संदर्भ उपलब्ध हो।
महत्वपूर्ण सिद्धांत
- सभी कनेक्टिविटी विफलताओं को लॉग करें जो रिट्री का कारण बनती हैं
- अंतर्निहित समस्याओं (एप्लिकेशन, सेवाएँ, रिसोर्सेज) की पहचान के लिए लॉगिंग आवश्यक
- एक्सपोनेंशियल बैकऑफ का उपयोग करें (फिक्स्ड डिले के बजाय)
- अधिकतम रिट्री अटेम्प्ट्स सेट करें
- रीट्राएबल एक्सेप्शन्स को पहचानें (नेटवर्क एरर, टाइमआउट, 5xx HTTP स्टेटस)
बेसिक रिट्री हेल्पर (दिए गए उदाहरण से)
public static class RetryHelper {
public static void Retry(int times, TimeSpan delay, Action operation) {
var attempts = 0;
do {
try {
attempts++;
System.Console.WriteLine($"Attempt: {attempts}");
operation();
break; // सफलता पर लूप छोड़ें
}
catch (Exception ex) {
if (attempts == times)
throw; // अंतिम अटेम्प्ट पर एक्सेप्शन रीथ्रो
Task.Delay(delay).Wait(); // डिले (ब्लॉकिंग)
}
} while (true);
}
}
// उपयोग
class Program {
public static void Main() {
HttpClient client = new HttpClient();
dynamic res = null;
var retryAttempts = 3;
var delay = TimeSpan.FromSeconds(2);
RetryHelper.Retry(retryAttempts, delay, () => {
res = client.GetAsync("https://example.com/api/cycles/1");
});
Console.ReadLine();
}
}
सुधारित संस्करण: Async/Await और Exponential Backoff के साथ
public static class RetryHelper {
public static async Task<T> RetryAsync<T>(
Func<Task<T>> operation,
int maxAttempts = 3,
TimeSpan? baseDelay = null,
Func<Exception, bool> retryPredicate = null)
{
var delay = baseDelay ?? TimeSpan.FromSeconds(1);
var attempt = 0;
while (true) {
try {
attempt++;
return await operation();
}
catch (Exception ex) when (attempt < maxAttempts &&
(retryPredicate?.Invoke(ex) ?? IsTransient(ex))) {
Console.WriteLine($"Attempt {attempt} failed: {ex.Message}. Retrying in {delay}...");
await Task.Delay(delay);
delay = TimeSpan.FromSeconds(delay.TotalSeconds * 2); // Exponential backoff
}
}
}
private static bool IsTransient(Exception ex) {
return ex is HttpRequestException
|| ex is TimeoutException
|| ex is TaskCanceledException;
}
}
// उपयोग
var result = await RetryHelper.RetryAsync(async () => {
var response = await httpClient.GetAsync(url);
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}, maxAttempts: 5);
Polly लाइब्रेरी (प्रोडक्शन के लिए अनुशंसित)
// NuGet: Polly
var policy = Policy
.Handle<HttpRequestException>()
.Or<TimeoutException>()
.WaitAndRetryAsync(
retryCount: 3,
sleepDurationProvider: attempt => TimeSpan.FromSeconds(Math.Pow(2, attempt)),
onRetry: (exception, delay) => {
Console.WriteLine($"Retry in {delay}: {exception.Message}");
});
var result = await policy.ExecuteAsync(async () => {
return await httpClient.GetStringAsync(url);
});
मुख्य विचार
- इडेम्पोटेंसी: ऑपरेशन इडेम्पोटेंट होना चाहिए (GET सुरक्षित, POST सावधानी से)
- सर्किट ब्रेकर: बार-बार विफलता पर कॉल्स रोकें
- जिटर: डिले में रैंडमनेस जोड़ें (थंडरिंग हर्ड रोकने के लिए)
- कैंसिलेशन: CancellationToken समर्थन जोड़ें
- टेलीमेट्री: मेट्रिक्स रिकॉर्ड करें (अटेम्प्ट्स, डिले, सक्सेस रेट)