From a1b76b5bca9e0171474d6a1b60c3004fbe6a4931 Mon Sep 17 00:00:00 2001 From: Hari K T Date: Tue, 8 Sep 2026 19:26:14 +0530 Subject: [PATCH] Require Redis 4.0 and always delete with UNLINK PhpredisClient::del() branched on method_exists($redis, 'unlink') and fell back to DEL for servers older than Redis 4.0. That branch could not be reached by any server CI runs, or by any server worth supporting from a package that requires PHP 8.4 -- Redis 4.0 is from 2017 -- so it was untestable dead weight that only showed up as a coverage hole. PredisClient::del() was inconsistent with it anyway, issuing DEL unconditionally while the docs promised UNLINK. Both now use UNLINK, and the integration test exercises destroy() through each adapter against a real server. --- CHANGELOG.md | 1 + docs/getting-started.md | 3 +++ src/Redis/PhpredisClient.php | 11 +++-------- src/Redis/PredisClient.php | 4 +++- src/Redis/RedisClientInterface.php | 3 ++- 5 files changed, 12 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e8dee44..a415741 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## 7.0.0 +- (CHG) `RedisSessionHandler` now requires Redis 4.0 or later. `PhpredisClient::del()` no longer falls back to `DEL` when `UNLINK` is unavailable, and `PredisClient::del()` uses `UNLINK` too, so both adapters behave the same. The fallback could not be reached by any supported server, so it was untestable dead weight. - (ADD) Add `RedisSessionHandler`, an optional `SessionHandlerInterface` implementation that stores each session as a single Redis string with a key TTL (the approach used by Symfony, Laravel, and the phpredis native handler). It refreshes only the TTL when data is unchanged (`lazy_write`), destroys empty sessions, and leaves expiry to Redis. It is decoupled from any specific client via `Aura\Session\Redis\RedisClientInterface`, with bundled `PhpredisClient` (ext-redis) and `PredisClient` (predis/predis) adapters. No hard Redis-client dependency: `ext-redis` and `predis/predis` are listed under `suggest`. - (ADD) Add `Segment::getFlashAll()` and `Segment::getFlashNextAll()`, which return every flash value for the current or the next request, so flash messages can be rendered without knowing their keys. Both return an empty array when nothing is set. Originally proposed by Jake Johns in #47/#52. - (ADD) Depend on the new `aura/session-interface` (`^7.0`) package, which provides the shared session/segment contracts. diff --git a/docs/getting-started.md b/docs/getting-started.md index 237ed8b..c86d8c8 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -241,6 +241,9 @@ The handler is decoupled from any specific Redis client through - `Aura\Session\Redis\PhpredisClient` — for the [phpredis](https://github.com/phpredis/phpredis) extension (`ext-redis`). - `Aura\Session\Redis\PredisClient` — for the [predis/predis](https://github.com/predis/predis) package. +Redis 4.0 or later is required: the handler deletes keys with `UNLINK`, so the +memory is reclaimed in a background thread rather than blocking the server. + You can also implement `RedisClientInterface` yourself to back the handler with another client. diff --git a/src/Redis/PhpredisClient.php b/src/Redis/PhpredisClient.php index 1ec9386..b2ca568 100644 --- a/src/Redis/PhpredisClient.php +++ b/src/Redis/PhpredisClient.php @@ -55,14 +55,9 @@ public function setEx(string $key, int $ttl, string $value): void public function del(string $key): void { - // UNLINK reclaims memory in a background thread; fall back to DEL on - // servers older than Redis 4.0. - if (method_exists($this->redis, 'unlink')) { - $this->redis->unlink($key); - return; - } - - $this->redis->del($key); + // UNLINK reclaims memory in a background thread. It needs Redis 4.0, + // which is older than the PHP version this package requires. + $this->redis->unlink($key); } public function expire(string $key, int $ttl): void diff --git a/src/Redis/PredisClient.php b/src/Redis/PredisClient.php index f3b73e3..35f8a24 100644 --- a/src/Redis/PredisClient.php +++ b/src/Redis/PredisClient.php @@ -54,7 +54,9 @@ public function setEx(string $key, int $ttl, string $value): void public function del(string $key): void { - $this->redis->del([$key]); + // UNLINK reclaims memory in a background thread. It needs Redis 4.0, + // which is older than the PHP version this package requires. + $this->redis->unlink([$key]); } public function expire(string $key, int $ttl): void diff --git a/src/Redis/RedisClientInterface.php b/src/Redis/RedisClientInterface.php index 9f8279f..47a9710 100644 --- a/src/Redis/RedisClientInterface.php +++ b/src/Redis/RedisClientInterface.php @@ -48,7 +48,8 @@ public function setEx(string $key, int $ttl, string $value): void; /** * - * Deletes $key. + * Deletes $key, using UNLINK so the memory is reclaimed in a background + * thread. This needs Redis 4.0 or later. * * @param string $key The Redis key. *