Skip to content

Commit 262168a

Browse files
[12.x] Parse Redis "friendly" algorithm names into integers (#56800)
* Parse algorithm names * add parenthesis * Update RedisCacheIntegrationTest.php * dont fail with int-based invalid backoff algorithms * refac
1 parent 579e0a9 commit 262168a

File tree

2 files changed

+120
-1
lines changed

2 files changed

+120
-1
lines changed

src/Illuminate/Redis/Connectors/PhpRedisConnector.php

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Illuminate\Support\Arr;
99
use Illuminate\Support\Facades\Redis as RedisFacade;
1010
use Illuminate\Support\Str;
11+
use InvalidArgumentException;
1112
use LogicException;
1213
use Redis;
1314
use RedisCluster;
@@ -92,7 +93,7 @@ protected function createClient(array $config)
9293
}
9394

9495
if (array_key_exists('backoff_algorithm', $config)) {
95-
$client->setOption(Redis::OPT_BACKOFF_ALGORITHM, $config['backoff_algorithm']);
96+
$client->setOption(Redis::OPT_BACKOFF_ALGORITHM, $this->parseBackoffAlgorithm($config['backoff_algorithm']));
9697
}
9798

9899
if (array_key_exists('backoff_base', $config)) {
@@ -241,4 +242,29 @@ protected function formatHost(array $options)
241242

242243
return $options['host'];
243244
}
245+
246+
/**
247+
* Parse a "friendly" backoff algorithm name into an integer.
248+
*
249+
* @param mixed $algorithm
250+
* @return int
251+
*
252+
* @throws \InvalidArgumentException
253+
*/
254+
protected function parseBackoffAlgorithm(mixed $algorithm)
255+
{
256+
if (is_int($algorithm)) {
257+
return $algorithm;
258+
}
259+
260+
return match ($algorithm) {
261+
'default' => Redis::BACKOFF_ALGORITHM_DEFAULT,
262+
'decorrelated_jitter' => Redis::BACKOFF_ALGORITHM_DECORRELATED_JITTER,
263+
'equal_jitter' => Redis::BACKOFF_ALGORITHM_EQUAL_JITTER,
264+
'exponential' => Redis::BACKOFF_ALGORITHM_EXPONENTIAL,
265+
'uniform' => Redis::BACKOFF_ALGORITHM_UNIFORM,
266+
'constant' => Redis::BACKOFF_ALGORITHM_CONSTANT,
267+
default => throw new InvalidArgumentException("Algorithm [{$algorithm}] is not a valid PhpRedis backoff algorithm.")
268+
};
269+
}
244270
}

tests/Cache/RedisCacheIntegrationTest.php

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,14 @@
55
use Illuminate\Cache\RateLimiter;
66
use Illuminate\Cache\RedisStore;
77
use Illuminate\Cache\Repository;
8+
use Illuminate\Foundation\Application;
89
use Illuminate\Foundation\Testing\Concerns\InteractsWithRedis;
10+
use Illuminate\Redis\RedisManager;
11+
use Illuminate\Support\Env;
12+
use InvalidArgumentException;
913
use PHPUnit\Framework\Attributes\DataProvider;
1014
use PHPUnit\Framework\TestCase;
15+
use Redis;
1116

1217
class RedisCacheIntegrationTest extends TestCase
1318
{
@@ -82,4 +87,92 @@ public function testRedisCacheAddNull($driver)
8287
$repository->forever('k', null);
8388
$this->assertFalse($repository->add('k', 'v', 60));
8489
}
90+
91+
#[DataProvider('phpRedisBackoffAlgorithmsProvider')]
92+
public function testPhpRedisBackoffAlgorithmParsing($friendlyAlgorithmName, $expectedAlgorithm)
93+
{
94+
$host = Env::get('REDIS_HOST', '127.0.0.1');
95+
$port = Env::get('REDIS_PORT', 6379);
96+
97+
$manager = new RedisManager(new Application(), 'phpredis', [
98+
'default' => [
99+
'host' => $host,
100+
'port' => $port,
101+
'backoff_algorithm' => $friendlyAlgorithmName,
102+
],
103+
]);
104+
105+
$this->assertEquals(
106+
$expectedAlgorithm,
107+
$manager->connection()->client()->getOption(Redis::OPT_BACKOFF_ALGORITHM)
108+
);
109+
}
110+
111+
#[DataProvider('phpRedisBackoffAlgorithmsProvider')]
112+
public function testPhpRedisBackoffAlgorithm($friendlyAlgorithm, $expectedAlgorithm)
113+
{
114+
$host = Env::get('REDIS_HOST', '127.0.0.1');
115+
$port = Env::get('REDIS_PORT', 6379);
116+
117+
$manager = new RedisManager(new Application(), 'phpredis', [
118+
'default' => [
119+
'host' => $host,
120+
'port' => $port,
121+
'backoff_algorithm' => $expectedAlgorithm,
122+
],
123+
]);
124+
125+
$this->assertEquals(
126+
$expectedAlgorithm,
127+
$manager->connection()->client()->getOption(Redis::OPT_BACKOFF_ALGORITHM)
128+
);
129+
}
130+
131+
public function testAnInvalidPhpRedisBackoffAlgorithmIsConvertedToDefault()
132+
{
133+
$host = Env::get('REDIS_HOST', '127.0.0.1');
134+
$port = Env::get('REDIS_PORT', 6379);
135+
136+
$manager = new RedisManager(new Application(), 'phpredis', [
137+
'default' => [
138+
'host' => $host,
139+
'port' => $port,
140+
'backoff_algorithm' => 7,
141+
],
142+
]);
143+
144+
$this->assertEquals(
145+
Redis::BACKOFF_ALGORITHM_DEFAULT,
146+
$manager->connection()->client()->getOption(Redis::OPT_BACKOFF_ALGORITHM)
147+
);
148+
}
149+
150+
public function testItFailsWithAnInvalidPhpRedisAlgorithm()
151+
{
152+
$this->expectException(InvalidArgumentException::class);
153+
$this->expectExceptionMessage('Algorithm [foo] is not a valid PhpRedis backoff algorithm');
154+
155+
$host = Env::get('REDIS_HOST', '127.0.0.1');
156+
$port = Env::get('REDIS_PORT', 6379);
157+
158+
(new RedisManager(new Application(), 'phpredis', [
159+
'default' => [
160+
'host' => $host,
161+
'port' => $port,
162+
'backoff_algorithm' => 'foo',
163+
],
164+
]))->connection();
165+
}
166+
167+
public static function phpRedisBackoffAlgorithmsProvider()
168+
{
169+
return [
170+
['default', Redis::BACKOFF_ALGORITHM_DEFAULT],
171+
['decorrelated_jitter', Redis::BACKOFF_ALGORITHM_DECORRELATED_JITTER],
172+
['equal_jitter', Redis::BACKOFF_ALGORITHM_EQUAL_JITTER],
173+
['exponential', Redis::BACKOFF_ALGORITHM_EXPONENTIAL],
174+
['uniform', Redis::BACKOFF_ALGORITHM_UNIFORM],
175+
['constant', Redis::BACKOFF_ALGORITHM_CONSTANT],
176+
];
177+
}
85178
}

0 commit comments

Comments
 (0)