NAME

Async::Redis::Pool - Connection pool for Async::Redis

SYNOPSIS

my $pool = Async::Redis::Pool->new(
    host => 'localhost',
    min  => 2,
    max  => 10,
);

# Recommended: scoped pattern
my $result = await $pool->with(async sub {
    my ($redis) = @_;
    await $redis->incr('counter');
});

# Manual acquire/release (be careful!)
my $redis = await $pool->acquire;
await $redis->set('key', 'value');
$pool->release($redis);

DESCRIPTION

Manages a pool of Redis connections with automatic dirty detection. Pool-specific options are consumed by Async::Redis::Pool; all other constructor arguments are passed through to Async::Redis->new.

CONSTRUCTOR

new

my $pool = Async::Redis::Pool->new(
    host            => 'localhost',
    min             => 2,
    max             => 10,
    acquire_timeout => 5,
    cleanup_timeout => 5,
    on_dirty        => 'destroy',
);

Options:

min

Minimum desired pool size. Default: 1. The pool creates replacement connections after dirty connections are destroyed if the total drops below this value.

max

Maximum number of active, idle, and currently-creating connections. Default: 10.

acquire_timeout

Seconds to wait for a connection when the pool is at capacity. Default: 5. Timeouts throw Async::Redis::Error::Timeout.

cleanup_timeout

Seconds to allow a best-effort cleanup command such as DISCARD or UNWATCH. Default: 5.

on_dirty

Dirty connection policy. Default: destroy.

destroy closes dirty connections instead of returning them to the pool.

cleanup attempts bounded cleanup only for transaction/watch state. PubSub connections and connections with pending responses are still destroyed.

idle_timeout

Accepted as a pool option but not currently enforced.

METHODS

acquire

my $redis = await $pool->acquire;

Return a healthy Async::Redis connection from the pool, creating one if the pool is below max. The caller must later call release.

release

$pool->release($redis);

Return a connection to the pool. Dirty connections are either destroyed or cleaned according to on_dirty.

with

my $result = await $pool->with(async sub {
    my ($redis) = @_;
    return await $redis->get('key');
});

Acquire a connection, run the callback, and release the connection even if the callback dies. This is the recommended public API.

stats

my $stats = $pool->stats;

Returns a hashref with active, idle, waiting, total, and destroyed counts.

shutdown

$pool->shutdown;

Stop new acquires, fail pending waiters, and close idle connections. Active connections are destroyed when they are released.

min / max

Return the configured pool size limits.

CONNECTION CLEANLINESS

A connection is "dirty" if it has state that could affect the next user:

  • in_multi - In a MULTI transaction

  • watching - Has WATCH keys

  • in_pubsub - In subscription mode

  • inflight - Has pending responses

Dirty connections are destroyed by default. The cost of a new TCP handshake is far less than the risk of data corruption. With on_dirty => 'cleanup', the pool attempts DISCARD and/or UNWATCH only when it can prove those are the only dirty states present.

RECOMMENDED USAGE

Always prefer with() over manual acquire/release:

await $pool->with(async sub {
    my ($redis) = @_;
    # Use $redis here
    # Connection released automatically, even on exception
});