Skip to content

Commit e1dae80

Browse files
committed
[Lock] Fix Predis error handling
1 parent 4f6e8b0 commit e1dae80

File tree

3 files changed

+68
-12
lines changed

3 files changed

+68
-12
lines changed

Store/RedisStore.php

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\Lock\Store;
1313

1414
use Predis\Response\Error;
15+
use Predis\Response\ServerException;
1516
use Relay\Relay;
1617
use Symfony\Component\Lock\Exception\InvalidTtlException;
1718
use Symfony\Component\Lock\Exception\LockConflictedException;
@@ -284,21 +285,18 @@ private function evaluate(string $script, string $resource, array $args): mixed
284285

285286
\assert($this->redis instanceof \Predis\ClientInterface);
286287

287-
$result = $this->redis->evalSha($scriptSha, 1, $resource, ...$args);
288-
if ($result instanceof Error && str_starts_with($result->getMessage(), self::NO_SCRIPT_ERROR_MESSAGE_PREFIX)) {
289-
$result = $this->redis->script('LOAD', $script);
290-
if ($result instanceof Error) {
291-
throw new LockStorageException($result->getMessage());
288+
try {
289+
return $this->handlePredisError(fn () => $this->redis->evalSha($scriptSha, 1, $resource, ...$args));
290+
} catch (LockStorageException $e) {
291+
// Fallthrough only if we need to load the script
292+
if (!str_starts_with($e->getMessage(), self::NO_SCRIPT_ERROR_MESSAGE_PREFIX)) {
293+
throw $e;
292294
}
293-
294-
$result = $this->redis->evalSha($scriptSha, 1, $resource, ...$args);
295295
}
296296

297-
if ($result instanceof Error) {
298-
throw new LockStorageException($result->getMessage());
299-
}
297+
$this->handlePredisError(fn () => $this->redis->script('LOAD', $script));
300298

301-
return $result;
299+
return $this->handlePredisError(fn () => $this->redis->evalSha($scriptSha, 1, $resource, ...$args));
302300
}
303301

304302
private function getUniqueToken(Key $key): string
@@ -347,4 +345,26 @@ private function getNowCode(): string
347345
now = math.floor(now * 1000)
348346
';
349347
}
348+
349+
/**
350+
* @template T
351+
*
352+
* @param callable(): T $callback
353+
*
354+
* @return T
355+
*/
356+
private function handlePredisError(callable $callback): mixed
357+
{
358+
try {
359+
$result = $callback();
360+
} catch (ServerException $e) {
361+
throw new LockStorageException($e->getMessage(), $e->getCode(), $e);
362+
}
363+
364+
if ($result instanceof Error) {
365+
throw new LockStorageException($result->getMessage());
366+
}
367+
368+
return $result;
369+
}
350370
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Lock\Tests\Store;
13+
14+
/**
15+
* @group integration
16+
*/
17+
class PredisStoreWithExceptionsTest extends AbstractRedisStoreTestCase
18+
{
19+
public static function setUpBeforeClass(): void
20+
{
21+
$redis = new \Predis\Client(array_combine(['host', 'port'], explode(':', getenv('REDIS_HOST')) + [1 => null]));
22+
try {
23+
$redis->connect();
24+
} catch (\Exception $e) {
25+
self::markTestSkipped($e->getMessage());
26+
}
27+
}
28+
29+
protected function getRedisConnection(): \Predis\Client
30+
{
31+
$redis = new \Predis\Client(array_combine(['host', 'port'], explode(':', getenv('REDIS_HOST')) + [1 => null]));
32+
$redis->connect();
33+
34+
return $redis;
35+
}
36+
}

Tests/Store/PredisStoreTest.php renamed to Tests/Store/PredisStoreWithoutExceptionsTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
*
1717
* @group integration
1818
*/
19-
class PredisStoreTest extends AbstractRedisStoreTestCase
19+
class PredisStoreWithoutExceptionsTest extends AbstractRedisStoreTestCase
2020
{
2121
public static function setUpBeforeClass(): void
2222
{

0 commit comments

Comments
 (0)