Skip to content

Commit c633647

Browse files
bug #59661 [Lock] Fix Predis error handling (HypeMC)
This PR was merged into the 7.2 branch. Discussion ---------- [Lock] Fix Predis error handling | Q | A | ------------- | --- | Branch? | 7.2 | Bug fix? | yes | New feature? | no | Deprecations? | no | Issues | Fix #59686 | License | MIT #59348 completely broke the Redis store when used with a service, eg: ```yaml framework: lock: resources: default: snc_redis.default ``` The assumption that `exceptions` is always `false` is only correct when a DSN is used. Commits ------- b20892f [Lock] Fix Predis error handling
2 parents 1f12093 + b20892f commit c633647

File tree

3 files changed

+68
-12
lines changed

3 files changed

+68
-12
lines changed

src/Symfony/Component/Lock/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 <fabien@symfony.com>
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+
}

src/Symfony/Component/Lock/Tests/Store/PredisStoreTest.php renamed to src/Symfony/Component/Lock/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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy