ClientPool
struct ClientPoolIdle-connection pool handle.
Copyable because the wrapped state is heap-allocated and
every copy points to the same _ClientPoolState. The
OWNER (the original creator -- typically an
:class:HttpClient) is responsible for calling :meth:free
once it's done; copies created during normal use (e.g. by
Mojo's implicit copy on argument passing) MUST NOT call
:meth:free.
The pool is an HTTP/1.1 building block; see the module docstring for scope.
Implements Copyable, Movable
__init__
def __init__(out self, addr: Int) disabled
def disabled() -> Self Return the no-op handle (_addr == 0).
Equivalent to HttpClient(...) without pooling: every
:meth:acquire returns -1 and every :meth:release
closes the fd immediately.
new
def new(max_idle_per_host: Int = Int(8), max_idle_total: Int = Int(64), idle_timeout_ms: Int = Int(90000)) -> Self Allocate a fresh pool with the given caps.
- Args
max_idle_per_host: Per-origin idle cap (RFC 7230 §6.3 keep-alive parallelism budget). 0 disables idle-keeping for that origin.max_idle_total: Total idle cap across all origins. 0 disables the total cap.idle_timeout_ms: Max wallclock age for a pooled fd before it's evicted on the next acquire(key). 0 disables timeout eviction.
enabled
def enabled(self) -> Bool Return True when _addr != 0 (pooling is on).
build_key
def build_key(scheme: String, host: String, port: Int) -> String Canonicalise the origin into a single-string lookup key.
Format: scheme://host:port. port is always emitted
explicitly (no default-port elision) so a pooled
http://api/ fd can never land in an http://api:8080/
bucket by accident. Used by both :meth:acquire and
:meth:release.
acquire
def acquire(self, key: String) -> Int Pop the most-recently-inserted idle fd for key.
Evicts every fd whose age exceeds
:attr:_ClientPoolState.idle_timeout_ms before pulling
from the deque (the eviction is lazy / on-acquire, not
background-driven).
release
def release(self, key: String, fd: Int) Hand fd back to the pool for key, or close it if the cap is reached.
fd must be in keep-alive shape -- the caller has
already confirmed the response was completely read AND the
server didn't send Connection: close. release does
NOT validate this; it trusts the caller.
total_idle
def total_idle(self) -> Int Public mirror of :meth:_total_idle for tests + the :meth:HttpClient.idle_count accessor.
free
def free(mut self) Close every pooled fd and free the state.
Idempotent on _addr == 0: a no-op on a moved-from /
disabled handle. After free returns, _addr is set
to 0 so subsequent __deinit__ calls (e.g. from a
moved-from copy) are no-ops.