-
Notifications
You must be signed in to change notification settings - Fork 1
02 Getting Started
This guide will help you install Murphy for Delphi and create your first resilience policies.
- Delphi 11 Alexandria or later
- Windows platform (Win32 or Win64)
Murphy makes use of modern Delphi features such as inline variables, generics, and anonymous methods.
The easiest way to install Murphy is using the Blocks package manager:
blocks install marcobreveglieri.murphy-delphiBlocks will automatically download the library and configure your project paths.
If you prefer manual installation:
-
Download or clone the Murphy repository from GitHub:
git clone https://github.com/marcobreveglieri/murphy-delphi.git
-
Add the
murphy-delphi/Sourcefolder to your project's include path:- Open your project in Delphi
- Go to Project > Options > Delphi Compiler > Search path
- Add the full path to
murphy-delphi/Source
-
Alternatively, add the folder to the IDE's global library path:
- Go to Tools > Options > Language > Delphi > Library
- Add the path to Library path for your target platform
Let's create a simple retry policy that automatically retries failed HTTP requests.
Add the Murphy unit to your uses clause:
uses
Murphy.Policy.Retry;Create and configure a retry policy using the fluent builder API:
var
RetryPolicy: IRetryPolicy;
begin
RetryPolicy := TRetryBuilder.Create
.Handle(EIdHTTPProtocolException) // Handle HTTP exceptions
.Retry(3) // Retry up to 3 times
.Wait(TTimeSpan.FromSeconds(1)) // Wait 1 second between retries
.Build;
end;Use the policy to execute your code:
RetryPolicy.Execute(
procedure
begin
// Your code here - will be automatically retried on failure
MakeHttpRequest('https://api.example.com/data');
end);Here's a complete example:
unit MyUnit;
interface
uses
System.SysUtils,
System.TimeSpan,
IdHTTP,
IdHTTPProtocolException,
Murphy.Policy.Retry;
procedure FetchDataWithRetry;
implementation
procedure FetchDataWithRetry;
var
RetryPolicy: IRetryPolicy;
HTTP: TIdHTTP;
Response: string;
begin
// Create HTTP client
HTTP := TIdHTTP.Create(nil);
try
// Create retry policy
RetryPolicy := TRetryBuilder.Create
.Handle(EIdHTTPProtocolException)
.Retry(3)
.Wait(TTimeSpan.FromSeconds(2))
.Build;
// Execute with automatic retry
RetryPolicy.Execute(
procedure
begin
Response := HTTP.Get('https://api.example.com/data');
WriteLn('Success: ', Response);
end);
finally
HTTP.Free;
end;
end;
end.Murphy includes four resilience patterns. Here are quick examples of each:
Prevent cascading failures by blocking calls to failing services:
uses Murphy.Policy.CircuitBreaker;
var
CircuitPolicy: ICircuitBreakerPolicy;
begin
CircuitPolicy := TCircuitBreakerBuilder.Create
.Handle(Exception)
.Fail(5) // Open after 5 failures
.Within(TTimeSpan.FromSeconds(30)) // Close after 30 seconds
.Build;
CircuitPolicy.Execute(
procedure
begin
CallExternalService;
end);
end;Provide alternative results when operations fail:
uses Murphy.Policy.Fallback;
var
FallbackPolicy: IFallbackPolicy<string>;
Result: string;
begin
FallbackPolicy := TFallbackBuilder<string>.Create
.Handle(Exception)
.Fallback(function: string
begin
Result := 'Cached or default data';
end)
.Build;
Result := FallbackPolicy.Execute(
function: string
begin
Result := GetDataFromService;
end);
WriteLn('Result: ', Result);
end;Control the rate of operations to prevent overload:
uses Murphy.Policy.RateLimit;
var
RateLimitPolicy: IRateLimitPolicy;
begin
RateLimitPolicy := TRateLimitBuilder.Create
.Allow(10) // Allow 10 calls
.Within(TTimeSpan.FromSeconds(1)) // Per second
.Build;
// This will throw ERateLimitRejectedException if limit exceeded
RateLimitPolicy.Execute(
procedure
begin
MakeApiCall;
end);
end;You can configure policies to handle multiple exception types:
RetryPolicy := TRetryBuilder.Create
.Handle(EIdHTTPProtocolException)
.Handle(EIdSocketError)
.Handle(EIdConnClosedGracefully)
.Retry(3)
.Build;Policies re-raise exceptions after exhausting retries or when not handled:
try
RetryPolicy.Execute(
procedure
begin
MakeRequest;
end);
except
on E: EIdHTTPProtocolException do
WriteLn('Request failed after retries: ', E.Message);
end;- Start Simple - Begin with a single pattern (e.g., Retry) before combining multiple patterns
- Use Specific Exceptions - Handle specific exception types rather than catching all exceptions
- Configure Appropriately - Adjust retry counts and delays based on your specific use case
-
Test Your Policies - Enable test mode (
MurphyTestModeEnabled := True) for unit testing - Monitor Behavior - Log or track when policies are triggered to understand system behavior
RetryPolicy := TRetryBuilder.Create
.Handle(EDatabaseError)
.Retry(3)
.Wait(TTimeSpan.FromSeconds(1))
.Build;
RetryPolicy.Execute(
procedure
begin
Database.Connect;
end);var
FallbackPolicy: IFallbackPolicy<TJSONObject>;
Data: TJSONObject;
begin
FallbackPolicy := TFallbackBuilder<TJSONObject>.Create
.Handle(Exception)
.Fallback(function: TJSONObject
begin
Result := GetCachedData;
end)
.Build;
Data := FallbackPolicy.Execute(
function: TJSONObject
begin
Result := FetchDataFromAPI;
end);
end;var
RateLimitPolicy: IRateLimitPolicy;
I: Integer;
begin
RateLimitPolicy := TRateLimitBuilder.Create
.Allow(100) // 100 requests
.Within(TTimeSpan.FromMinutes(1)) // Per minute
.Build;
for I := 1 to 1000 do
begin
try
RateLimitPolicy.Execute(
procedure
begin
MakeAPIRequest(I);
end);
except
on E: ERateLimitRejectedException do
begin
WriteLn('Rate limit exceeded, waiting...');
Sleep(1000);
end;
end;
end;
end;Murphy includes a comprehensive demo application with examples for all patterns. You can find it in the Demos/00_Primer folder:
- Samples.Retry.pas - Retry pattern examples
- Samples.CircuitBreaker.pas - Circuit breaker examples
- Samples.Fallback.pas - Fallback examples
- Samples.RateLimit.pas - Rate limit examples
Run the demo to see the patterns in action and explore the code for more examples.
Now that you've learned the basics:
- Deep Dive: Read the Pattern Guides for comprehensive examples
- API Reference: Explore the API Reference for detailed documentation
- Advanced Usage: Learn about Combining Patterns
- Best Practices: Review Best Practices for production use
Make sure the murphy-delphi/Source folder is in your project's search path or library path.
Murphy requires Delphi 11 Alexandria or later. Check your Delphi version.
Enable test mode and verify your exception types are correct. Check the Testing Guide for more information.