Skip to content

Commit 4ae015b

Browse files
[11.x] Fix Cache component to be aware of phpredis serialization and compression settings (#54221)
* Add phpredis support to the cache component - Fix cache component not being able to handle serialized or compressed phpredis connections * formatting --------- Co-authored-by: Taylor Otwell <[email protected]>
1 parent c5e1c50 commit 4ae015b

File tree

3 files changed

+99
-10
lines changed

3 files changed

+99
-10
lines changed

src/Illuminate/Cache/LuaScripts.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,22 @@
44

55
class LuaScripts
66
{
7+
/**
8+
* Get the Lua script that sets a key only when it does not yet exist.
9+
*
10+
* KEYS[1] - The name of the key
11+
* ARGV[1] - The value of the key
12+
* ARGV[2] - The number of seconds the key should be valid
13+
*
14+
* @return string
15+
*/
16+
public static function add()
17+
{
18+
return <<<'LUA'
19+
return redis.call('exists',KEYS[1])<1 and redis.call('setex',KEYS[1],ARGV[2],ARGV[1])
20+
LUA;
21+
}
22+
723
/**
824
* Get the Lua script to atomically release a lock.
925
*

src/Illuminate/Cache/RedisStore.php

Lines changed: 72 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,11 @@ public function __construct(Redis $redis, $prefix = '', $connection = 'default')
6868
*/
6969
public function get($key)
7070
{
71-
$value = $this->connection()->get($this->prefix.$key);
71+
$connection = $this->connection();
72+
73+
$value = $connection->get($this->prefix.$key);
7274

73-
return ! is_null($value) ? $this->unserialize($value) : null;
75+
return ! is_null($value) ? $this->connectionAwareUnserialize($value, $connection) : null;
7476
}
7577

7678
/**
@@ -89,12 +91,14 @@ public function many(array $keys)
8991

9092
$results = [];
9193

92-
$values = $this->connection()->mget(array_map(function ($key) {
94+
$connection = $this->connection();
95+
96+
$values = $connection->mget(array_map(function ($key) {
9397
return $this->prefix.$key;
9498
}, $keys));
9599

96100
foreach ($values as $index => $value) {
97-
$results[$keys[$index]] = ! is_null($value) ? $this->unserialize($value) : null;
101+
$results[$keys[$index]] = ! is_null($value) ? $this->connectionAwareUnserialize($value, $connection) : null;
98102
}
99103

100104
return $results;
@@ -110,8 +114,10 @@ public function many(array $keys)
110114
*/
111115
public function put($key, $value, $seconds)
112116
{
113-
return (bool) $this->connection()->setex(
114-
$this->prefix.$key, (int) max(1, $seconds), $this->serialize($value)
117+
$connection = $this->connection();
118+
119+
return (bool) $connection->setex(
120+
$this->prefix.$key, (int) max(1, $seconds), $this->connectionAwareSerialize($value, $connection)
115121
);
116122
}
117123

@@ -165,10 +171,10 @@ public function putMany(array $values, $seconds)
165171
*/
166172
public function add($key, $value, $seconds)
167173
{
168-
$lua = "return redis.call('exists',KEYS[1])<1 and redis.call('setex',KEYS[1],ARGV[2],ARGV[1])";
174+
$connection = $this->connection();
169175

170-
return (bool) $this->connection()->eval(
171-
$lua, 1, $this->prefix.$key, $this->serialize($value), (int) max(1, $seconds)
176+
return (bool) $connection->eval(
177+
LuaScripts::add(), 1, $this->prefix.$key, $this->pack($value, $connection), (int) max(1, $seconds)
172178
);
173179
}
174180

@@ -205,7 +211,9 @@ public function decrement($key, $value = 1)
205211
*/
206212
public function forever($key, $value)
207213
{
208-
return (bool) $this->connection()->set($this->prefix.$key, $this->serialize($value));
214+
$connection = $this->connection();
215+
216+
return (bool) $connection->set($this->prefix.$key, $this->connectionAwareSerialize($value, $connection));
209217
}
210218

211219
/**
@@ -414,6 +422,28 @@ public function setPrefix($prefix)
414422
$this->prefix = $prefix;
415423
}
416424

425+
/**
426+
* Prepare a value to be used with the Redis cache store when used by eval scripts.
427+
*
428+
* @param mixed $value
429+
* @param \Illuminate\Redis\Connections\Connection $connection
430+
* @return mixed
431+
*/
432+
protected function pack($value, $connection)
433+
{
434+
if ($connection instanceof PhpRedisConnection) {
435+
if ($connection->serialized()) {
436+
return $connection->pack([$value])[0];
437+
}
438+
439+
if ($connection->compressed()) {
440+
return $connection->pack([$this->serialize($value)])[0];
441+
}
442+
}
443+
444+
return $this->serialize($value);
445+
}
446+
417447
/**
418448
* Serialize the value.
419449
*
@@ -435,4 +465,36 @@ protected function unserialize($value)
435465
{
436466
return is_numeric($value) ? $value : unserialize($value);
437467
}
468+
469+
/**
470+
* Handle connection specific considerations when a value needs to be serialized.
471+
*
472+
* @param mixed $value
473+
* @param \Illuminate\Redis\Connections\Connection $connection
474+
* @return mixed
475+
*/
476+
protected function connectionAwareSerialize($value, $connection)
477+
{
478+
if ($connection instanceof PhpRedisConnection && $connection->serialized()) {
479+
return $value;
480+
}
481+
482+
return $this->serialize($value);
483+
}
484+
485+
/**
486+
* Handle connection specific considerations when a value needs to be unserialized.
487+
*
488+
* @param mixed $value
489+
* @param \Illuminate\Redis\Connections\Connection $connection
490+
* @return mixed
491+
*/
492+
protected function connectionAwareUnserialize($value, $connection)
493+
{
494+
if ($connection instanceof PhpRedisConnection && $connection->serialized()) {
495+
return $value;
496+
}
497+
498+
return $this->unserialize($value);
499+
}
438500
}

src/Illuminate/Redis/Connections/PacksPhpRedisValues.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,17 @@ public function pack(array $values): array
8282
return array_map($processor, $values);
8383
}
8484

85+
/**
86+
* Determine if serialization is enabled.
87+
*
88+
* @return bool
89+
*/
90+
public function serialized(): bool
91+
{
92+
return defined('Redis::OPT_SERIALIZER') &&
93+
$this->client->getOption(Redis::OPT_SERIALIZER) !== Redis::SERIALIZER_NONE;
94+
}
95+
8596
/**
8697
* Determine if compression is enabled.
8798
*

0 commit comments

Comments
 (0)