API reference
Six types, all in the Flytachi\Winter\CPool namespace. Signatures match the
source; for each item you get the arguments, the return value and any non-obvious
semantics.
Overview
| Type | Kind | Role |
|---|---|---|
ConnectionFactory |
interface | the driver adapter — the single extension point |
ConnectionPool |
class | the pool: borrow, release, evict |
SingleConnection |
class | the same meaning for a runtime without concurrency |
PoolEntry |
DTO | a borrowed connection and its timestamps |
PoolPolicy |
value | the settings |
PoolException |
exception | the package’s only exception |
ConnectionFactory (interface)
public function create(): object;
public function validate(object $connection): bool;
public function close(object $connection): void;| Method | Description |
|---|---|
create() |
Open a connection. May throw — the pool wraps it in PoolException::connectFailed() |
validate($c) |
A cheap liveness probe. false → the pool evicts and opens a new one. A thrown exception counts as death too |
close($c) |
Close it. The pool ignores errors |
In detail — in Writing an adapter.
ConnectionPool (final class)
new ConnectionPool(
ConnectionFactory $factory,
PoolPolicy $policy = new PoolPolicy(),
?Closure $clock = null,
)$clock substitutes the time source, for tests; production code does not need it.
| Method | Returns | Description |
|---|---|---|
borrow() |
PoolEntry |
Take a connection. Below the cap it creates one; at the cap it waits up to connectionTimeout. Throws exhausted() on timeout, unusable() if connections keep failing the probe |
release($entry) |
void |
Return it to the pool. The timestamp is refreshed, the probe is not run |
evict($entry) |
void |
Evict and close — for when the caller knows the connection is broken |
stats() |
array |
['total', 'idle', 'active', 'maximum'] |
close() |
void |
Close every connection and disarm the housekeeping timer |
abandon() |
void |
Forget every connection without closing and disarm the timer — the fork-safe counterpart of close() |
Releasing is mandatory
The pool does not track connections that were never returned: every leak permanently
shrinks it by one. Wrap borrow() in try/finally, or build a facade that releases at
the end of the unit of work.
evict() versus release()
release() puts the connection back into circulation as is. If you know it is broken
— the driver reported a disconnect — returning it means handing a corpse to the next
borrower. That is what evict() is for.
SingleConnection (final class)
new SingleConnection(
ConnectionFactory $factory,
PoolPolicy $policy = new PoolPolicy(),
?Closure $clock = null,
)| Method | Returns | Description |
|---|---|---|
get() |
object |
The connection. Opens it on first call; probes it if it sat idle longer than aliveBypassWindow; reopens it once maxLifetime has passed |
peek() |
?object |
The current connection without creating or probing — for diagnostics with no side effects |
evict() |
void |
Drop it; the next get() opens a new one |
close() |
void |
Close it |
For runtimes where the process serves one unit of work at a time. It honours the same lifetimes and probes, so a long-lived CLI worker does not wake up holding a socket the server closed hours ago.
PoolEntry (final class)
new PoolEntry(
object $resource,
float $createdAt,
float $lastUsedAt,
?float $expiresAt,
)What borrow() returns. The connection itself is in $entry->resource; the rest is what
the pool uses to decide about probing and eviction. You never construct one by hand.
PoolPolicy (final readonly class)
new PoolPolicy(
int $maximumPoolSize = 10,
float $connectionTimeout = 15.0,
float $maxLifetime = 1800.0,
float $aliveBypassWindow = 0.5,
float $maxLifetimeJitter = 0.1,
float $housekeepingInterval = 30.0,
float $keepaliveTime = 0.0,
float $idleTimeout = 0.0,
int $minimumIdle = 0,
)
PoolPolicy::default(): PoolPolicy
$policy->housekeepingEnabled(): boolEach parameter is discussed on the Policy page.
PoolException (final class)
The package’s only exception, with three named constructors:
| Constructor | When |
|---|---|
exhausted(float $timeout) |
No connection became free within the timeout — everything is busy |
connectFailed(Throwable $previous) |
The adapter’s create() threw; the original is in getPrevious() |
unusable(int $attempts) |
Connections keep failing the probe — the database is not answering |
exhausted and unusable are different diagnoses: the first says “your code is holding
everything”, the second says “the connections themselves are bad”.
Next
- Quick start — a working example
- Writing an adapter — how to plug in a driver