# Retry Pattern Guide The Retry pattern automatically retries failed operations, handling transient failures gracefully. ## When to Use - Network requests that may timeout temporarily - Database operations with transient connection issues - File operations on network drives - API calls to services with intermittent availability ## When NOT to Use - Operations that are not idempotent (executing multiple times causes issues) - Permanent failures (invalid credentials, 404 errors) - Operations with side effects that shouldn't be repeated ## Quick Start ```pascal uses Murphy.Policy.Retry; var Policy: IRetryPolicy; begin Policy := TRetryBuilder .Handle(EIdHTTPProtocolException) .Retry(3) .Wait(TTimeSpan.FromSeconds(1)) .Build; Policy.Execute(procedure begin HTTP.Get('https://api.example.com'); end); end; ``` ## Common Scenarios ### HTTP API Calls ```pascal function FetchUserData(UserId: Integer): string; var RetryPolicy: IRetryPolicy; begin RetryPolicy := TRetryBuilder .Handle([EIdHTTPProtocolException, EIdSocketError]) .Retry(3) .Wait(TTimeSpan.FromSeconds(2)) .Build; Result := RetryPolicy.Execute( function: string begin Result := HTTP.Get(Format('https://api.example.com/users/%d', [UserId])); end); end; ``` ### Database Operations ```pascal procedure SaveToDatabase(Data: string); var Policy: IRetryPolicy; begin Policy := TRetryBuilder .Handle(EDatabaseError) .Retry(2) .Wait(TTimeSpan.FromMilliseconds(500)) .Build; Policy.Execute( procedure begin Database.Connect; Database.Execute('INSERT INTO logs VALUES (' + QuotedStr(Data) + ')'); end); end; ``` ### Exponential Backoff ```pascal var Policy: IRetryPolicy; begin Policy := TRetryBuilder .Handle(Exception) .Retry(5) .Wait(TTimeSpan.FromSeconds(1)) .When(function(Ctx: TRetryContext): Boolean begin WriteLn(Format('Retry %d, waiting %dms', [Ctx.Attempts, Trunc(Ctx.WaitDelay.TotalMilliseconds)])); Ctx.WaitDelay := TTimeSpan.FromMilliseconds( Ctx.WaitDelay.TotalMilliseconds * 2); Result := True; end) .Build; end; // Delays: 1s, 2s, 4s, 8s, 16s ``` ### Conditional Retry ```pascal var Policy: IRetryPolicy; begin Policy := TRetryBuilder .Handle(EIdHTTPProtocolException) .Retry(5) .When(function(Ctx: TRetryContext): Boolean begin var Ex := EIdHTTPProtocolException(Ctx.Exception); Result := (Ex.ErrorCode = 503) or (Ex.ErrorCode = 429); end) .Build; end; ``` ## Best Practices 1. **Use specific exceptions** - Don't catch all exceptions 2. **Set reasonable limits** - Too many retries waste resources 3. **Add delays** - Immediate retries often fail again 4. **Consider exponential backoff** - For better server recovery 5. **Log retry attempts** - For debugging and monitoring ## See Also - [Retry API Reference](../API-Reference/Retry-Policy.md) - [Combining Patterns](Combining-Patterns.md) --- [Back to Index](../Home.md)