From ac8e021c57f8b80bf7981aa124533e5eb8a9abc6 Mon Sep 17 00:00:00 2001 From: Vladyslav Vildanov <117659936+vladvildanov@users.noreply.github.com> Date: Wed, 1 Feb 2023 13:51:45 +0200 Subject: [PATCH] Added support for CF.LOADCHUNK, CF.SCANDUMP commands (#1085) Co-authored-by: Vladyslav Vildanov --- src/ClientContextInterface.php | 3 +- src/ClientInterface.php | 2 + .../Redis/CuckooFilter/CFLOADCHUNK.php | 29 +++++ src/Command/Redis/CuckooFilter/CFSCANDUMP.php | 29 +++++ .../Redis/CuckooFilter/CFLOADCHUNK_Test.php | 108 ++++++++++++++++++ .../Redis/CuckooFilter/CFSCANDUMP_Test.php | 89 +++++++++++++++ 6 files changed, 259 insertions(+), 1 deletion(-) create mode 100644 src/Command/Redis/CuckooFilter/CFLOADCHUNK.php create mode 100644 src/Command/Redis/CuckooFilter/CFSCANDUMP.php create mode 100644 tests/Predis/Command/Redis/CuckooFilter/CFLOADCHUNK_Test.php create mode 100644 tests/Predis/Command/Redis/CuckooFilter/CFSCANDUMP_Test.php diff --git a/src/ClientContextInterface.php b/src/ClientContextInterface.php index d78750c4..e3521156 100644 --- a/src/ClientContextInterface.php +++ b/src/ClientContextInterface.php @@ -64,11 +64,12 @@ use Predis\Command\CommandInterface; * @method $this cfcount(string $key, $item) * @method $this cfdel(string $key, $item) * @method $this cfexists(string $key, $item) + * @method $this cfloadchunk(string $key, int $iterator, $data) * @method $this cfmexists(string $key, ...$item) * @method $this cfinfo(string $key) * @method $this cfinsert(string $key, int $capacity = -1, bool $noCreate = false, string ...$item) * @method $this cfreserve(string $key, int $capacity, int $bucketSize = -1, int $maxIterations = -1, int $expansion = -1) - * @method $this decr($key) + * @method $this cfscandump(string $key, int $iterator) * @method $this decr($key) * @method $this decrby($key, $decrement) * @method $this failover(?To $to = null, bool $abort = false, int $timeout = -1) * @method $this get($key) diff --git a/src/ClientInterface.php b/src/ClientInterface.php index 66e2df8e..af26e273 100644 --- a/src/ClientInterface.php +++ b/src/ClientInterface.php @@ -73,10 +73,12 @@ use Predis\Response\Status; * @method int cfcount(string $key, $item) * @method int cfdel(string $key, $item) * @method int cfexists(string $key, $item) + * @method Status cfloadchunk(string $key, int $iterator, $data) * @method int cfmexists(string $key, ...$item) * @method array cfinfo(string $key) * @method array cfinsert(string $key, int $capacity = -1, bool $noCreate = false, string ...$item) * @method Status cfreserve(string $key, int $capacity, int $bucketSize = -1, int $maxIterations = -1, int $expansion = -1) + * @method array cfscandump(string $key, int $iterator) * @method int decr(string $key) * @method int decrby(string $key, int $decrement) * @method Status failover(?To $to = null, bool $abort = false, int $timeout = -1) diff --git a/src/Command/Redis/CuckooFilter/CFLOADCHUNK.php b/src/Command/Redis/CuckooFilter/CFLOADCHUNK.php new file mode 100644 index 00000000..6a961552 --- /dev/null +++ b/src/Command/Redis/CuckooFilter/CFLOADCHUNK.php @@ -0,0 +1,29 @@ +getCommand(); + $command->setArguments($actualArguments); + + $this->assertSameValues($expectedArguments, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse(): void + { + $this->assertSame(1, $this->getCommand()->parseResponse(1)); + } + + /** + * @group connected + * @return void + * @requiresRedisBfVersion >= 1.0.0 + */ + public function testLoadChunkSuccessfullyRestoresCuckooFilter(): void + { + $redis = $this->getClient(); + + $redis->cfadd('key', 'item1'); + + $chunks = []; + $iter = 0; + + while (true) { + [$iter, $data] = $redis->cfscandump('key', $iter); + + if ($iter === 0) { + break; + } + + $chunks[] = [$iter, $data]; + } + + $redis->flushall(); + + foreach ($chunks as $chunk) { + [$iter, $data] = $chunk; + $actualResponse = $redis->cfloadchunk('key', $iter, $data); + + $this->assertEquals('OK', $actualResponse); + } + + $this->assertSame(1, $redis->cfexists('key', 'item1')); + } + + /** + * @group connected + * @requiresRedisBfVersion >= 1.0.0 + */ + public function testThrowsExceptionOnWrongType(): void + { + $this->expectException(ServerException::class); + $this->expectExceptionMessage('Invalid position'); + + $redis = $this->getClient(); + + $redis->set('cfloadchunk_foo', 'bar'); + $redis->cfloadchunk('cfloadchunk_foo', 0, 'data'); + } +} diff --git a/tests/Predis/Command/Redis/CuckooFilter/CFSCANDUMP_Test.php b/tests/Predis/Command/Redis/CuckooFilter/CFSCANDUMP_Test.php new file mode 100644 index 00000000..dbcdfda3 --- /dev/null +++ b/tests/Predis/Command/Redis/CuckooFilter/CFSCANDUMP_Test.php @@ -0,0 +1,89 @@ +getCommand(); + $command->setArguments($actualArguments); + + $this->assertSameValues($expectedArguments, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse(): void + { + $this->assertSame(1, $this->getCommand()->parseResponse(1)); + } + + /** + * @group connected + * @return void + * @requiresRedisBfVersion >= 1.0.0 + */ + public function testScanDumpReturnsNotEmptyDataChunk(): void + { + $expectedIterator = 1; + $redis = $this->getClient(); + + $redis->cfadd('key', 'item1'); + [$iterator, $dataChunk] = $redis->cfscandump('key', 0); + + $this->assertSame($expectedIterator, $iterator); + $this->assertNotEmpty($dataChunk); + } + + /** + * @group connected + * @requiresRedisBfVersion >= 1.0.0 + */ + public function testThrowsExceptionOnWrongType(): void + { + $this->expectException(ServerException::class); + $this->expectExceptionMessage('Operation against a key holding the wrong kind of value'); + + $redis = $this->getClient(); + + $redis->set('cfscandump_foo', 'bar'); + $redis->cfscandump('cfscandump_foo', 0); + } +}