Skip to content

Commit 83945c2

Browse files
author
André R
committed
Backport exception if redis eviction policy is wrong
1 parent cd11a7a commit 83945c2

File tree

2 files changed

+85
-3
lines changed

2 files changed

+85
-3
lines changed

src/lib/Symfony/Components/Cache/Adapter/TagAware/RedisTagAwareAdapter.php

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@
1515

1616
namespace Symfony\Component\Cache\Adapter\TagAware;
1717

18-
use Predis;
1918
use Predis\Connection\Aggregate\ClusterInterface;
2019
use Predis\Response\Status;
2120
use Symfony\Component\Cache\Adapter\TagAwareAdapterInterface;
21+
use Symfony\Component\Cache\Exception\LogicException;
2222
use Symfony\Component\Cache\Traits\RedisTrait;
2323

2424
/**
@@ -52,6 +52,11 @@ final class RedisTagAwareAdapter extends AbstractTagAwareAdapter implements TagA
5252
*/
5353
private const FORCED_ITEM_TTL = 864000;
5454

55+
/**
56+
* @var string|null detected eviction policy used on Redis server
57+
*/
58+
private $redisEvictionPolicy;
59+
5560
/**
5661
* @param \Redis|\RedisArray|\RedisCluster|\Predis\Client $redisClient The redis client
5762
* @param string $namespace The default namespace
@@ -64,8 +69,8 @@ public function __construct($redisClient, string $namespace = '', int $defaultLi
6469
$this->init($redisClient, $namespace, $defaultLifetime);
6570

6671
// Make sure php-redis is 3.1.3 or higher configured for Redis classes
67-
if (!$this->redis instanceof Predis\Client && version_compare(phpversion('redis'), '3.1.3', '<')) {
68-
throw new \Exception('RedisTagAwareAdapter requries php-redis 3.1.3 or higher, alternatively use predis/predis');
72+
if (!$this->redis instanceof \Predis\ClientInterface && version_compare(phpversion('redis'), '3.1.3', '<')) {
73+
throw new \Exception('RedisTagAwareAdapter requries php-redis 3.1.3 or higher, alternatively use predis/predis, or upgrade ezsystems/symfony-tools to v1.1.x');
6974
}
7075
}
7176

@@ -80,6 +85,11 @@ public function __construct($redisClient, string $namespace = '', int $defaultLi
8085
*/
8186
protected function doSave(array $values, $lifetime)
8287
{
88+
$eviction = $this->getRedisEvictionPolicy();
89+
if ('noeviction' !== $eviction && 0 !== strpos($eviction, 'volatile-')) {
90+
throw new LogicException(sprintf('Redis maxmemory-policy setting "%s" is *not* supported by RedisTagAwareAdapter, use "noeviction" or "volatile-*" eviction policies.', $eviction));
91+
}
92+
8393
// Extract tag operations
8494
$tagOperations = ['sAdd' => [], 'sRem' => []];
8595
foreach ($values as $id => $value) {
@@ -183,4 +193,50 @@ public function doInvalidate(array $tagIds): bool
183193

184194
return true;
185195
}
196+
197+
private function getRedisEvictionPolicy(): string
198+
{
199+
if (null !== $this->redisEvictionPolicy) {
200+
return $this->redisEvictionPolicy;
201+
}
202+
203+
foreach ($this->getHosts() as $host) {
204+
$info = $host->info('Memory');
205+
$info = isset($info['Memory']) ? $info['Memory'] : $info;
206+
207+
return $this->redisEvictionPolicy = $info['maxmemory_policy'];
208+
}
209+
210+
return $this->redisEvictionPolicy = '';
211+
}
212+
213+
/**
214+
* Backport from RedisTrait in 4.4.
215+
*/
216+
private function getHosts(): array
217+
{
218+
$hosts = [$this->redis];
219+
if ($this->redis instanceof \Predis\ClientInterface) {
220+
$connection = $this->redis->getConnection();
221+
if ($connection instanceof ClusterInterface && $connection instanceof \Traversable) {
222+
$hosts = [];
223+
foreach ($connection as $c) {
224+
$hosts[] = new \Predis\Client($c);
225+
}
226+
}
227+
} elseif ($this->redis instanceof \RedisArray) {
228+
$hosts = [];
229+
foreach ($this->redis->_hosts() as $host) {
230+
$hosts[] = $this->redis->_instance($host);
231+
}
232+
} elseif ($this->redis instanceof \RedisCluster) {
233+
$hosts = [];
234+
foreach ($this->redis->_masters() as $host) {
235+
$hosts[] = $h = new \Redis();
236+
$h->connect($host[0], $host[1]);
237+
}
238+
}
239+
240+
return $hosts;
241+
}
186242
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
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\Cache\Exception;
13+
14+
use Psr\Cache\CacheException as Psr6CacheInterface;
15+
use Psr\SimpleCache\CacheException as SimpleCacheInterface;
16+
17+
if (interface_exists(SimpleCacheInterface::class)) {
18+
class LogicException extends \LogicException implements Psr6CacheInterface, SimpleCacheInterface
19+
{
20+
}
21+
} else {
22+
class LogicException extends \LogicException implements Psr6CacheInterface
23+
{
24+
}
25+
}
26+

0 commit comments

Comments
 (0)