Skip to content

Commit 00a3c25

Browse files
dkuzmenchukDenis Kuzmenchuktaylorotwell
authored
[8.x] Fix possible out of memory error when deleting values by reference key from cache in Redis driver (#39939)
* [8.x] Fix possible out of memory error when deleting values by reference key from cache in Redis driver * formatting Co-authored-by: Denis Kuzmenchuk <[email protected]> Co-authored-by: Taylor Otwell <[email protected]>
1 parent 127334a commit 00a3c25

File tree

2 files changed

+14
-8
lines changed

2 files changed

+14
-8
lines changed

src/Illuminate/Cache/RedisTaggedCache.php

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -178,13 +178,19 @@ protected function deleteKeysByReference($reference)
178178
*/
179179
protected function deleteValues($referenceKey)
180180
{
181-
$values = array_unique($this->store->connection()->smembers($referenceKey));
181+
$cursor = $defaultCursorValue = '0';
182182

183-
if (count($values) > 0) {
184-
foreach (array_chunk($values, 1000) as $valuesChunk) {
183+
do {
184+
[$cursor, $valuesChunk] = $this->store->connection()->sscan(
185+
$referenceKey, $cursor, ['MATCH' => '*', 'COUNT' => 1000]
186+
);
187+
188+
$valuesChunk = array_unique($valuesChunk);
189+
190+
if (count($valuesChunk) > 0) {
185191
$this->store->connection()->del(...$valuesChunk);
186192
}
187-
}
193+
} while ($cursor !== $defaultCursorValue);
188194
}
189195

190196
/**

tests/Cache/CacheTaggedCacheTest.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -267,16 +267,16 @@ public function testRedisCacheTagsCanBeFlushed()
267267
$store->shouldReceive('connection')->andReturn($conn = m::mock(stdClass::class));
268268

269269
// Forever tag keys
270-
$conn->shouldReceive('smembers')->once()->with('prefix:foo:forever_ref')->andReturn(['key1', 'key2']);
271-
$conn->shouldReceive('smembers')->once()->with('prefix:bar:forever_ref')->andReturn(['key3']);
270+
$conn->shouldReceive('sscan')->once()->with('prefix:foo:forever_ref', '0', ['MATCH' => '*', 'COUNT' => 1000])->andReturn(['0', ['key1', 'key2']]);
271+
$conn->shouldReceive('sscan')->once()->with('prefix:bar:forever_ref', '0', ['MATCH' => '*', 'COUNT' => 1000])->andReturn(['0', ['key3']]);
272272
$conn->shouldReceive('del')->once()->with('key1', 'key2');
273273
$conn->shouldReceive('del')->once()->with('key3');
274274
$conn->shouldReceive('del')->once()->with('prefix:foo:forever_ref');
275275
$conn->shouldReceive('del')->once()->with('prefix:bar:forever_ref');
276276

277277
// Standard tag keys
278-
$conn->shouldReceive('smembers')->once()->with('prefix:foo:standard_ref')->andReturn(['key4', 'key5']);
279-
$conn->shouldReceive('smembers')->once()->with('prefix:bar:standard_ref')->andReturn(['key6']);
278+
$conn->shouldReceive('sscan')->once()->with('prefix:foo:standard_ref', '0', ['MATCH' => '*', 'COUNT' => 1000])->andReturn(['0', ['key4', 'key5']]);
279+
$conn->shouldReceive('sscan')->once()->with('prefix:bar:standard_ref', '0', ['MATCH' => '*', 'COUNT' => 1000])->andReturn(['0', ['key6']]);
280280
$conn->shouldReceive('del')->once()->with('key4', 'key5');
281281
$conn->shouldReceive('del')->once()->with('key6');
282282
$conn->shouldReceive('del')->once()->with('prefix:foo:standard_ref');

0 commit comments

Comments
 (0)