Alpha ZealPHP is early-stage and under active development. APIs may change between minor versions until v1.0. Feedback and bug reports welcome on GitHub.
API Index — Namespaces, Packages, Reports, Indices

RedisConnectionPool
in package

FinalYes

Per-worker pool of RedisClient connections.

Two coroutines sharing one phpredis/predis socket interleave RESP frames and corrupt the stream — so each op must acquire a private client from this pool, use it, and release it back. The pool is sized N (default 8) per worker; the OpenSwoole\Coroutine\Channel blocks until a client is available.

Outside a coroutine context (sync mode, e.g. superglobals(true)), the pool degrades to a single lazily-built client used sequentially — the channel pop() would block the worker indefinitely otherwise.

Table of Contents

Properties

$buildLock  : Channel|null
Size-1 channel used as a coroutine mutex around channel construction.
$ch  : Channel|null
The coroutine channel holding available RedisClient instances.
$closed  : bool
Set once close() has run. Distinguishes "torn down" from "never built" (both leave $ch === null), so a post-close() acquire() throws instead of silently rebuilding a fresh N-client pool — which would leak the sockets the rebuilt pool opens (#252).
$opts  : array<string|int, mixed>
$size  : int
Configured pool capacity (minimum 1).
$stats  : Stats
Per-worker counters (pool_acquires_total, pool_acquire_timeouts_total, pool_clients_created_total).
$syncClient  : RedisClient|null
Single RedisClient used in sync (non-coroutine) mode.
$url  : string

Methods

__construct()  : mixed
acquire()  : RedisClient
Pop a client from the pool. In coroutine context, yields up to $timeout seconds for one to become available; throws StoreException on timeout. In sync context, returns a shared single client.
close()  : void
Tear down every connection. The channel is drained with a tiny timeout so workers that haven't released their clients yet don't block shutdown.
release()  : void
Return a client to the pool. No-op when the released client is the sync-mode singleton (it lives outside the channel).
size()  : int
Return the configured pool capacity.
stats()  : Stats
Per-worker stats — pool_acquires_total, pool_acquire_timeouts_total, pool_clients_created_total.
url()  : string
Return the Redis connection URL this pool connects to.
with()  : T
Acquire + use + release in one call. Exception-safe via try/finally; the client always goes back into the pool even when $fn throws.
buildChannelLocked()  : Channel
The serialized half of {@see ensureChannel()} — runs under $buildLock.
discard()  : void
Drop a (possibly broken) client instead of returning it to the pool, and refill the pool with a fresh connection so capacity is preserved. The sync-mode singleton is just nulled so acquire() lazily rebuilds it.
ensureChannel()  : Channel
Lazily initialise the Channel and pre-fill it with $size clients.

Properties

$buildLock

Size-1 channel used as a coroutine mutex around channel construction.

private Channel|null $buildLock = null

Every client connect in the fill loop yields on network I/O, so without this gate every cold concurrent acquirer passed the $ch === null check and built its OWN full channel — leaking all but the last (#322).

$ch

The coroutine channel holding available RedisClient instances.

private Channel|null $ch = null

Created lazily on the first acquire() inside a coroutine context because Channel::push() throws outside the scheduler.

$closed

Set once close() has run. Distinguishes "torn down" from "never built" (both leave $ch === null), so a post-close() acquire() throws instead of silently rebuilding a fresh N-client pool — which would leak the sockets the rebuilt pool opens (#252).

private bool $closed = false

$stats

Per-worker counters (pool_acquires_total, pool_acquire_timeouts_total, pool_clients_created_total).

private Stats $stats

Methods

__construct()

public __construct(string $url[, int $size = 8 ][, array{prefer?: "auto"|"phpredis"|"predis"} $opts = [] ]) : mixed
Parameters
$url : string

Redis connection URL (e.g. redis://127.0.0.1:6379).

$size : int = 8

Maximum pool size per worker (default 8).

$opts : array{prefer?: "auto"|"phpredis"|"predis"} = []

Driver preference options.

acquire()

Pop a client from the pool. In coroutine context, yields up to $timeout seconds for one to become available; throws StoreException on timeout. In sync context, returns a shared single client.

public acquire([float $timeout = 5.0 ]) : RedisClient
Parameters
$timeout : float = 5.0
Return values
RedisClient

close()

Tear down every connection. The channel is drained with a tiny timeout so workers that haven't released their clients yet don't block shutdown.

public close() : void

release()

Return a client to the pool. No-op when the released client is the sync-mode singleton (it lives outside the channel).

public release(RedisClient $client) : void
Parameters
$client : RedisClient

stats()

Per-worker stats — pool_acquires_total, pool_acquire_timeouts_total, pool_clients_created_total.

public stats() : Stats
Return values
Stats

url()

Return the Redis connection URL this pool connects to.

public url() : string
Return values
string

with()

Acquire + use + release in one call. Exception-safe via try/finally; the client always goes back into the pool even when $fn throws.

public with(callable(RedisClient): T $fn) : T
Parameters
$fn : callable(RedisClient): T
Tags
template
Return values
T

buildChannelLocked()

The serialized half of {@see ensureChannel()} — runs under $buildLock.

private buildChannelLocked() : Channel

Re-checks $ch first: a parked peer wakes here AFTER the winner built, so it must adopt the winner's channel instead of building another.

Return values
Channel

discard()

Drop a (possibly broken) client instead of returning it to the pool, and refill the pool with a fresh connection so capacity is preserved. The sync-mode singleton is just nulled so acquire() lazily rebuilds it.

private discard(RedisClient $client) : void
Parameters
$client : RedisClient

ensureChannel()

Lazily initialise the Channel and pre-fill it with $size clients.

private ensureChannel() : Channel

IMPORTANT: must be called inside a coroutine — Channel::push() throws outside the scheduler.

Return values
Channel
On this page