-
Notifications
You must be signed in to change notification settings - Fork 1
Bulkhead Policy
Unit: Murphy.Policy.Bulkhead
The Bulkhead policy limits the number of concurrent executions of an operation, isolating resources so that one workload cannot exhaust the whole system.
The Bulkhead pattern is useful for capping concurrency, such as:
- Protecting a connection pool from being overwhelmed
- Isolating one workload from another
- Preventing a burst of calls from starving shared resources
The interface for the Bulkhead policy pattern. Extends IExecutablePolicy, so a Bulkhead policy can participate in a Policy Wrap.
type
IBulkheadPolicy = interface(IExecutablePolicy)
['{22323982-6EE4-47B9-851F-A11E8B4ABFB2}']
function ExecutionCount: Integer;
function Limit(AMaxParallelization: Integer): IBulkheadPolicy;
end;procedure Execute(AProc: TProc);Description: Executes AProc if a slot is available, otherwise rejects the call immediately.
Behavior:
- Acquires an execution slot under a lock; if the limit is already reached, raises
EBulkheadRejectedExceptionwithout runningAProc - Runs
AProcoutside the lock, so accepted calls execute in parallel - Always releases the slot afterwards, even if
AProcraises
Note: Exception filtering configured via Handle() is not applied by this policy - calls are limited regardless of exception type, and any exception raised by AProc is re-raised untouched. Rejected calls are not queued.
function ExecutionCount: Integer;Description: Returns the number of executions currently in progress.
Returns: Integer - Current concurrent execution count (thread-safe read)
Use Cases: Monitoring current load, exposing health-check metrics
function Limit(AMaxParallelization: Integer): IBulkheadPolicy;Description: Configures the maximum number of concurrent executions allowed.
Parameters:
-
AMaxParallelization: Integer- Maximum concurrent executions
Returns: IBulkheadPolicy - Self for method chaining
Default: 10 if not specified
Example:
Policy := TBulkheadBuilder
.Handle([])
.Limit(5)
.Build;Concrete implementation of the Bulkhead policy pattern.
type
TBulkheadPolicy = class(TPolicy, IBulkheadPolicy)
private
FExecutionCount: Integer;
FMaxParallelization: Integer;
public
constructor Create(AExceptionTypes: TArray<ExceptClass>); override;
procedure Execute(AProc: TProc);
function ExecutionCount: Integer;
function Limit(AMaxParallelization: Integer): IBulkheadPolicy;
end;constructor Create(AExceptionTypes: TArray<ExceptClass>); override;Defaults:
-
FMaxParallelization:10 -
FExecutionCount:0
Note: Typically called by TBulkheadBuilder, not directly by users.
Slot acquisition, release, and the ExecutionCount read are all synchronized via TMonitor on the policy instance. The action itself always runs outside the lock, so accepted calls execute concurrently up to the configured limit.
Builder class for creating Bulkhead policies with fluent configuration.
type
TBulkheadBuilder = class sealed(TPolicyBuilder<IBulkheadPolicy>)
public
class function Handle(AExceptionTypes: TArray<ExceptClass>): IBulkheadPolicy; override;
end;class function Handle(AExceptionTypes: TArray<ExceptClass>): IBulkheadPolicy; override;Description: Creates a new Bulkhead policy instance. The exception types passed here are not used by this policy: calls are limited regardless of any exception filter. Pass [] for clarity.
Returns: IBulkheadPolicy - Policy instance ready for further configuration
uses
Murphy.Policy.Bulkhead;
var
Policy: IBulkheadPolicy;
begin
Policy := TBulkheadBuilder
.Handle([])
.Limit(10)
.Build;
Policy.Execute(
procedure
begin
ProcessRequest;
end);
end;var
Policy: IBulkheadPolicy;
begin
Policy := TBulkheadBuilder.Handle([]).Limit(20).Build;
try
Policy.Execute(procedure begin ProcessRequest; end);
except
on E: EBulkheadRejectedException do
WriteLn('Rejected: too many concurrent requests');
end;
end;uses Murphy.Policy.Retry, Murphy.Policy.Bulkhead, Murphy.Policy.Wrap;
var
Policy: IPolicyWrap;
begin
Policy := TPolicyWrapBuilder.Wrap([
TRetryBuilder.Handle(EBulkheadRejectedException).Retry(3).Wait(TTimeSpan.FromMilliseconds(200)),
TBulkheadBuilder.Handle([]).Limit(10)
]);
Policy.Execute(procedure begin ProcessRequest; end);
end;- Bulkhead Pattern Guide - Comprehensive usage guide with more examples
-
Base Policy API - Inherited functionality, including
IExecutablePolicy - Policy Wrap API - Composing Bulkhead with other policies
- Combining Patterns - Using Bulkhead with other policies