From 5a445b749bcc252cba73d0651f31c751ea7504c9 Mon Sep 17 00:00:00 2001 From: Matthias Neid Date: Thu, 29 Oct 2026 12:39:47 +0100 Subject: [PATCH] Fix Redis driver treating every query as failed --- .github/workflows/tests.yaml | 1 + .../Redis/Exception/RedisQueryException.php | 5 +- src/Driver/Redis/Redis.php | 3 + test/tests/RedisQueryExceptionTest.php | 63 +++++++++++++++++++ 4 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 test/tests/RedisQueryExceptionTest.php diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 0dde0a1..dcbf2a4 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -24,6 +24,7 @@ jobs: uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php-version }} + extensions: redis - name: Set composer cache directory id: composer-cache diff --git a/src/Driver/Redis/Exception/RedisQueryException.php b/src/Driver/Redis/Exception/RedisQueryException.php index 05f756d..b02b524 100644 --- a/src/Driver/Redis/Exception/RedisQueryException.php +++ b/src/Driver/Redis/Exception/RedisQueryException.php @@ -16,8 +16,11 @@ class RedisQueryException extends RedisModelException */ public static function checkConnection(Redis $redis): void { + // getLastError() returns null if there is no error (or false if there is no connection) $error = $redis->getLastError(); - if ($error !== false) { + if (is_string($error)) { + // the error is kept until it's cleared, so it would be reported again for the next query + $redis->clearLastError(); throw new static("Redis Query Error: " . $error); } } diff --git a/src/Driver/Redis/Redis.php b/src/Driver/Redis/Redis.php index ddea7a9..b865537 100644 --- a/src/Driver/Redis/Redis.php +++ b/src/Driver/Redis/Redis.php @@ -116,6 +116,7 @@ public function save(ModelInterface $model): bool $this->connect(); $key = $this->generateCacheKey($model::class, $model->getId()); try { + $this->connection->clearLastError(); $this->connection->set($key, json_encode($model), $model->getCacheTime()); RedisQueryException::checkConnection($this->connection); } catch (RedisException $e) { @@ -141,6 +142,7 @@ public function get(string $modelClass, mixed $id, ?ModelInterface $model = null $this->connect(); try { + $this->connection->clearLastError(); $rawData = $this->connection->get($this->generateCacheKey($modelClass, $id)); RedisQueryException::checkConnection($this->connection); } catch (RedisException $e) { @@ -178,6 +180,7 @@ public function delete(ModelInterface $model): bool $this->connect(); $key = $this->generateCacheKey($model::class, $model->getId()); try { + $this->connection->clearLastError(); $this->connection->del($key); RedisQueryException::checkConnection($this->connection); } catch (RedisException $e) { diff --git a/test/tests/RedisQueryExceptionTest.php b/test/tests/RedisQueryExceptionTest.php new file mode 100644 index 0000000..3572f3b --- /dev/null +++ b/test/tests/RedisQueryExceptionTest.php @@ -0,0 +1,63 @@ +lastError; + } + + public function clearLastError(): bool + { + $this->cleared = true; + $this->lastError = null; + return true; + } + }; + } + + public function testNoErrorDoesNotThrow(): void + { + $redis = $this->createRedis(null); + RedisQueryException::checkConnection($redis); + $this->assertFalse($redis->cleared); + } + + public function testErrorThrows(): void + { + $this->expectException(RedisQueryException::class); + $this->expectExceptionMessage("Redis Query Error: ERR something went wrong"); + RedisQueryException::checkConnection($this->createRedis("ERR something went wrong")); + } + + public function testErrorIsClearedAfterThrowing(): void + { + $redis = $this->createRedis("ERR something went wrong"); + try { + RedisQueryException::checkConnection($redis); + $this->fail("Expected RedisQueryException"); + } catch (RedisQueryException) { + } + + $this->assertTrue($redis->cleared); + RedisQueryException::checkConnection($redis); + } +}