diff --git a/src/Illuminate/Cache/RedisTaggedCache.php b/src/Illuminate/Cache/RedisTaggedCache.php index 6a683c10c36b..21f367df17db 100644 --- a/src/Illuminate/Cache/RedisTaggedCache.php +++ b/src/Illuminate/Cache/RedisTaggedCache.php @@ -178,13 +178,26 @@ protected function deleteKeysByReference($reference) */ protected function deleteValues($referenceKey) { - $values = array_unique($this->store->connection()->smembers($referenceKey)); + $cursor = $defaultCursorValue = '0'; + + do { + [$cursor, $valuesChunk] = $this->store->connection()->sscan( + $referenceKey, $cursor, ['match' => '*', 'count' => 1000] + ); + + // PhpRedis client returns false if set does not exist or empty. Destruction on false stores null + // in each variable. If valuesChunk is null, it means that there is no results from sscan command. + // Iteration over set could be finished. + if ($valuesChunk === null) { + break; + } + + $valuesChunk = array_unique($valuesChunk); - if (count($values) > 0) { - foreach (array_chunk($values, 1000) as $valuesChunk) { + if (count($valuesChunk) > 0) { $this->store->connection()->del(...$valuesChunk); } - } + } while (((string) $cursor) !== $defaultCursorValue); } /** diff --git a/tests/Cache/CacheTaggedCacheTest.php b/tests/Cache/CacheTaggedCacheTest.php index 05baebd209a4..b2493694d136 100644 --- a/tests/Cache/CacheTaggedCacheTest.php +++ b/tests/Cache/CacheTaggedCacheTest.php @@ -267,16 +267,16 @@ public function testRedisCacheTagsCanBeFlushed() $store->shouldReceive('connection')->andReturn($conn = m::mock(stdClass::class)); // Forever tag keys - $conn->shouldReceive('smembers')->once()->with('prefix:foo:forever_ref')->andReturn(['key1', 'key2']); - $conn->shouldReceive('smembers')->once()->with('prefix:bar:forever_ref')->andReturn(['key3']); + $conn->shouldReceive('sscan')->once()->with('prefix:foo:forever_ref', '0', ['match' => '*', 'count' => 1000])->andReturn(['0', ['key1', 'key2']]); + $conn->shouldReceive('sscan')->once()->with('prefix:bar:forever_ref', '0', ['match' => '*', 'count' => 1000])->andReturn(['0', ['key3']]); $conn->shouldReceive('del')->once()->with('key1', 'key2'); $conn->shouldReceive('del')->once()->with('key3'); $conn->shouldReceive('del')->once()->with('prefix:foo:forever_ref'); $conn->shouldReceive('del')->once()->with('prefix:bar:forever_ref'); // Standard tag keys - $conn->shouldReceive('smembers')->once()->with('prefix:foo:standard_ref')->andReturn(['key4', 'key5']); - $conn->shouldReceive('smembers')->once()->with('prefix:bar:standard_ref')->andReturn(['key6']); + $conn->shouldReceive('sscan')->once()->with('prefix:foo:standard_ref', '0', ['match' => '*', 'count' => 1000])->andReturn(['0', ['key4', 'key5']]); + $conn->shouldReceive('sscan')->once()->with('prefix:bar:standard_ref', '0', ['match' => '*', 'count' => 1000])->andReturn(['0', ['key6']]); $conn->shouldReceive('del')->once()->with('key4', 'key5'); $conn->shouldReceive('del')->once()->with('key6'); $conn->shouldReceive('del')->once()->with('prefix:foo:standard_ref');