Client¶
Client entities for generating requests with retry and timeout logic.
Client components for request handling simulation.
This package provides client abstractions with timeout handling, retry policies, connection pooling, and response tracking.
Client ¶
Client(
name: str,
target: Entity,
timeout: float | None = None,
retry_policy: RetryPolicy | None = None,
on_success: Callable[[Event, Event], None]
| None = None,
on_failure: Callable[[Event, str], None] | None = None,
)
Bases: Entity
Client that sends requests and handles responses.
Provides a clean interface for making requests to target entities with support for timeouts and retry policies. Tracks in-flight requests and collects statistics for analysis.
The client handles the request lifecycle: 1. Send request to target 2. Wait for response (with optional timeout) 3. On success: invoke success callback, record stats 4. On timeout: retry according to policy, or invoke failure callback
Attributes:
| Name | Type | Description |
|---|---|---|
name |
Client identifier for logging. |
|
target |
Entity
|
The entity to send requests to. |
timeout |
float | None
|
Request timeout in seconds (None = no timeout). |
retry_policy |
RetryPolicy
|
Policy for retry behavior. |
Initialize the client.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Client identifier. |
required |
target
|
Entity
|
Entity to send requests to. |
required |
timeout
|
float | None
|
Request timeout in seconds (None = no timeout). |
None
|
retry_policy
|
RetryPolicy | None
|
Retry policy for failed requests (default NoRetry). |
None
|
on_success
|
Callable[[Event, Event], None] | None
|
Callback(request, response) on successful response. |
None
|
on_failure
|
Callable[[Event, str], None] | None
|
Callback(request, reason) on final failure. |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If timeout is negative. |
send_request ¶
send_request(
payload: Any = None,
event_type: str = "request",
on_success: Callable[[Event, Event], None]
| None = None,
on_failure: Callable[[Event, str], None] | None = None,
) -> Event
Create a request event to send to the target.
Creates an event that, when scheduled, will send a request to the target entity. The event is ready to be scheduled with sim.schedule().
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
payload
|
Any
|
Optional payload data for the request. |
None
|
event_type
|
str
|
Type string for the request event. |
'request'
|
on_success
|
Callable[[Event, Event], None] | None
|
Override success callback for this request. |
None
|
on_failure
|
Callable[[Event, str], None] | None
|
Override failure callback for this request. |
None
|
Returns:
| Type | Description |
|---|---|
Event
|
Event ready to be scheduled. |
handle_event ¶
handle_event(
event: Event,
) -> (
Generator[float, None, list[Event] | Event | None]
| list[Event]
| Event
| None
)
Handle client events.
Processes: - Outgoing requests: forward to target with tracking - Timeout events: handle timeout and retry - Response events: complete the request
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event
|
Event
|
The event to handle. |
required |
Returns:
| Type | Description |
|---|---|
Generator[float, None, list[Event] | Event | None] | list[Event] | Event | None
|
Events to schedule or generator for async processing. |
get_response_time_percentile ¶
Calculate a percentile of observed response times.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
percentile
|
float
|
Percentile value between 0 and 1. |
required |
Returns:
| Type | Description |
|---|---|
float
|
Response time at the given percentile, or 0 if no data. |
ClientStats
dataclass
¶
ClientStats(
requests_sent: int = 0,
responses_received: int = 0,
timeouts: int = 0,
retries: int = 0,
failures: int = 0,
)
Frozen snapshot of Client statistics.
Connection
dataclass
¶
ConnectionPool ¶
ConnectionPool(
name: str,
target: Entity,
min_connections: int = 0,
max_connections: int = 10,
connection_timeout: float = 5.0,
idle_timeout: float = 60.0,
connection_latency: LatencyDistribution | None = None,
on_acquire: Callable[[Connection], None] | None = None,
on_release: Callable[[Connection], None] | None = None,
on_timeout: Callable[[], None] | None = None,
)
Bases: Entity
Manages a pool of reusable connections to a target.
The connection pool maintains warm connections that can be reused across requests, reducing the overhead of establishing new connections. When the pool is exhausted, new connections are created up to the maximum limit. Requests block when at capacity until a connection is released.
Attributes:
| Name | Type | Description |
|---|---|---|
name |
Pool identifier for logging. |
|
target |
Entity
|
The entity to connect to. |
min_connections |
int
|
Minimum number of warm connections to maintain. |
max_connections |
int
|
Maximum number of total connections. |
connection_timeout |
float
|
Time to wait for a connection before failing. |
idle_timeout |
float
|
Time before idle connections are closed. |
connection_latency |
float
|
Time to establish a new connection. |
Initialize the connection pool.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Pool identifier. |
required |
target
|
Entity
|
Entity to connect to. |
required |
min_connections
|
int
|
Minimum pool size (default 0). |
0
|
max_connections
|
int
|
Maximum pool size (default 10). |
10
|
connection_timeout
|
float
|
Wait timeout in seconds (default 5.0). |
5.0
|
idle_timeout
|
float
|
Idle connection timeout in seconds (default 60.0). |
60.0
|
connection_latency
|
LatencyDistribution | None
|
Time to create a new connection. |
None
|
on_acquire
|
Callable[[Connection], None] | None
|
Callback when connection is acquired. |
None
|
on_release
|
Callable[[Connection], None] | None
|
Callback when connection is released. |
None
|
on_timeout
|
Callable[[], None] | None
|
Callback when acquisition times out. |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If parameters are invalid. |
connection_timeout
property
¶
Timeout in seconds for acquiring a connection.
acquire ¶
Acquire a connection from the pool.
This generator yields while waiting for a connection to become available or while creating a new connection. It returns a Connection object that must be released with release() when done.
Yields:
| Type | Description |
|---|---|
float
|
Time to wait (for connection creation or waiting in queue). |
Returns:
| Type | Description |
|---|---|
Connection
|
A Connection object. |
Raises:
| Type | Description |
|---|---|
TimeoutError
|
If no connection becomes available within timeout. |
release ¶
Release a connection back to the pool.
The connection becomes available for reuse. If there are waiters, the connection is immediately given to the next waiter.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
connection
|
Connection
|
The connection to release. |
required |
Returns:
| Type | Description |
|---|---|
list[Event]
|
Events to schedule (for idle timeout checks). |
handle_event ¶
handle_event(
event: Event,
) -> (
Generator[float, None, list[Event] | Event | None]
| list[Event]
| Event
| None
)
Handle pool events.
Processes: - Idle timeout events: close connections that have been idle too long
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event
|
Event
|
The event to handle. |
required |
Returns:
| Type | Description |
|---|---|
Generator[float, None, list[Event] | Event | None] | list[Event] | Event | None
|
Events to schedule or None. |
warmup ¶
Create minimum connections during simulation startup.
Returns an event that, when scheduled, will create the minimum number of connections specified in min_connections.
Returns:
| Type | Description |
|---|---|
Event
|
Event to schedule for warmup. |
close_all ¶
Close all connections in the pool.
This should be called during simulation teardown.
ConnectionPoolStats
dataclass
¶
ConnectionPoolStats(
connections_created: int = 0,
connections_closed: int = 0,
acquisitions: int = 0,
releases: int = 0,
timeouts: int = 0,
total_wait_time: float = 0.0,
)
Frozen snapshot of ConnectionPool statistics.
PooledClient ¶
PooledClient(
name: str,
connection_pool: ConnectionPool,
timeout: float | None = None,
retry_policy: RetryPolicy | None = None,
on_success: Callable[[Event, Event], None]
| None = None,
on_failure: Callable[[Event, str], None] | None = None,
)
Bases: Entity
Client that uses connection pooling for requests.
Acquires a connection from the pool before each request, ensuring connections are reused efficiently. Supports the same timeout and retry features as the basic Client.
Attributes:
| Name | Type | Description |
|---|---|---|
name |
Client identifier for logging. |
|
connection_pool |
ConnectionPool
|
Pool to acquire connections from. |
timeout |
float | None
|
Request timeout in seconds (None = no timeout). |
retry_policy |
RetryPolicy
|
Policy for retry behavior. |
Initialize the pooled client.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Client identifier. |
required |
connection_pool
|
ConnectionPool
|
Pool to acquire connections from. |
required |
timeout
|
float | None
|
Request timeout in seconds (None = no timeout). |
None
|
retry_policy
|
RetryPolicy | None
|
Retry policy for failed requests (default NoRetry). |
None
|
on_success
|
Callable[[Event, Event], None] | None
|
Callback(request, response) on successful response. |
None
|
on_failure
|
Callable[[Event, str], None] | None
|
Callback(request, reason) on final failure. |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If timeout is negative. |
send_request ¶
send_request(
payload: Any = None,
event_type: str = "request",
on_success: Callable[[Event, Event], None]
| None = None,
on_failure: Callable[[Event, str], None] | None = None,
) -> Event
Create a request event to send through the pool.
Creates an event that, when scheduled, will acquire a connection from the pool and send a request to the target. The event is ready to be scheduled with sim.schedule().
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
payload
|
Any
|
Optional payload data for the request. |
None
|
event_type
|
str
|
Type string for the request event. |
'request'
|
on_success
|
Callable[[Event, Event], None] | None
|
Override success callback for this request. |
None
|
on_failure
|
Callable[[Event, str], None] | None
|
Override failure callback for this request. |
None
|
Returns:
| Type | Description |
|---|---|
Event
|
Event ready to be scheduled. |
handle_event ¶
handle_event(
event: Event,
) -> (
Generator[float, None, list[Event] | Event | None]
| list[Event]
| Event
| None
)
Handle client events.
Processes: - Outgoing requests: acquire connection, forward to target - Timeout events: handle timeout and retry - Response events: complete the request, release connection
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event
|
Event
|
The event to handle. |
required |
Returns:
| Type | Description |
|---|---|
Generator[float, None, list[Event] | Event | None] | list[Event] | Event | None
|
Events to schedule or generator for async processing. |
get_response_time_percentile ¶
Calculate a percentile of observed response times.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
percentile
|
float
|
Percentile value between 0 and 1. |
required |
Returns:
| Type | Description |
|---|---|
float
|
Response time at the given percentile, or 0 if no data. |
PooledClientStats
dataclass
¶
PooledClientStats(
requests_sent: int = 0,
responses_received: int = 0,
timeouts: int = 0,
retries: int = 0,
failures: int = 0,
connection_wait_timeouts: int = 0,
)
Frozen snapshot of PooledClient statistics.
DecorrelatedJitter ¶
AWS-style decorrelated jitter backoff.
A more sophisticated jitter algorithm that decorrelates retry times across multiple clients. This helps prevent synchronized retries (thundering herd) more effectively than simple jitter.
The delay formula is
delay = random(base_delay, min(max_delay, previous_delay * 3))
Reference
https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/
Attributes:
| Name | Type | Description |
|---|---|---|
max_attempts |
int
|
Maximum number of total attempts. |
base_delay |
float
|
Minimum delay between attempts. |
max_delay |
float
|
Maximum delay cap. |
Initialize decorrelated jitter policy.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
max_attempts
|
int
|
Maximum total attempts (must be >= 1). |
required |
base_delay
|
float
|
Minimum delay in seconds (must be > 0). |
required |
max_delay
|
float
|
Maximum delay cap in seconds (must be >= base_delay). |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If parameters are invalid. |
should_retry ¶
Check if another retry should be attempted.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
attempt
|
int
|
Current attempt number (1-based). |
required |
error
|
Exception | None
|
The error that occurred (ignored for this policy). |
None
|
Returns:
| Type | Description |
|---|---|
bool
|
True if attempt < max_attempts. |
get_delay ¶
Calculate decorrelated jitter delay.
Uses the formula: random(base, min(max, prev * 3))
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
attempt
|
int
|
Current attempt number (1-based). |
required |
Returns:
| Type | Description |
|---|---|
float
|
Delay in seconds for this attempt. |
reset ¶
Reset the previous delay to base_delay.
Call this when starting a new request sequence.
ExponentialBackoff ¶
ExponentialBackoff(
max_attempts: int,
initial_delay: float,
max_delay: float,
multiplier: float = 2.0,
jitter: float = 0.0,
)
Exponential backoff with optional jitter.
Increases delay exponentially between retries, with optional random jitter to prevent thundering herd problems. This is the recommended retry strategy for most distributed systems.
The delay formula is
delay = min(initial_delay * (multiplier ^ (attempt - 1)), max_delay) delay += random(0, jitter)
Attributes:
| Name | Type | Description |
|---|---|---|
max_attempts |
int
|
Maximum number of total attempts. |
initial_delay |
float
|
Delay for the first retry. |
max_delay |
float
|
Maximum delay cap. |
multiplier |
float
|
Factor to multiply delay by each attempt. |
jitter |
float
|
Maximum random delay to add. |
Initialize exponential backoff policy.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
max_attempts
|
int
|
Maximum total attempts (must be >= 1). |
required |
initial_delay
|
float
|
Initial delay in seconds (must be > 0). |
required |
max_delay
|
float
|
Maximum delay cap in seconds (must be >= initial_delay). |
required |
multiplier
|
float
|
Delay multiplier per attempt (must be >= 1). |
2.0
|
jitter
|
float
|
Maximum random jitter to add (must be >= 0). |
0.0
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If parameters are invalid. |
should_retry ¶
Check if another retry should be attempted.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
attempt
|
int
|
Current attempt number (1-based). |
required |
error
|
Exception | None
|
The error that occurred (ignored for this policy). |
None
|
Returns:
| Type | Description |
|---|---|
bool
|
True if attempt < max_attempts. |
get_delay ¶
Calculate exponential backoff delay with jitter.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
attempt
|
int
|
Current attempt number (1-based). |
required |
Returns:
| Type | Description |
|---|---|
float
|
Delay in seconds for this attempt. |
FixedRetry ¶
Retry with a fixed delay between attempts.
Simple retry strategy that waits the same amount of time between each retry attempt. Good for transient failures where the delay doesn't need to increase.
Attributes:
| Name | Type | Description |
|---|---|---|
max_attempts |
int
|
Maximum number of total attempts (including initial). |
delay |
float
|
Fixed delay in seconds between attempts. |
Initialize fixed retry policy.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
max_attempts
|
int
|
Maximum total attempts (must be >= 1). |
required |
delay
|
float
|
Delay in seconds between attempts (must be >= 0). |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If max_attempts < 1 or delay < 0. |
should_retry ¶
Check if another retry should be attempted.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
attempt
|
int
|
Current attempt number (1-based). |
required |
error
|
Exception | None
|
The error that occurred (ignored for this policy). |
None
|
Returns:
| Type | Description |
|---|---|
bool
|
True if attempt < max_attempts. |
get_delay ¶
Get the fixed delay.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
attempt
|
int
|
Current attempt number (ignored). |
required |
Returns:
| Type | Description |
|---|---|
float
|
The configured fixed delay. |
NoRetry ¶
Never retry failed requests.
Use when requests should fail immediately without retry attempts. This is the default policy when no retry is configured.
should_retry ¶
Never retry.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
attempt
|
int
|
The attempt number (ignored). |
required |
error
|
Exception | None
|
The error (ignored). |
None
|
Returns:
| Type | Description |
|---|---|
bool
|
Always False. |
get_delay ¶
No delay since we never retry.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
attempt
|
int
|
The attempt number (ignored). |
required |
Returns:
| Type | Description |
|---|---|
float
|
Always 0. |
RetryPolicy ¶
Bases: Protocol
Protocol for retry behavior strategies.
Implementations determine whether to retry a failed request and how long to wait before the next attempt.
should_retry ¶
Determine if another retry attempt should be made.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
attempt
|
int
|
The attempt number (1 = first attempt, 2 = first retry, etc.). |
required |
error
|
Exception | None
|
The error that caused the failure, if any. |
None
|
Returns:
| Type | Description |
|---|---|
bool
|
True if another attempt should be made. |
get_delay ¶
Get the delay before the next retry attempt.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
attempt
|
int
|
The attempt number (1 = first attempt, 2 = first retry, etc.). |
required |
Returns:
| Type | Description |
|---|---|
float
|
Delay in seconds before the next attempt. |