# Bulkhead Policy API **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. ## Overview 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 ## Table of Contents - [IBulkheadPolicy Interface](#ibulkheadpolicy-interface) - [TBulkheadPolicy Class](#tbulkheadpolicy-class) - [TBulkheadBuilder Class](#tbulkheadbuilder-class) - [Usage Examples](#usage-examples) --- ## IBulkheadPolicy Interface The interface for the Bulkhead policy pattern. Extends `IExecutablePolicy`, so a Bulkhead policy can participate in a [Policy Wrap](PolicyWrap-Policy.md). ### Declaration ```pascal type IBulkheadPolicy = interface(IExecutablePolicy) ['{22323982-6EE4-47B9-851F-A11E8B4ABFB2}'] function ExecutionCount: Integer; function Limit(AMaxParallelization: Integer): IBulkheadPolicy; end; ``` ### Methods #### Execute ```pascal procedure Execute(AProc: TProc); ``` **Description**: Executes `AProc` if a slot is available, otherwise rejects the call immediately. **Behavior**: 1. Acquires an execution slot under a lock; if the limit is already reached, raises `EBulkheadRejectedException` without running `AProc` 2. Runs `AProc` outside the lock, so accepted calls execute in parallel 3. Always releases the slot afterwards, even if `AProc` raises **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. #### ExecutionCount ```pascal 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 #### Limit ```pascal 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**: ```pascal Policy := TBulkheadBuilder .Handle([]) .Limit(5) .Build; ``` --- ## TBulkheadPolicy Class Concrete implementation of the Bulkhead policy pattern. ### Declaration ```pascal type TBulkheadPolicy = class(TPolicy, IBulkheadPolicy) private FExecutionCount: Integer; FMaxParallelization: Integer; public constructor Create(AExceptionTypes: TArray); override; procedure Execute(AProc: TProc); function ExecutionCount: Integer; function Limit(AMaxParallelization: Integer): IBulkheadPolicy; end; ``` ### Constructor ```pascal constructor Create(AExceptionTypes: TArray); override; ``` **Defaults**: - `FMaxParallelization`: `10` - `FExecutionCount`: `0` **Note**: Typically called by `TBulkheadBuilder`, not directly by users. ### Implementation Details 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. --- ## TBulkheadBuilder Class Builder class for creating Bulkhead policies with fluent configuration. ### Declaration ```pascal type TBulkheadBuilder = class sealed(TPolicyBuilder) public class function Handle(AExceptionTypes: TArray): IBulkheadPolicy; override; end; ``` #### Handle ```pascal class function Handle(AExceptionTypes: TArray): 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 --- ## Usage Examples ### Example 1: Basic Bulkhead ```pascal uses Murphy.Policy.Bulkhead; var Policy: IBulkheadPolicy; begin Policy := TBulkheadBuilder .Handle([]) .Limit(10) .Build; Policy.Execute( procedure begin ProcessRequest; end); end; ``` ### Example 2: Handling Rejection ```pascal 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; ``` ### Example 3: Bulkhead with Retry ```pascal 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; ``` --- ## See Also - [Bulkhead Pattern Guide](../Patterns/Bulkhead.md) - Comprehensive usage guide with more examples - [Base Policy API](Base-Policy.md) - Inherited functionality, including `IExecutablePolicy` - [Policy Wrap API](PolicyWrap-Policy.md) - Composing Bulkhead with other policies - [Combining Patterns](../Patterns/Combining-Patterns.md) - Using Bulkhead with other policies --- [← Timeout Policy](Timeout-Policy.md) | [API Reference Index](README.md) | [Cache Policy →](Cache-Policy.md)