From d2cd99492df8f0ac38dbe431f84dbcc0fa599cd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Till=20Kr=C3=BCss?= Date: Thu, 13 Apr 2023 09:51:16 -0700 Subject: [PATCH 1/9] don't export `bin` --- .gitattributes | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.gitattributes b/.gitattributes index e20c2b8a..24d268ad 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,8 +1,9 @@ * text=auto -/.github/ export-ignore -/examples/ export-ignore -/tests/ export-ignore +/.github export-ignore +/bin export-ignore +/examples export-ignore +/tests export-ignore /.codespellrc export-ignore linguist-language=INI /.editorconfig export-ignore /.gitattributes export-ignore From bf2075a176df2435f3159c04922689b7c81268fe Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 19 Apr 2023 22:51:42 +0200 Subject: [PATCH 2/9] Add missing `@return` annotations (#1265) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add missing `@return` annotations * formatting * formatting * Update ProcessorChain.php * Update Handler.php --------- Co-authored-by: Till Krüss --- src/Cluster/SlotMap.php | 3 ++- .../Iterator/CursorBasedIterator.php | 10 +++++----- src/Collection/Iterator/ListKey.php | 10 +++++----- src/Command/Processor/ProcessorChain.php | 13 +++++++++---- src/Connection/Cluster/PredisCluster.php | 5 +++-- src/Connection/Cluster/RedisCluster.php | 5 +++-- src/Monitor/Consumer.php | 6 +++--- src/PubSub/AbstractConsumer.php | 6 +++--- src/Response/Iterator/MultiBulkIterator.php | 10 +++++----- src/Response/Iterator/MultiBulkTuple.php | 2 +- src/Session/Handler.php | 19 +++++++++++++------ 11 files changed, 52 insertions(+), 37 deletions(-) diff --git a/src/Cluster/SlotMap.php b/src/Cluster/SlotMap.php index 0557c25e..1af63077 100644 --- a/src/Cluster/SlotMap.php +++ b/src/Cluster/SlotMap.php @@ -19,6 +19,7 @@ use IteratorAggregate; use OutOfBoundsException; use Predis\Connection\NodeConnectionInterface; use ReturnTypeWillChange; +use Traversable; /** * Slot map for redis-cluster. @@ -198,7 +199,7 @@ class SlotMap implements ArrayAccess, IteratorAggregate, Countable /** * Returns an iterator over the slot map. * - * @return ArrayIterator + * @return Traversable */ #[ReturnTypeWillChange] public function getIterator() diff --git a/src/Collection/Iterator/CursorBasedIterator.php b/src/Collection/Iterator/CursorBasedIterator.php index baa3a7c9..946bbc3a 100644 --- a/src/Collection/Iterator/CursorBasedIterator.php +++ b/src/Collection/Iterator/CursorBasedIterator.php @@ -138,7 +138,7 @@ abstract class CursorBasedIterator implements Iterator } /** - * {@inheritdoc} + * @return void */ #[ReturnTypeWillChange] public function rewind() @@ -148,7 +148,7 @@ abstract class CursorBasedIterator implements Iterator } /** - * {@inheritdoc} + * @return mixed */ #[ReturnTypeWillChange] public function current() @@ -157,7 +157,7 @@ abstract class CursorBasedIterator implements Iterator } /** - * {@inheritdoc} + * @return int|null */ #[ReturnTypeWillChange] public function key() @@ -166,7 +166,7 @@ abstract class CursorBasedIterator implements Iterator } /** - * {@inheritdoc} + * @return void */ #[ReturnTypeWillChange] public function next() @@ -186,7 +186,7 @@ abstract class CursorBasedIterator implements Iterator } /** - * {@inheritdoc} + * @return bool */ #[ReturnTypeWillChange] public function valid() diff --git a/src/Collection/Iterator/ListKey.php b/src/Collection/Iterator/ListKey.php index 9f4a21ca..79ab3aa1 100644 --- a/src/Collection/Iterator/ListKey.php +++ b/src/Collection/Iterator/ListKey.php @@ -128,7 +128,7 @@ class ListKey implements Iterator } /** - * {@inheritdoc} + * @return void */ #[ReturnTypeWillChange] public function rewind() @@ -138,7 +138,7 @@ class ListKey implements Iterator } /** - * {@inheritdoc} + * @return mixed */ #[ReturnTypeWillChange] public function current() @@ -147,7 +147,7 @@ class ListKey implements Iterator } /** - * {@inheritdoc} + * @return int|null */ #[ReturnTypeWillChange] public function key() @@ -156,7 +156,7 @@ class ListKey implements Iterator } /** - * {@inheritdoc} + * @return void */ #[ReturnTypeWillChange] public function next() @@ -173,7 +173,7 @@ class ListKey implements Iterator } /** - * {@inheritdoc} + * @return bool */ #[ReturnTypeWillChange] public function valid() diff --git a/src/Command/Processor/ProcessorChain.php b/src/Command/Processor/ProcessorChain.php index 8ecfc4d9..30589556 100644 --- a/src/Command/Processor/ProcessorChain.php +++ b/src/Command/Processor/ProcessorChain.php @@ -93,7 +93,8 @@ class ProcessorChain implements ArrayAccess, ProcessorInterface } /** - * {@inheritdoc} + * @param int $index + * @return bool */ #[ReturnTypeWillChange] public function offsetExists($index) @@ -102,7 +103,8 @@ class ProcessorChain implements ArrayAccess, ProcessorInterface } /** - * {@inheritdoc} + * @param int $index + * @return ProcessorInterface */ #[ReturnTypeWillChange] public function offsetGet($index) @@ -111,7 +113,9 @@ class ProcessorChain implements ArrayAccess, ProcessorInterface } /** - * {@inheritdoc} + * @param int $index + * @param ProcessorInterface $processor + * @return void */ #[ReturnTypeWillChange] public function offsetSet($index, $processor) @@ -126,7 +130,8 @@ class ProcessorChain implements ArrayAccess, ProcessorInterface } /** - * {@inheritdoc} + * @param int $index + * @return void */ #[ReturnTypeWillChange] public function offsetUnset($index) diff --git a/src/Connection/Cluster/PredisCluster.php b/src/Connection/Cluster/PredisCluster.php index 0ba29bb5..c30fd09d 100644 --- a/src/Connection/Cluster/PredisCluster.php +++ b/src/Connection/Cluster/PredisCluster.php @@ -21,6 +21,7 @@ use Predis\Command\CommandInterface; use Predis\Connection\NodeConnectionInterface; use Predis\NotSupportedException; use ReturnTypeWillChange; +use Traversable; /** * Abstraction for a cluster of aggregate connections to various Redis servers @@ -200,7 +201,7 @@ class PredisCluster implements ClusterInterface, IteratorAggregate, Countable } /** - * {@inheritdoc} + * @return int */ #[ReturnTypeWillChange] public function count() @@ -209,7 +210,7 @@ class PredisCluster implements ClusterInterface, IteratorAggregate, Countable } /** - * {@inheritdoc} + * @return Traversable */ #[ReturnTypeWillChange] public function getIterator() diff --git a/src/Connection/Cluster/RedisCluster.php b/src/Connection/Cluster/RedisCluster.php index e0376940..7f3013c1 100644 --- a/src/Connection/Cluster/RedisCluster.php +++ b/src/Connection/Cluster/RedisCluster.php @@ -31,6 +31,7 @@ use Predis\Response\ErrorInterface as ErrorResponseInterface; use Predis\Response\ServerException; use ReturnTypeWillChange; use Throwable; +use Traversable; /** * Abstraction for a Redis-backed cluster of nodes (Redis >= 3.0.0). @@ -589,7 +590,7 @@ class RedisCluster implements ClusterInterface, IteratorAggregate, Countable } /** - * {@inheritdoc} + * @return int */ #[ReturnTypeWillChange] public function count() @@ -598,7 +599,7 @@ class RedisCluster implements ClusterInterface, IteratorAggregate, Countable } /** - * {@inheritdoc} + * @return Traversable */ #[ReturnTypeWillChange] public function getIterator() diff --git a/src/Monitor/Consumer.php b/src/Monitor/Consumer.php index eb46b049..9076bf12 100644 --- a/src/Monitor/Consumer.php +++ b/src/Monitor/Consumer.php @@ -90,7 +90,7 @@ class Consumer implements Iterator } /** - * {@inheritdoc} + * @return void */ #[ReturnTypeWillChange] public function rewind() @@ -110,7 +110,7 @@ class Consumer implements Iterator } /** - * {@inheritdoc} + * @return int|null */ #[ReturnTypeWillChange] public function key() @@ -119,7 +119,7 @@ class Consumer implements Iterator } /** - * {@inheritdoc} + * @return void */ #[ReturnTypeWillChange] public function next() diff --git a/src/PubSub/AbstractConsumer.php b/src/PubSub/AbstractConsumer.php index f764693d..7c77e331 100644 --- a/src/PubSub/AbstractConsumer.php +++ b/src/PubSub/AbstractConsumer.php @@ -151,7 +151,7 @@ abstract class AbstractConsumer implements Iterator abstract protected function writeRequest($method, $arguments); /** - * {@inheritdoc} + * @return void */ #[ReturnTypeWillChange] public function rewind() @@ -172,7 +172,7 @@ abstract class AbstractConsumer implements Iterator } /** - * {@inheritdoc} + * @return int|null */ #[ReturnTypeWillChange] public function key() @@ -181,7 +181,7 @@ abstract class AbstractConsumer implements Iterator } /** - * {@inheritdoc} + * @return int|null */ #[ReturnTypeWillChange] public function next() diff --git a/src/Response/Iterator/MultiBulkIterator.php b/src/Response/Iterator/MultiBulkIterator.php index cbc74a12..cbc61385 100644 --- a/src/Response/Iterator/MultiBulkIterator.php +++ b/src/Response/Iterator/MultiBulkIterator.php @@ -34,7 +34,7 @@ abstract class MultiBulkIterator implements Iterator, Countable, ResponseInterfa protected $size; /** - * {@inheritdoc} + * @return void */ #[ReturnTypeWillChange] public function rewind() @@ -43,7 +43,7 @@ abstract class MultiBulkIterator implements Iterator, Countable, ResponseInterfa } /** - * {@inheritdoc} + * @return mixed */ #[ReturnTypeWillChange] public function current() @@ -52,7 +52,7 @@ abstract class MultiBulkIterator implements Iterator, Countable, ResponseInterfa } /** - * {@inheritdoc} + * @return int|null */ #[ReturnTypeWillChange] public function key() @@ -61,7 +61,7 @@ abstract class MultiBulkIterator implements Iterator, Countable, ResponseInterfa } /** - * {@inheritdoc} + * @return void */ #[ReturnTypeWillChange] public function next() @@ -72,7 +72,7 @@ abstract class MultiBulkIterator implements Iterator, Countable, ResponseInterfa } /** - * {@inheritdoc} + * @return bool */ #[ReturnTypeWillChange] public function valid() diff --git a/src/Response/Iterator/MultiBulkTuple.php b/src/Response/Iterator/MultiBulkTuple.php index 77019aa8..4761f0ec 100644 --- a/src/Response/Iterator/MultiBulkTuple.php +++ b/src/Response/Iterator/MultiBulkTuple.php @@ -63,7 +63,7 @@ class MultiBulkTuple extends MultiBulk implements OuterIterator } /** - * {@inheritdoc} + * @return MultiBulk */ #[ReturnTypeWillChange] public function getInnerIterator() diff --git a/src/Session/Handler.php b/src/Session/Handler.php index 2e22a181..7b91a5ee 100644 --- a/src/Session/Handler.php +++ b/src/Session/Handler.php @@ -53,7 +53,9 @@ class Handler implements SessionHandlerInterface } /** - * {@inheritdoc} + * @param string $save_path + * @param string $session_id + * @return bool */ #[ReturnTypeWillChange] public function open($save_path, $session_id) @@ -63,7 +65,7 @@ class Handler implements SessionHandlerInterface } /** - * {@inheritdoc} + * @return bool */ #[ReturnTypeWillChange] public function close() @@ -73,7 +75,8 @@ class Handler implements SessionHandlerInterface } /** - * {@inheritdoc} + * @param int $maxlifetime + * @return bool */ #[ReturnTypeWillChange] public function gc($maxlifetime) @@ -83,7 +86,8 @@ class Handler implements SessionHandlerInterface } /** - * {@inheritdoc} + * @param string $session_id + * @return string */ #[ReturnTypeWillChange] public function read($session_id) @@ -96,7 +100,9 @@ class Handler implements SessionHandlerInterface } /** - * {@inheritdoc} + * @param string $session_id + * @param string $session_data + * @return bool */ #[ReturnTypeWillChange] public function write($session_id, $session_data) @@ -107,7 +113,8 @@ class Handler implements SessionHandlerInterface } /** - * {@inheritdoc} + * @param string $session_id + * @return bool */ #[ReturnTypeWillChange] public function destroy($session_id) From e8ea05dafe2f9cc6806adefd0c117ccfffd413c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Till=20Kru=CC=88ss?= Date: Wed, 19 Apr 2023 13:52:53 -0700 Subject: [PATCH 3/9] spacing --- src/Command/Processor/ProcessorChain.php | 8 ++++---- src/Session/Handler.php | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Command/Processor/ProcessorChain.php b/src/Command/Processor/ProcessorChain.php index 30589556..1ce915e2 100644 --- a/src/Command/Processor/ProcessorChain.php +++ b/src/Command/Processor/ProcessorChain.php @@ -93,7 +93,7 @@ class ProcessorChain implements ArrayAccess, ProcessorInterface } /** - * @param int $index + * @param int $index * @return bool */ #[ReturnTypeWillChange] @@ -103,7 +103,7 @@ class ProcessorChain implements ArrayAccess, ProcessorInterface } /** - * @param int $index + * @param int $index * @return ProcessorInterface */ #[ReturnTypeWillChange] @@ -113,7 +113,7 @@ class ProcessorChain implements ArrayAccess, ProcessorInterface } /** - * @param int $index + * @param int $index * @param ProcessorInterface $processor * @return void */ @@ -130,7 +130,7 @@ class ProcessorChain implements ArrayAccess, ProcessorInterface } /** - * @param int $index + * @param int $index * @return void */ #[ReturnTypeWillChange] diff --git a/src/Session/Handler.php b/src/Session/Handler.php index 7b91a5ee..68c87378 100644 --- a/src/Session/Handler.php +++ b/src/Session/Handler.php @@ -75,7 +75,7 @@ class Handler implements SessionHandlerInterface } /** - * @param int $maxlifetime + * @param int $maxlifetime * @return bool */ #[ReturnTypeWillChange] @@ -113,7 +113,7 @@ class Handler implements SessionHandlerInterface } /** - * @param string $session_id + * @param string $session_id * @return bool */ #[ReturnTypeWillChange] From 538c65946d524f31f4a274504a0de0838ed41ae0 Mon Sep 17 00:00:00 2001 From: Vladyslav Vildanov <117659936+vladvildanov@users.noreply.github.com> Date: Wed, 3 May 2023 21:00:31 +0300 Subject: [PATCH 4/9] Added timeout to prevent search before create (#1269) --- tests/Predis/Command/Redis/Search/FTSEARCH_Test.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/Predis/Command/Redis/Search/FTSEARCH_Test.php b/tests/Predis/Command/Redis/Search/FTSEARCH_Test.php index ecbf593f..58254af5 100644 --- a/tests/Predis/Command/Redis/Search/FTSEARCH_Test.php +++ b/tests/Predis/Command/Redis/Search/FTSEARCH_Test.php @@ -79,6 +79,9 @@ class FTSEARCH_Test extends PredisCommandTestCase $ftCreateResponse = $redis->ftcreate('idx_json', $schema, $createArguments); $this->assertEquals('OK', $ftCreateResponse); + // Timeout to make sure that index created before search performed. + usleep(2000); + $ftSearchArguments = new SearchArguments(); $ftSearchArguments->addReturn(2, 'arr', 'val'); From 946c4b7bd718cad74a5cb0f012bc9e83609e2e38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Till=20Kr=C3=BCss?= Date: Tue, 9 May 2023 10:39:00 -0700 Subject: [PATCH 5/9] [v2.x] Relay support (#1263) --- .gitattributes | 1 + .github/workflows/stack.yml | 8 +- .github/workflows/tests.yml | 15 +- CHANGELOG.md | 3 +- FAQ.md | 96 ++--- README.md | 27 +- composer.json | 3 + examples/pubsub_consumer.php | 6 +- examples/relay_compression.php | 51 +++ examples/relay_connection.php | 55 +++ examples/relay_events.php | 61 ++++ examples/relay_pubsub_consumer.php | 59 +++ phpunit.relay.xml | 42 +++ phpunit.xml.dist | 12 +- src/Client.php | 58 ++- src/Command/Redis/ACL.php | 24 ++ src/Command/Redis/COMMAND.php | 11 + src/Command/Redis/CONFIG.php | 4 + src/Command/Redis/HGETALL.php | 4 + src/Command/Redis/HRANDFIELD.php | 19 + src/Command/Redis/LCS.php | 4 + src/Command/Redis/TDigest/TDIGESTBYRANK.php | 27 ++ .../Redis/TDigest/TDIGESTBYREVRANK.php | 27 ++ src/Command/Redis/TDigest/TDIGESTCDF.php | 27 ++ src/Command/Redis/TDigest/TDIGESTMAX.php | 21 ++ src/Command/Redis/TDigest/TDIGESTMIN.php | 21 ++ src/Command/Redis/TDigest/TDIGESTQUANTILE.php | 27 ++ .../Redis/TDigest/TDIGESTTRIMMED_MEAN.php | 21 ++ src/Command/Redis/TYPE.php | 22 ++ src/Command/Redis/ZPOPMAX.php | 6 +- src/Command/Redis/ZPOPMIN.php | 6 +- src/Command/Redis/ZRANGE.php | 6 +- src/Command/Traits/With/WithScores.php | 4 +- src/Configuration/Option/Connections.php | 8 + src/Connection/ParametersInterface.php | 7 +- src/Connection/RelayConnection.php | 337 ++++++++++++++++++ src/Connection/RelayMethods.php | 136 +++++++ src/Pipeline/Pipeline.php | 2 +- src/Pipeline/RelayAtomic.php | 69 ++++ src/Pipeline/RelayPipeline.php | 75 ++++ src/PubSub/AbstractConsumer.php | 4 +- src/PubSub/Consumer.php | 10 +- src/PubSub/RelayConsumer.php | 114 ++++++ src/Transaction/MultiExec.php | 44 ++- tests/PHPUnit/PredisConnectionTestCase.php | 10 + tests/PHPUnit/PredisTestCase.php | 7 +- tests/Predis/Command/Redis/BZMPOP_Test.php | 2 +- tests/Predis/Command/Redis/BZPOPMAX_Test.php | 2 +- tests/Predis/Command/Redis/BZPOPMIN_Test.php | 2 +- tests/Predis/Command/Redis/CLIENT_Test.php | 1 + tests/Predis/Command/Redis/COMMAND_Test.php | 4 + tests/Predis/Command/Redis/DISCARD_Test.php | 19 +- tests/Predis/Command/Redis/EXEC_Test.php | 2 +- tests/Predis/Command/Redis/EXPIREAT_Test.php | 2 +- tests/Predis/Command/Redis/EXPIRE_Test.php | 2 +- tests/Predis/Command/Redis/FCALL_Test.php | 3 + tests/Predis/Command/Redis/FUNCTIONS_Test.php | 6 + tests/Predis/Command/Redis/GEOADD_Test.php | 2 +- tests/Predis/Command/Redis/GETBIT_Test.php | 6 +- tests/Predis/Command/Redis/HMGET_Test.php | 24 ++ tests/Predis/Command/Redis/MIGRATE_Test.php | 13 + tests/Predis/Command/Redis/MONITOR_Test.php | 1 + tests/Predis/Command/Redis/MOVE_Test.php | 1 - tests/Predis/Command/Redis/MULTI_Test.php | 21 ++ tests/Predis/Command/Redis/PING_Test.php | 16 + .../Predis/Command/Redis/PSUBSCRIBE_Test.php | 1 + tests/Predis/Command/Redis/PUBLISH_Test.php | 1 + .../Command/Redis/PUNSUBSCRIBE_Test.php | 1 + tests/Predis/Command/Redis/QUIT_Test.php | 1 + tests/Predis/Command/Redis/SELECT_Test.php | 1 + tests/Predis/Command/Redis/SUBSCRIBE_Test.php | 1 + .../Command/Redis/Search/FTAGGREGATE_Test.php | 4 + .../Command/Redis/Search/FTCURSOR_Test.php | 4 + .../Command/Redis/Search/FTEXPLAIN_Test.php | 4 + .../Command/Redis/Search/FTINFO_Test.php | 3 + .../Redis/Search/FTSPELLCHECK_Test.php | 2 +- .../Command/Redis/Search/FTSUGGET_Test.php | 6 +- .../Command/Redis/Search/FTSUGLEN_Test.php | 4 + .../Redis/TDigest/TDIGESTBYRANK_Test.php | 4 +- .../Redis/TDigest/TDIGESTBYREVRANK_Test.php | 4 +- .../Command/Redis/TDigest/TDIGESTCDF_Test.php | 4 +- .../Command/Redis/TDigest/TDIGESTMAX_Test.php | 4 +- .../Redis/TDigest/TDIGESTMERGE_Test.php | 10 +- .../Command/Redis/TDigest/TDIGESTMIN_Test.php | 4 +- .../Redis/TDigest/TDIGESTQUANTILE_Test.php | 4 +- .../Redis/TDigest/TDIGESTRESET_Test.php | 4 +- .../TDigest/TDIGESTTRIMMED_MEAN_Test.php | 4 +- .../Command/Redis/TimeSeries/TSADD_Test.php | 4 + .../Command/Redis/TimeSeries/TSALTER_Test.php | 4 + .../Redis/TimeSeries/TSCREATERULE_Test.php | 4 + .../Redis/TimeSeries/TSCREATE_Test.php | 4 + .../Redis/TimeSeries/TSDECRBY_Test.php | 4 + .../Redis/TimeSeries/TSDELETERULE_Test.php | 4 + .../Command/Redis/TimeSeries/TSDEL_Test.php | 4 + .../Command/Redis/TimeSeries/TSGET_Test.php | 4 + .../Redis/TimeSeries/TSINCRBY_Test.php | 4 + .../Command/Redis/TimeSeries/TSINFO_Test.php | 4 + .../Command/Redis/TimeSeries/TSMADD_Test.php | 4 + .../Command/Redis/TimeSeries/TSMGET_Test.php | 4 + .../Redis/TimeSeries/TSMRANGE_Test.php | 4 + .../Redis/TimeSeries/TSMREVRANGE_Test.php | 4 + .../Redis/TimeSeries/TSQUERYINDEX_Test.php | 4 + .../Command/Redis/TimeSeries/TSRANGE_Test.php | 4 + .../Redis/TimeSeries/TSREVRANGE_Test.php | 4 + .../Command/Redis/TopK/TOPKINFO_Test.php | 2 +- .../Command/Redis/TopK/TOPKRESERVE_Test.php | 2 +- .../Predis/Command/Redis/UNSUBSCRIBE_Test.php | 1 + tests/Predis/Command/Redis/UNWATCH_Test.php | 14 + tests/Predis/Command/Redis/WATCH_Test.php | 1 + tests/Predis/Command/Redis/ZADD_Test.php | 8 +- tests/Predis/Command/Redis/ZINCRBY_Test.php | 8 +- .../Predis/Command/Redis/ZINTERSTORE_Test.php | 2 +- tests/Predis/Command/Redis/ZINTER_Test.php | 2 +- tests/Predis/Command/Redis/ZMPOP_Test.php | 2 +- tests/Predis/Command/Redis/ZMSCORE_Test.php | 2 +- tests/Predis/Command/Redis/ZPOPMAX_Test.php | 9 +- tests/Predis/Command/Redis/ZPOPMIN_Test.php | 9 +- .../Command/Redis/ZRANGEBYSCORE_Test.php | 6 +- tests/Predis/Command/Redis/ZRANGE_Test.php | 4 +- .../Command/Redis/ZREVRANGEBYSCORE_Test.php | 6 +- tests/Predis/Command/Redis/ZREVRANGE_Test.php | 4 +- tests/Predis/Command/Redis/ZSCORE_Test.php | 6 +- .../Predis/Command/Redis/ZUNIONSTORE_Test.php | 2 +- tests/Predis/Command/Redis/ZUNION_Test.php | 2 +- .../Configuration/Option/ConnectionsTest.php | 3 +- .../Connection/Cluster/RedisClusterTest.php | 1 + tests/Predis/Connection/ParametersTest.php | 17 + .../Predis/Connection/RelayConnectionTest.php | 234 ++++++++++++ tests/Predis/Transaction/MultiExecTest.php | 20 ++ tests/README.md | 2 +- 130 files changed, 2037 insertions(+), 205 deletions(-) create mode 100644 examples/relay_compression.php create mode 100644 examples/relay_connection.php create mode 100644 examples/relay_events.php create mode 100644 examples/relay_pubsub_consumer.php create mode 100644 phpunit.relay.xml create mode 100644 src/Connection/RelayConnection.php create mode 100644 src/Connection/RelayMethods.php create mode 100644 src/Pipeline/RelayAtomic.php create mode 100644 src/Pipeline/RelayPipeline.php create mode 100644 src/PubSub/RelayConsumer.php create mode 100644 tests/Predis/Connection/RelayConnectionTest.php diff --git a/.gitattributes b/.gitattributes index 24d268ad..226cb6ab 100644 --- a/.gitattributes +++ b/.gitattributes @@ -13,6 +13,7 @@ /CONTRIBUTING.md export-ignore linguist-documentation /FAQ.md export-ignore linguist-documentation /VERSION export-ignore +/phpunit.relay.xml export-ignore /phpunit.xml.dist export-ignore /phpstan.dist.neon export-ignore /phpstan-tests.dist.neon export-ignore diff --git a/.github/workflows/stack.yml b/.github/workflows/stack.yml index df25cac9..c5a7ad60 100644 --- a/.github/workflows/stack.yml +++ b/.github/workflows/stack.yml @@ -41,6 +41,7 @@ jobs: uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} + extensions: relay - name: Get Composer cache directory id: composer-cache @@ -58,5 +59,8 @@ jobs: PHP_VERSION: ${{ matrix.php }} run: composer install --ansi --no-progress --prefer-dist - - name: Run PHPUnit tests - run: vendor/bin/phpunit + - name: Run tests + run: vendor/bin/phpunit --group realm-stack + + - name: Run tests using Relay + run: vendor/bin/phpunit --group realm-stack -c phpunit.relay.xml diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 647a0029..b5259142 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -14,7 +14,7 @@ concurrency: jobs: predis: - name: PHP ${{ matrix.php }} Redis ${{ matrix.redis }} + name: PHP ${{ matrix.php }} (Redis ${{ matrix.redis }}) runs-on: ubuntu-latest strategy: @@ -50,6 +50,7 @@ jobs: uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} + extensions: relay coverage: ${{ (matrix.php == '8.1' && matrix.redis == '7') && 'xdebug' || 'none' }} - name: Install Composer dependencies @@ -58,13 +59,17 @@ jobs: dependency-versions: highest composer-options: ${{ matrix.php == '8.0' && '--ignore-platform-reqs' || '' }} - - name: Run PHPUnit tests + - name: Run tests if: ${{ matrix.php != '8.1' || matrix.redis != '7' }} - run: vendor/bin/phpunit --verbose --exclude-group realm-stack + run: vendor/bin/phpunit - - name: Run PHPUnit tests with coverage + - name: Run tests with coverage if: ${{ matrix.php == '8.1' && matrix.redis == '7' }} - run: vendor/bin/phpunit --verbose --exclude-group realm-stack --coverage-clover build/logs/clover.xml --coverage-filter ./src + run: vendor/bin/phpunit --coverage-clover build/logs/clover.xml --coverage-filter ./src + + - name: Run tests using Relay + if: ${{ matrix.redis >= '6' }} + run: vendor/bin/phpunit -c phpunit.relay.xml - name: Send coverage to Coveralls env: diff --git a/CHANGELOG.md b/CHANGELOG.md index ceb2660a..f89c35f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,12 +3,13 @@ ## Unreleased ### Added -- Added support for `ACL SETUSER, GETUSER, DRYRUN` commands +- Added support for [Relay](https://github.com/predis/predis/wiki/Using-Relay) (#1263) - Added support for `FCALL_RO` command - Added support for `Redis JSON` module - Added support for `Redis Bloom` module - Added support for `Redis Search` module - Added support for `Redis TimeSeries` module +- Added support for `ACL SETUSER, GETUSER, DRYRUN` commands ### Fixed - Fixed prefixes for `XTRIM` and `XREVRANGE` commands diff --git a/FAQ.md b/FAQ.md index ed96cf31..65d34a0b 100644 --- a/FAQ.md +++ b/FAQ.md @@ -1,7 +1,6 @@ -# Some frequently asked questions about Predis # -________________________________________________ +# Frequently asked questions about Predis # -### What is the point of Predis? ### +## What is the point of Predis? ## The main point of Predis is about offering a highly customizable and extensible client for Redis, that can be easily extended by developers while still being reasonably fast. With Predis you can @@ -13,12 +12,12 @@ a great asset since it allows developers to add new and still missing features o the standard behaviour of the library without the need to break dependencies in production code (at least to some degree). -### Does Predis support UNIX domain sockets and persistent connections? ### +## Does Predis support UNIX domain sockets and persistent connections? ## Yes. Obviously persistent connections actually work only when using PHP configured as a persistent process reused by the web server (see [PHP-FPM](http://php-fpm.org)). -### Does Predis support SSL-encrypted connections? ### +## Does Predis support SSL-encrypted connections? ## Yes. Encrypted connections are mostly useful when connecting to Redis instances exposed by various cloud hosting providers without the need to configure an SSL proxy, but you should also take into @@ -26,16 +25,21 @@ account the general performances degradation especially during the connect() ope handshake must be performed to secure the connection. Persistent SSL-encrypted connections may help in that respect, but they are supported only when running on PHP >= 7.0.0. -### Does Predis support transparent (de)serialization of values? ### +## Does Predis support transparent (de)serialization of values? ## -No and it will not ever do that by default. The reason behind this decision is that serialization is -usually something that developers prefer to customize depending on their needs and can not be easily -generalized when using Redis because of the many possible access patterns for your data. This does -not mean that it is impossible to have such a feature since you can leverage the extensibility of -this library to define your own serialization-aware commands. You can find more details about how to -do that [on this issue](http://github.com/predis/predis/issues/29#issuecomment-1202624). +When using [Relay](https://github.com/cachewerk/relay) as the underlying client, several +serialization and compression algorithms are supported. This slightly increases CPU usage, +but significantly reduces bytes sent over the network and Redis memory usage. -### How can I force Predis to connect to Redis before sending any command? ### +Without Relay, Predis will not serialize data and will never do that by default. The reason +behind this decision is that serialization is usually something that developers prefer to +customize depending on their needs and can not be easilygeneralized when using Redis because +of the many possible access patterns for your data. This does not mean that it is impossible +to have such a feature since you can leverage the extensibility of this library to define +your own serialization-aware commands. You can find more details about how to do that +[on this issue](http://github.com/predis/predis/issues/29#issuecomment-1202624). + +## How can I force Predis to connect to Redis before sending any command? ## Explicitly connecting to Redis is usually not needed since the client initializes connections lazily only when they are needed. Admittedly, this behavior can be inconvenient in certain scenarios when @@ -55,7 +59,7 @@ try { $client->info(); ``` -### How Predis abstracts Redis commands? ### +## How Predis abstracts Redis commands? ## The approach used to implement Redis commands is quite simple: by default each command follows the same signature as defined on the [Redis documentation](http://redis.io/commands) which makes things @@ -75,12 +79,20 @@ $client->hmset('my:hash', ['field1'=>'value1', 'field2'=>'value2']); // single n An exception to this rule is [`SORT`](http://redis.io/commands/sort) for which modifiers are passed [using a named array](tests/Predis/Command/KeySortTest.php#L54-L75). +## When should I use Relay? ## -# Speaking about performances... # -_________________________________________________ +If you care about performance, __always__. [Relay](https://github.com/cachewerk/relay) is free to use. +## When should I use PhpRedis? ### -### Predis is a pure-PHP implementation: it can not be fast enough! ### +Predis is fast enough when Redis is located on the same machine as PHP, more on that later. + +[PhpRedis](https://github.com/phpredis/phpredis) (and Relay) perform significantly better when +network I/O is involved, due to their ability to compress data by ~75%. Fewer bytes and received +sent over the network [means faster operations](https://akalongman.medium.com/phpredis-vs-predis-comparison-on-real-production-data-a819b48cbadb), +and potentially cost savings when network traffic isn't free (e.g. AWS Elasticache Inter-AZ transfer costs). + +## Predis is a pure-PHP implementation: it can not be fast enough! ## It really depends, but most of the times the answer is: _yes, it is fast enough_. I will give you a couple of easy numbers with a simple test that uses a single client and is executed by PHP 5.5.6 @@ -92,7 +104,7 @@ against a local instance of Redis 2.8 that runs under Ubuntu 13.10 on a Intel Q6 0.130 seconds to fetch 30000 keys using _KEYS *_. ``` -How does it compare with [__phpredis__](http://github.com/nicolasff/phpredis), a nice C extension +How does it compare with [__PhpRedis__](http://github.com/phpredis/phpredis), a nice C extension providing an efficient client for Redis? ``` @@ -101,7 +113,7 @@ providing an efficient client for Redis? 0.035 seconds to fetch 30000 keys using "KEYS *"". ``` -Wow __phpredis__ seems much faster! Well, we are comparing a C extension with a pure-PHP library so +Wow __PhpRedis__ seems much faster! Well, we are comparing a C extension with a pure-PHP library so lower numbers are quite expected but there is a fundamental flaw in them: is this really how you are going to use Redis in your application? Are you really going to send thousands of commands using a for-loop on each page request using a single client instance? If so... well I guess you are probably @@ -119,7 +131,7 @@ Using Predis: 3200 GET/sec while retrieving the very same values 0.132 seconds to fetch 30000 keys using "KEYS *". -Using phpredis: +Using PhpRedis: 3500 SET/sec using 12 bytes for both key and value 3500 GET/sec while retrieving the very same values 0.045 seconds to fetch 30000 keys using "KEYS *". @@ -131,47 +143,3 @@ that we are measuring the overhead of client libraries implementations and the e round-trip times, so we are not really measuring how fast Redis is. Redis shines best with thousands of concurrent clients doing requests! Also, actual performances should be measured according to how your application will use Redis. - -### I am convinced, but performances for multi-bulk responses are still worse ### - -Fair enough, but there is an option available if you need even more speed and consists on installing -__[phpiredis](http://github.com/nrk/phpiredis)__ (note the additional _i_ in the name) and let the -client use it. __phpiredis__ is another C extension that wraps __hiredis__ (the official C client -library for Redis) with a thin layer exposing its features to PHP. You can then choose between two -different connection classes: - - - `Predis\Connection\PhpiredisStreamConnection` (using native PHP streams). - - `Predis\Connection\PhpiredisSocketConnection` (requires `ext-socket`). - -You will now get the benefits of a faster protocol serializer and parser just by adding a couple of -lines of code: - -```php -$client = new Predis\Client('tcp://127.0.0.1', array( - 'connections' => array( - 'tcp' => 'Predis\Connection\PhpiredisStreamConnection', - 'unix' => 'Predis\Connection\PhpiredisSocketConnection', - ), -)); -``` - -Dead simple. Nothing changes in the way you use the library in your application. So how fast is it -our basic benchmark script now? There are not much improvements for inline or short bulk responses -like the ones returned by `SET` and `GET`, but the speed for parsing multi-bulk responses is now on -par with phpredis: - -``` -Fatching 30000 keys with _KEYS *_ using Predis paired with phpiredis:: - -0.035 seconds from a local Redis instance -0.047 seconds from a remote Redis instance -``` - -### If I need an extension to get better performances, why not using phpredis? ### - -Good question. Generically speaking if you need absolute uber-speed using Redis on the localhost and -you do not care about abstractions built around some Redis features such as MULTI / EXEC, or if you -do not need any kind of extensibility or guaranteed backwards compatibility with different versions -of Redis (Predis currently supports from 1.2 up to 2.8 and the current development version), then -using __phpredis__ makes absolutely sense. Otherwise, Predis is perfect for the job and by adding -__phpiredis__ you can get a nice speed bump almost for free. diff --git a/README.md b/README.md index 913af580..d7375470 100644 --- a/README.md +++ b/README.md @@ -396,6 +396,16 @@ $response = $client->lpushrand('random_values', $seed = mt_rand()); ### Customizable connection backends ### +Predis can use different connection backends to connect to Redis. The builtin Relay integration +leverages the [Relay](https://github.com/cachewerk/relay) extension for PHP for major performance +gains, by caching a partial replica of the Redis dataset in PHP shared runtime memory. + +```php +$client = new Predis\Client('tcp://127.0.0.1', [ + 'connections' => 'relay', +]); +``` + Developers can create their own connection classes to support whole new network backends, extend existing classes or provide completely different implementations. Connection classes must implement `Predis\Connection\NodeConnectionInterface` or extend `Predis\Connection\AbstractConnection`: @@ -439,23 +449,6 @@ be disabled. See [the tests README](tests/README.md) for more details about test Predis uses GitHub Actions for continuous integration and the history for past and current builds can be found [on its actions page](https://github.com/predis/predis/actions). - -## Other ## - - -### Project related links ### - -- [Source code](https://github.com/predis/predis) -- [Wiki](https://github.com/predis/predis/wiki) -- [Issue tracker](https://github.com/predis/predis/issues) - - -### Author ### - -- [Till Krüss](https://till.im) ([Twitter](http://twitter.com/tillkruss)) -- [Daniele Alessandri](mailto:suppakilla@gmail.com) ([twitter](http://twitter.com/JoL1hAHN)) - - ### License ### The code for Predis is distributed under the terms of the MIT license (see [LICENSE](LICENSE)). diff --git a/composer.json b/composer.json index 7968991c..f842e16a 100644 --- a/composer.json +++ b/composer.json @@ -29,6 +29,9 @@ "phpstan/phpstan": "^1.9", "phpunit/phpunit": "^8.0 || ~9.4.4" }, + "suggest": { + "ext-relay": "Faster connection with in-memory caching (>=0.6.2)" + }, "scripts": { "phpstan": "phpstan analyse", "style": "php-cs-fixer fix --diff --dry-run", diff --git a/examples/pubsub_consumer.php b/examples/pubsub_consumer.php index c593067e..61cc9fcd 100644 --- a/examples/pubsub_consumer.php +++ b/examples/pubsub_consumer.php @@ -24,10 +24,10 @@ $pubsub = $client->pubSubLoop(); // Subscribe to your channels $pubsub->subscribe('control_channel', 'notifications'); -// Start processing the pubsup messages. Open a terminal and use redis-cli +// Start processing the pubsub messages. Open a terminal and use redis-cli // to push messages to the channels. Examples: -// ./redis-cli PUBLISH notifications "this is a test" -// ./redis-cli PUBLISH control_channel quit_loop +// redis-cli PUBLISH notifications "this is a test" +// redis-cli PUBLISH control_channel quit_loop foreach ($pubsub as $message) { switch ($message->kind) { case 'subscribe': diff --git a/examples/relay_compression.php b/examples/relay_compression.php new file mode 100644 index 00000000..eb10a3d9 --- /dev/null +++ b/examples/relay_compression.php @@ -0,0 +1,51 @@ + 'igbinary', + 'compression' => 'lz4', +]; + +$client = new Predis\Client($single_server + $options, [ + 'connections' => 'relay', +]); + +$quote = (object) [ + 'author' => 'Jean-Luc Picard', + 'text' => 'I look forward to your report Mr. Broccoli.', +]; + +// Serialize object and apply LZ4 compression, then write key to Redis +$client->set('quote', $client->pack($quote)); + +// NOTE: In Predis v3.x serialization and compression will happen +// automatically without the need to call `pack()` and `unpack()` + +// Retrieve raw binary value from Redis +$raw = $client->get('quote'); + +// Decompress and unserialize binary value +$data = $client->unpack($raw); + +var_dump($quote == $data); // true + +var_dump($data); + +/* +object(stdClass)#11 (2) { + ["author"]=>string(15) "Jean-Luc Picard" + ["text"]=>string(43) "I look forward to your report Mr. Broccoli." +} +*/ diff --git a/examples/relay_connection.php b/examples/relay_connection.php new file mode 100644 index 00000000..f54e8fa3 --- /dev/null +++ b/examples/relay_connection.php @@ -0,0 +1,55 @@ + 1.0, + 'read_write_timeout' => 1.0, + + // Relay specific options + 'cache' => true, + // 'compression' => 'lz4', + // 'serializer' => 'igbinary', +]; + +$client = new Predis\Client($single_server + $options, [ + 'connections' => 'relay', +]); + +// Write key to Redis +$client->set('torpedo', mt_rand()); + +// Retrieve key from Redis +$client->get('torpedo'); + +// Retrieve key from Relay (without talking to Redis) +// This key is now available to all PHP workers in this FPM pool +$client->get('torpedo'); + +// For debugging only: +var_export( + $client->getConnection()->getClient()->_getKeys() +); + +/* +array ( + 'torpedo' => array ( + 0 => array ( + 'type' => 'string', + 'local-len' => 10, + 'remote-len' => 10, + 'size' => 10, + ), + ), +) +*/ diff --git a/examples/relay_events.php b/examples/relay_events.php new file mode 100644 index 00000000..cd37b0f3 --- /dev/null +++ b/examples/relay_events.php @@ -0,0 +1,61 @@ + 'relay', +]); + +/** @var Predis\Connection\RelayConnection $relay */ +$relay = $client->getConnection(); + +// establish connection +$client->ping(); + +// register `FLUSH*` callback +$relay->onFlushed( + static function (Relay\Event $event) use (&$key) { + echo 'Redis was flushed, unsetting $key...' . PHP_EOL; + $key = null; + } +); + +// register `INVALIDATE` callback +$relay->onInvalidated( + static function (Relay\Event $event) use (&$key) { + if ($event->key === 'library') { + echo "The `{$event->key}` key was invalidated, unsetting \$key..." . PHP_EOL; + $key = null; + } + } +); + +// Write key to Redis +$client->set('library', mt_rand()); + +// Retrieve key once from Redis, then cached in Relay and $key +$key = $client->get('library'); + +while (true) { + echo '$key is: ' . var_export($key, true) . PHP_EOL; + + // To trigger our event callbacks, we need to either interact with Relay: + $client->get(mt_rand()); + + // ... or alternatively dispatch events directly on Relay: + $relay->dispatchEvents(); + + sleep(1); +} diff --git a/examples/relay_pubsub_consumer.php b/examples/relay_pubsub_consumer.php new file mode 100644 index 00000000..43affa77 --- /dev/null +++ b/examples/relay_pubsub_consumer.php @@ -0,0 +1,59 @@ + 0], + ['connections' => 'relay'] +); + +// Initialize a new pubsub consumer. +$pubsub = $client->pubSubLoop(); + +// When using Relay you cannot use foreach-loops to iterate +// over messages instead use a callback function +$poorMansKafka = function ($message, $client) { + switch ($message->kind) { + case 'subscribe': + echo "Subscribed to {$message->channel}", PHP_EOL; + break; + + case 'message': + case 'pmessage': + if ($message->channel == 'control_channel') { + if ($message->payload == 'quit_loop') { + echo 'Aborting pubsub loop...', PHP_EOL; + $client->unsubscribe(); + } else { + echo "Received an unrecognized command: {$message->payload}.", PHP_EOL; + } + } else { + echo "Received the message from `{$message->channel}` channel:", + PHP_EOL, " {$message->payload}", PHP_EOL, PHP_EOL; + } + } +}; + +// Subscribe to your channels and start processing the messages. +$pubsub->subscribe('control_channel', 'notifications', $poorMansKafka); + +// Open a terminal and use redis-cli to push messages to the channels. Examples: +// redis-cli PUBLISH notifications "this is a test" +// redis-cli PUBLISH control_channel quit_loop + +// When using Relay, there is no need to unset the pubsub consumer instance when you are done + +// Say goodbye :-) +$version = redis_version($client->info()); +echo "Goodbye from Redis $version!", PHP_EOL; diff --git a/phpunit.relay.xml b/phpunit.relay.xml new file mode 100644 index 00000000..731f29c2 --- /dev/null +++ b/phpunit.relay.xml @@ -0,0 +1,42 @@ + + + + + + tests/Predis/ + + + + + + relay-incompatible + realm-webdis + realm-stack + ext-curl + ext-phpiredis + + + + + + src/ + + + + + + + + + + diff --git a/phpunit.xml.dist b/phpunit.xml.dist index dff6900b..d47afa8d 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -28,9 +28,11 @@ - ext-phpiredis - ext-curl realm-webdis + realm-stack + ext-relay + ext-curl + ext-phpiredis @@ -45,13 +47,9 @@ - - - - - + diff --git a/src/Client.php b/src/Client.php index 91c126f4..6e89678a 100644 --- a/src/Client.php +++ b/src/Client.php @@ -25,9 +25,15 @@ use Predis\Configuration\OptionsInterface; use Predis\Connection\ConnectionInterface; use Predis\Connection\Parameters; use Predis\Connection\ParametersInterface; +use Predis\Connection\RelayConnection; use Predis\Monitor\Consumer as MonitorConsumer; +use Predis\Pipeline\Atomic; +use Predis\Pipeline\FireAndForget; use Predis\Pipeline\Pipeline; +use Predis\Pipeline\RelayAtomic; +use Predis\Pipeline\RelayPipeline; use Predis\PubSub\Consumer as PubSubConsumer; +use Predis\PubSub\RelayConsumer as RelayPubSubConsumer; use Predis\Response\ErrorInterface as ErrorResponseInterface; use Predis\Response\ResponseInterface; use Predis\Response\ServerException; @@ -262,6 +268,32 @@ class Client implements ClientInterface, IteratorAggregate return $this->connection; } + /** + * Applies the configured serializer and compression to given value. + * + * @param mixed $value + * @return string + */ + public function pack($value) + { + return $this->connection instanceof RelayConnection + ? $this->connection->pack($value) + : $value; + } + + /** + * Deserializes and decompresses to given value. + * + * @param mixed $value + * @return string + */ + public function unpack($value) + { + return $this->connection instanceof RelayConnection + ? $this->connection->unpack($value) + : $value; + } + /** * Executes a command without filtering its arguments, parsing the response, * applying any prefix to keys or throwing exceptions on Redis errors even @@ -435,19 +467,29 @@ class Client implements ClientInterface, IteratorAggregate /** * Actual pipeline context initializer method. * - * @param array $options Options for the context. - * @param mixed $callable Optional callable used to execute the context. + * @param array|null $options Options for the context. + * @param mixed $callable Optional callable used to execute the context. * * @return Pipeline|array */ protected function createPipeline(array $options = null, $callable = null) { if (isset($options['atomic']) && $options['atomic']) { - $class = 'Predis\Pipeline\Atomic'; + $class = Atomic::class; } elseif (isset($options['fire-and-forget']) && $options['fire-and-forget']) { - $class = 'Predis\Pipeline\FireAndForget'; + $class = FireAndForget::class; } else { - $class = 'Predis\Pipeline\Pipeline'; + $class = Pipeline::class; + } + + if ($this->connection instanceof RelayConnection) { + if (isset($options['atomic']) && $options['atomic']) { + $class = RelayAtomic::class; + } elseif (isset($options['fire-and-forget']) && $options['fire-and-forget']) { + throw new NotSupportedException('The "relay" extension does not support fire-and-forget pipelines.'); + } else { + $class = RelayPipeline::class; + } } /* @@ -517,7 +559,11 @@ class Client implements ClientInterface, IteratorAggregate */ protected function createPubSub(array $options = null, $callable = null) { - $pubsub = new PubSubConsumer($this, $options); + if ($this->connection instanceof RelayConnection) { + $pubsub = new RelayPubSubConsumer($this, $options); + } else { + $pubsub = new PubSubConsumer($this, $options); + } if (!isset($callable)) { return $pubsub; diff --git a/src/Command/Redis/ACL.php b/src/Command/Redis/ACL.php index 4cfbdb25..e8999ea2 100644 --- a/src/Command/Redis/ACL.php +++ b/src/Command/Redis/ACL.php @@ -26,4 +26,28 @@ class ACL extends RedisCommand { return 'ACL'; } + + /** + * {@inheritdoc} + */ + public function parseResponse($data) + { + if (!is_array($data)) { + return $data; + } + + if ($data === array_values($data)) { + return $data; + } + + // flatten Relay (RESP3) maps + $return = []; + + array_walk($data, function ($value, $key) use (&$return) { + $return[] = $key; + $return[] = $value; + }); + + return $return; + } } diff --git a/src/Command/Redis/COMMAND.php b/src/Command/Redis/COMMAND.php index a215f47e..385d54ee 100644 --- a/src/Command/Redis/COMMAND.php +++ b/src/Command/Redis/COMMAND.php @@ -26,4 +26,15 @@ class COMMAND extends BaseCommand { return 'COMMAND'; } + + /** + * {@inheritdoc} + */ + public function parseResponse($data) + { + // Relay (RESP3) uses maps and it might be good + // to make the return value a breaking change + + return $data; + } } diff --git a/src/Command/Redis/CONFIG.php b/src/Command/Redis/CONFIG.php index 60d8271c..c60ac2dc 100644 --- a/src/Command/Redis/CONFIG.php +++ b/src/Command/Redis/CONFIG.php @@ -36,6 +36,10 @@ class CONFIG extends RedisCommand public function parseResponse($data) { if (is_array($data)) { + if ($data !== array_values($data)) { + return $data; // Relay + } + $result = []; for ($i = 0; $i < count($data); ++$i) { diff --git a/src/Command/Redis/HGETALL.php b/src/Command/Redis/HGETALL.php index 5db3eded..c5f566ba 100644 --- a/src/Command/Redis/HGETALL.php +++ b/src/Command/Redis/HGETALL.php @@ -32,6 +32,10 @@ class HGETALL extends RedisCommand */ public function parseResponse($data) { + if ($data !== array_values($data)) { + return $data; // Relay + } + $result = []; for ($i = 0; $i < count($data); ++$i) { diff --git a/src/Command/Redis/HRANDFIELD.php b/src/Command/Redis/HRANDFIELD.php index 0d0fb75d..62ce7dbe 100644 --- a/src/Command/Redis/HRANDFIELD.php +++ b/src/Command/Redis/HRANDFIELD.php @@ -31,4 +31,23 @@ class HRANDFIELD extends RedisCommand { return 'HRANDFIELD'; } + + /** + * {@inheritdoc} + */ + public function parseResponse($data) + { + if (!is_array($data)) { + return $data; + } + + // flatten Relay (RESP3) maps + $return = []; + + array_walk_recursive($data, function ($value) use (&$return) { + $return[] = $value; + }); + + return $return; + } } diff --git a/src/Command/Redis/LCS.php b/src/Command/Redis/LCS.php index e3f91697..e8663f45 100644 --- a/src/Command/Redis/LCS.php +++ b/src/Command/Redis/LCS.php @@ -57,6 +57,10 @@ class LCS extends RedisCommand public function parseResponse($data) { if (is_array($data)) { + if ($data !== array_values($data)) { + return $data; // Relay + } + return [$data[0] => $data[1], $data[2] => $data[3]]; } diff --git a/src/Command/Redis/TDigest/TDIGESTBYRANK.php b/src/Command/Redis/TDigest/TDIGESTBYRANK.php index a8b8d482..8fba75ec 100644 --- a/src/Command/Redis/TDigest/TDIGESTBYRANK.php +++ b/src/Command/Redis/TDigest/TDIGESTBYRANK.php @@ -25,4 +25,31 @@ class TDIGESTBYRANK extends RedisCommand { return 'TDIGEST.BYRANK'; } + + /** + * {@inheritdoc} + */ + public function parseResponse($data) + { + if (!is_array($data)) { + return $data; + } + + // convert Relay (RESP3) constants to strings + return array_map(function ($value) { + if (is_string($value) || !is_float($value)) { + return $value; + } + + if (is_nan($value)) { + return 'nan'; + } + + switch ($value) { + case INF: return 'inf'; + case -INF: return '-inf'; + default: return $value; + } + }, $data); + } } diff --git a/src/Command/Redis/TDigest/TDIGESTBYREVRANK.php b/src/Command/Redis/TDigest/TDIGESTBYREVRANK.php index 62322836..979270cc 100644 --- a/src/Command/Redis/TDigest/TDIGESTBYREVRANK.php +++ b/src/Command/Redis/TDigest/TDIGESTBYREVRANK.php @@ -25,4 +25,31 @@ class TDIGESTBYREVRANK extends RedisCommand { return 'TDIGEST.BYREVRANK'; } + + /** + * {@inheritdoc} + */ + public function parseResponse($data) + { + if (!is_array($data)) { + return $data; + } + + // convert Relay (RESP3) constants to strings + return array_map(function ($value) { + if (is_string($value) || !is_float($value)) { + return $value; + } + + if (is_nan($value)) { + return 'nan'; + } + + switch ($value) { + case INF: return 'inf'; + case -INF: return '-inf'; + default: return $value; + } + }, $data); + } } diff --git a/src/Command/Redis/TDigest/TDIGESTCDF.php b/src/Command/Redis/TDigest/TDIGESTCDF.php index 42aaefb4..3f58f9a7 100644 --- a/src/Command/Redis/TDigest/TDIGESTCDF.php +++ b/src/Command/Redis/TDigest/TDIGESTCDF.php @@ -27,4 +27,31 @@ class TDIGESTCDF extends RedisCommand { return 'TDIGEST.CDF'; } + + /** + * {@inheritdoc} + */ + public function parseResponse($data) + { + if (!is_array($data)) { + return $data; + } + + // convert Relay (RESP3) constants to strings + return array_map(function ($value) { + if (is_string($value) || !is_float($value)) { + return $value; + } + + if (is_nan($value)) { + return 'nan'; + } + + switch ($value) { + case INF: return 'inf'; + case -INF: return '-inf'; + default: return $value; + } + }, $data); + } } diff --git a/src/Command/Redis/TDigest/TDIGESTMAX.php b/src/Command/Redis/TDigest/TDIGESTMAX.php index 5dc86410..6441f24c 100644 --- a/src/Command/Redis/TDigest/TDIGESTMAX.php +++ b/src/Command/Redis/TDigest/TDIGESTMAX.php @@ -25,4 +25,25 @@ class TDIGESTMAX extends RedisCommand { return 'TDIGEST.MAX'; } + + /** + * {@inheritdoc} + */ + public function parseResponse($data) + { + if (is_string($data) || !is_float($data)) { + return $data; + } + + // convert Relay (RESP3) constants to strings + if (is_nan($data)) { + return 'nan'; + } + + switch ($data) { + case INF: return 'inf'; + case -INF: return '-inf'; + default: return $data; + } + } } diff --git a/src/Command/Redis/TDigest/TDIGESTMIN.php b/src/Command/Redis/TDigest/TDIGESTMIN.php index d997c841..472f07da 100644 --- a/src/Command/Redis/TDigest/TDIGESTMIN.php +++ b/src/Command/Redis/TDigest/TDIGESTMIN.php @@ -25,4 +25,25 @@ class TDIGESTMIN extends RedisCommand { return 'TDIGEST.MIN'; } + + /** + * {@inheritdoc} + */ + public function parseResponse($data) + { + if (is_string($data) || !is_float($data)) { + return $data; + } + + // convert Relay (RESP3) constants to strings + if (is_nan($data)) { + return 'nan'; + } + + switch ($data) { + case INF: return 'inf'; + case -INF: return '-inf'; + default: return $data; + } + } } diff --git a/src/Command/Redis/TDigest/TDIGESTQUANTILE.php b/src/Command/Redis/TDigest/TDIGESTQUANTILE.php index 7de94ffe..001ec0e3 100644 --- a/src/Command/Redis/TDigest/TDIGESTQUANTILE.php +++ b/src/Command/Redis/TDigest/TDIGESTQUANTILE.php @@ -25,4 +25,31 @@ class TDIGESTQUANTILE extends RedisCommand { return 'TDIGEST.QUANTILE'; } + + /** + * {@inheritdoc} + */ + public function parseResponse($data) + { + if (!is_array($data)) { + return $data; + } + + // convert Relay (RESP3) constants to strings + return array_map(function ($value) { + if (is_string($value) || !is_float($value)) { + return $value; + } + + if (is_nan($value)) { + return 'nan'; + } + + switch ($value) { + case INF: return 'inf'; + case -INF: return '-inf'; + default: return $value; + } + }, $data); + } } diff --git a/src/Command/Redis/TDigest/TDIGESTTRIMMED_MEAN.php b/src/Command/Redis/TDigest/TDIGESTTRIMMED_MEAN.php index 6658a5e9..2ccd3d34 100644 --- a/src/Command/Redis/TDigest/TDIGESTTRIMMED_MEAN.php +++ b/src/Command/Redis/TDigest/TDIGESTTRIMMED_MEAN.php @@ -26,4 +26,25 @@ class TDIGESTTRIMMED_MEAN extends RedisCommand { return 'TDIGEST.TRIMMED_MEAN'; } + + /** + * {@inheritdoc} + */ + public function parseResponse($data) + { + if (is_string($data) || !is_float($data)) { + return $data; + } + + // convert Relay (RESP3) constants to strings + if (is_nan($data)) { + return 'nan'; + } + + switch ($data) { + case INF: return 'inf'; + case -INF: return '-inf'; + default: return $data; + } + } } diff --git a/src/Command/Redis/TYPE.php b/src/Command/Redis/TYPE.php index dea01f28..dece6377 100644 --- a/src/Command/Redis/TYPE.php +++ b/src/Command/Redis/TYPE.php @@ -26,4 +26,26 @@ class TYPE extends RedisCommand { return 'TYPE'; } + + /** + * {@inheritdoc} + */ + public function parseResponse($data) + { + if (is_string($data)) { + return $data; + } + + // Relay types + switch ($data) { + case 0: return 'none'; + case 1: return 'string'; + case 2: return 'set'; + case 3: return 'list'; + case 4: return 'zset'; + case 5: return 'hash'; + case 6: return 'stream'; + default: return $data; + } + } } diff --git a/src/Command/Redis/ZPOPMAX.php b/src/Command/Redis/ZPOPMAX.php index 9f9c7c30..1ebf45b0 100644 --- a/src/Command/Redis/ZPOPMAX.php +++ b/src/Command/Redis/ZPOPMAX.php @@ -35,7 +35,11 @@ class ZPOPMAX extends RedisCommand $result = []; for ($i = 0; $i < count($data); ++$i) { - $result[$data[$i]] = $data[++$i]; + if (is_array($data[$i])) { + $result[$data[$i][0]] = $data[$i][1]; // Relay + } else { + $result[$data[$i]] = $data[++$i]; + } } return $result; diff --git a/src/Command/Redis/ZPOPMIN.php b/src/Command/Redis/ZPOPMIN.php index a58ece3e..5f561c8e 100644 --- a/src/Command/Redis/ZPOPMIN.php +++ b/src/Command/Redis/ZPOPMIN.php @@ -35,7 +35,11 @@ class ZPOPMIN extends RedisCommand $result = []; for ($i = 0; $i < count($data); ++$i) { - $result[$data[$i]] = $data[++$i]; + if (is_array($data[$i])) { + $result[$data[$i][0]] = $data[$i][1]; // Relay + } else { + $result[$data[$i]] = $data[++$i]; + } } return $result; diff --git a/src/Command/Redis/ZRANGE.php b/src/Command/Redis/ZRANGE.php index c06ee5da..2024ad4e 100644 --- a/src/Command/Redis/ZRANGE.php +++ b/src/Command/Redis/ZRANGE.php @@ -94,7 +94,11 @@ class ZRANGE extends RedisCommand $result = []; for ($i = 0; $i < count($data); ++$i) { - $result[$data[$i]] = $data[++$i]; + if (is_array($data[$i])) { + $result[$data[$i][0]] = $data[$i][1]; // Relay + } else { + $result[$data[$i]] = $data[++$i]; + } } return $result; diff --git a/src/Command/Traits/With/WithScores.php b/src/Command/Traits/With/WithScores.php index e98b4ea2..bc81d36c 100644 --- a/src/Command/Traits/With/WithScores.php +++ b/src/Command/Traits/With/WithScores.php @@ -53,7 +53,9 @@ trait WithScores $result = []; for ($i = 0, $iMax = count($data); $i < $iMax; ++$i) { - if ($data[$i + 1] ?? false) { + if (is_array($data[$i])) { + $result[$data[$i][0]] = $data[$i][1]; // Relay + } elseif (array_key_exists($i + 1, $data)) { $result[$data[$i]] = $data[++$i]; } } diff --git a/src/Configuration/Option/Connections.php b/src/Configuration/Option/Connections.php index 89bfb8f0..e37de4ca 100644 --- a/src/Configuration/Option/Connections.php +++ b/src/Configuration/Option/Connections.php @@ -19,6 +19,7 @@ use Predis\Connection\Factory; use Predis\Connection\FactoryInterface; use Predis\Connection\PhpiredisSocketConnection; use Predis\Connection\PhpiredisStreamConnection; +use Predis\Connection\RelayConnection; /** * Configures a new connection factory instance. @@ -89,6 +90,7 @@ class Connections implements OptionInterface * - "phpiredis-stream" maps tcp, redis, unix to PhpiredisStreamConnection * - "phpiredis-socket" maps tcp, redis, unix to PhpiredisSocketConnection * - "phpiredis" is an alias of "phpiredis-stream" + * - "relay" maps tcp, redis, unix, tls, rediss to RelayConnection * * @param OptionsInterface $options Client options * @param string $value Descriptive string identifying the desired configuration @@ -116,6 +118,12 @@ class Connections implements OptionInterface $factory->define('unix', PhpiredisSocketConnection::class); break; + case 'relay': + $factory->define('tcp', RelayConnection::class); + $factory->define('redis', RelayConnection::class); + $factory->define('unix', RelayConnection::class); + break; + case 'default': return $factory; diff --git a/src/Connection/ParametersInterface.php b/src/Connection/ParametersInterface.php index 25c7e1ae..37ed97f7 100644 --- a/src/Connection/ParametersInterface.php +++ b/src/Connection/ParametersInterface.php @@ -26,11 +26,14 @@ namespace Predis\Connection; * @property string $alias Alias for the connection. * @property float $timeout Timeout for the connect() operation. * @property float $read_write_timeout Timeout for read() and write() operations. - * @property bool $async_connect Performs the connect() operation asynchronously. - * @property bool $tcp_nodelay Toggles the Nagle's algorithm for coalescing. * @property bool $persistent Leaves the connection open after a GC collection. * @property string $password Password to access Redis (see the AUTH command). * @property string $database Database index (see the SELECT command). + * @property bool $async_connect Performs the connect() operation asynchronously. + * @property bool $tcp_nodelay Toggles the Nagle's algorithm for coalescing. + * @property bool $cache (Relay only) Whether to use in-memory caching. + * @property string $serializer (Relay only) Serializer used for data serialization. + * @property string $compression (Relay only) Algorithm used for data compression. */ interface ParametersInterface { diff --git a/src/Connection/RelayConnection.php b/src/Connection/RelayConnection.php new file mode 100644 index 00000000..4ff674f5 --- /dev/null +++ b/src/Connection/RelayConnection.php @@ -0,0 +1,337 @@ +assertExtensions(); + + $this->parameters = $this->assertParameters($parameters); + $this->client = $this->createClient(); + } + + /** + * {@inheritdoc} + */ + public function isConnected() + { + return $this->client->isConnected(); + } + + /** + * {@inheritdoc} + */ + public function disconnect() + { + if ($this->client->isConnected()) { + $this->client->close(); + } + } + + /** + * Checks if the Relay extension is loaded in PHP. + */ + private function assertExtensions() + { + if (!extension_loaded('relay')) { + throw new NotSupportedException( + 'The "relay" extension is required by this connection backend.' + ); + } + } + + /** + * {@inheritdoc} + */ + protected function assertParameters(ParametersInterface $parameters) + { + if (!in_array($parameters->scheme, ['tcp', 'tls', 'unix', 'redis', 'rediss'])) { + throw new InvalidArgumentException("Invalid scheme: '{$parameters->scheme}'."); + } + + if (!in_array($parameters->serializer, [null, 'php', 'igbinary', 'msgpack', 'json'])) { + throw new InvalidArgumentException("Invalid serializer: '{$parameters->serializer}'."); + } + + if (!in_array($parameters->compression, [null, 'lzf', 'lz4', 'zstd'])) { + throw new InvalidArgumentException("Invalid compression algorithm: '{$parameters->compression}'."); + } + + return $parameters; + } + + /** + * Creates a new instance of the client. + * + * @return \Relay\Relay + */ + private function createClient() + { + $client = new Relay(); + + // throw when errors occur and return `null` for non-existent keys + $client->setOption(Relay::OPT_PHPREDIS_COMPATIBILITY, false); + + // use reply literals + $client->setOption(Relay::OPT_REPLY_LITERAL, true); + + // disable Relay's command/connection retry + $client->setOption(Relay::OPT_MAX_RETRIES, 0); + + // whether to use in-memory caching + $client->setOption(Relay::OPT_USE_CACHE, $this->parameters->cache ?? true); + + // set data serializer + $client->setOption(Relay::OPT_SERIALIZER, constant(sprintf( + '%s::SERIALIZER_%s', + Relay::class, + strtoupper($this->parameters->serializer ?? 'none') + ))); + + // set data compression algorithm + $client->setOption(Relay::OPT_COMPRESSION, constant(sprintf( + '%s::COMPRESSION_%s', + Relay::class, + strtoupper($this->parameters->compression ?? 'none') + ))); + + return $client; + } + + /** + * Returns the underlying client. + * + * @return \Relay\Relay + */ + public function getClient() + { + return $this->client; + } + + /** + * {@inheritdoc} + */ + protected function getIdentifier() + { + return $this->client->endpointId(); + } + + /** + * {@inheritdoc} + */ + protected function createStreamSocket(ParametersInterface $parameters, $address, $flags) + { + $timeout = isset($parameters->timeout) ? (float) $parameters->timeout : 5.0; + + $retry_interval = 0; + $read_timeout = 5.0; + + if (isset($parameters->read_write_timeout)) { + $read_timeout = (float) $parameters->read_write_timeout; + $read_timeout = $read_timeout > 0 ? $read_timeout : 0; + } + + try { + $this->client->connect( + $parameters->path ?? $parameters->host, + isset($parameters->path) ? 0 : $parameters->port, + $timeout, + null, + $retry_interval, + $read_timeout + ); + } catch (RelayException $ex) { + $this->onConnectionError($ex->getMessage(), $ex->getCode()); + } + + return $this->client; + } + + /** + * {@inheritdoc} + */ + public function executeCommand(CommandInterface $command) + { + if (!$this->client->isConnected()) { + $this->getResource(); + } + + try { + $name = $command->getId(); + + // When using compression or a serializer, we'll need a dedicated + // handler for `Predis\Command\RawCommand` calls, currently both + // parameters are unsupported until a future Relay release + return in_array($name, $this->atypicalCommands) + ? $this->client->{$name}(...$command->getArguments()) + : $this->client->rawCommand($name, ...$command->getArguments()); + } catch (RelayException $ex) { + throw $this->onCommandError($ex, $command); + } + } + + /** + * {@inheritdoc} + */ + public function onCommandError(RelayException $exception, CommandInterface $command) + { + $code = $exception->getCode(); + $message = $exception->getMessage(); + + if (strpos($message, 'RELAY_ERR_IO')) { + return new ConnectionException($this, $message, $code, $exception); + } + + if (strpos($message, 'RELAY_ERR_REDIS')) { + return new ServerException($message, $code, $exception); + } + + if (strpos($message, 'RELAY_ERR_WRONGTYPE') && strpos($message, "Got reply-type 'status'")) { + $message = 'Operation against a key holding the wrong kind of value'; + } + + return new ClientException($message, $code, $exception); + } + + /** + * Applies the configured serializer and compression to given value. + * + * @param mixed $value + * @return string + */ + public function pack($value) + { + return $this->client->_pack($value); + } + + /** + * Deserializes and decompresses to given value. + * + * @param mixed $value + * @return string + */ + public function unpack($value) + { + return $this->client->_unpack($value); + } + + /** + * {@inheritdoc} + */ + public function writeRequest(CommandInterface $command) + { + throw new NotSupportedException('The "relay" extension does not support writing requests.'); + } + + /** + * {@inheritdoc} + */ + public function readResponse(CommandInterface $command) + { + throw new NotSupportedException('The "relay" extension does not support reading responses.'); + } + + /** + * {@inheritdoc} + */ + public function __destruct() + { + $this->disconnect(); + } + + /** + * {@inheritdoc} + */ + public function __wakeup() + { + $this->assertExtensions(); + $this->client = $this->createClient(); + } +} diff --git a/src/Connection/RelayMethods.php b/src/Connection/RelayMethods.php new file mode 100644 index 00000000..0e460a6e --- /dev/null +++ b/src/Connection/RelayMethods.php @@ -0,0 +1,136 @@ +client->onFlushed($callback); + } + + /** + * Registers a new `invalidated` event listener. + * + * @param callable $callback + * @param string $pattern + * @return bool + */ + public function onInvalidated(?callable $callback, ?string $pattern = null) + { + return $this->client->onInvalidated($callback, $pattern); + } + + /** + * Dispatches all pending events. + * + * @return int|false + */ + public function dispatchEvents() + { + return $this->client->dispatchEvents(); + } + + /** + * Adds ignore pattern(s). Matching keys will not be cached in memory. + * + * @param string $pattern,... + * @return int + */ + public function addIgnorePatterns(string ...$pattern) + { + return $this->client->addIgnorePatterns(...$pattern); + } + + /** + * Adds allow pattern(s). Only matching keys will be cached in memory. + * + * @param string $pattern,... + * @return int + */ + public function addAllowPatterns(string ...$pattern) + { + return $this->client->addAllowPatterns(...$pattern); + } + + /** + * Returns the connection's endpoint identifier. + * + * @return string|false + */ + public function endpointId() + { + return $this->client->endpointId(); + } + + /** + * Returns a unique representation of the underlying socket connection identifier. + * + * @return string|false + */ + public function socketId() + { + return $this->client->socketId(); + } + + /** + * Returns information about the license. + * + * @return array + */ + public function license() + { + return $this->client->license(); + } + + /** + * Returns statistics about Relay. + * + * @return array> + */ + public function stats() + { + return $this->client->stats(); + } + + /** + * Returns the number of bytes allocated, or `0` in client-only mode. + * + * @return int + */ + public function maxMemory() + { + return $this->client->maxMemory(); + } + + /** + * Flushes Relay's in-memory cache of all databases. + * When given an endpoint, only that connection will be flushed. + * When given an endpoint and database index, only that database + * for that connection will be flushed. + * + * @param ?string $endpointId + * @param ?int $db + * @return bool + */ + public function flushMemory(?string $endpointId = null, int $db = null) + { + return $this->client->flushMemory($endpointId, $db); + } +} diff --git a/src/Pipeline/Pipeline.php b/src/Pipeline/Pipeline.php index 3e1011f2..1f67d0b9 100644 --- a/src/Pipeline/Pipeline.php +++ b/src/Pipeline/Pipeline.php @@ -33,7 +33,7 @@ use SplQueue; */ class Pipeline implements ClientContextInterface { - private $client; + protected $client; private $pipeline; private $responses = []; diff --git a/src/Pipeline/RelayAtomic.php b/src/Pipeline/RelayAtomic.php new file mode 100644 index 00000000..c36e1086 --- /dev/null +++ b/src/Pipeline/RelayAtomic.php @@ -0,0 +1,69 @@ +getClient(); + + $throw = $this->client->getOptions()->exceptions; + + try { + $transaction = $client->multi(); + + foreach ($commands as $command) { + $name = $command->getId(); + + in_array($name, $connection->atypicalCommands) + ? $transaction->{$name}(...$command->getArguments()) + : $transaction->rawCommand($name, ...$command->getArguments()); + } + + $responses = $transaction->exec(); + + if (!is_array($responses)) { + return $responses; + } + + foreach ($responses as $key => $response) { + if ($response instanceof RelayException) { + if ($throw) { + throw $response; + } + + $responses[$key] = new Error($response->getMessage()); + } + } + + return $responses; + } catch (RelayException $ex) { + if ($client->getMode() !== $client::ATOMIC) { + $client->discard(); + } + + throw new ServerException($ex->getMessage(), $ex->getCode(), $ex); + } + } +} diff --git a/src/Pipeline/RelayPipeline.php b/src/Pipeline/RelayPipeline.php new file mode 100644 index 00000000..5f36a0aa --- /dev/null +++ b/src/Pipeline/RelayPipeline.php @@ -0,0 +1,75 @@ +getClient(); + + $throw = $this->client->getOptions()->exceptions; + + try { + $pipeline = $client->pipeline(); + + foreach ($commands as $command) { + $name = $command->getId(); + + in_array($name, $connection->atypicalCommands) + ? $pipeline->{$name}(...$command->getArguments()) + : $pipeline->rawCommand($name, ...$command->getArguments()); + } + + $responses = $pipeline->exec(); + + if (!is_array($responses)) { + return $responses; + } + + foreach ($responses as $key => $response) { + if ($response instanceof RelayException) { + if ($throw) { + throw $response; + } + + $responses[$key] = new Error($response->getMessage()); + } + } + + return $responses; + } catch (RelayException $ex) { + if ($client->getMode() !== $client::ATOMIC) { + $client->discard(); + } + + throw new ServerException($ex->getMessage(), $ex->getCode(), $ex); + } + } +} diff --git a/src/PubSub/AbstractConsumer.php b/src/PubSub/AbstractConsumer.php index 7c77e331..653517a0 100644 --- a/src/PubSub/AbstractConsumer.php +++ b/src/PubSub/AbstractConsumer.php @@ -32,8 +32,8 @@ abstract class AbstractConsumer implements Iterator public const STATUS_SUBSCRIBED = 2; // 0b0010 public const STATUS_PSUBSCRIBED = 4; // 0b0100 - private $position = null; - private $statusFlags = self::STATUS_VALID; + protected $position = null; + protected $statusFlags = self::STATUS_VALID; /** * Automatically stops the consumer when the garbage collector kicks in. diff --git a/src/PubSub/Consumer.php b/src/PubSub/Consumer.php index 253c33fd..b5267323 100644 --- a/src/PubSub/Consumer.php +++ b/src/PubSub/Consumer.php @@ -19,12 +19,12 @@ use Predis\Connection\Cluster\ClusterInterface; use Predis\NotSupportedException; /** - * PUB/SUB consumer abstraction. + * PUB/SUB consumer. */ class Consumer extends AbstractConsumer { - private $client; - private $options; + protected $client; + protected $options; /** * @param ClientInterface $client Client instance used by the consumer. @@ -59,7 +59,7 @@ class Consumer extends AbstractConsumer * * @throws NotSupportedException */ - private function checkCapabilities(ClientInterface $client) + protected function checkCapabilities(ClientInterface $client) { if ($client->getConnection() instanceof ClusterInterface) { throw new NotSupportedException( @@ -81,7 +81,7 @@ class Consumer extends AbstractConsumer * * @param string $subscribeAction Type of subscription. */ - private function genericSubscribeInit($subscribeAction) + protected function genericSubscribeInit($subscribeAction) { if (isset($this->options[$subscribeAction])) { $this->$subscribeAction($this->options[$subscribeAction]); diff --git a/src/PubSub/RelayConsumer.php b/src/PubSub/RelayConsumer.php new file mode 100644 index 00000000..2af67b84 --- /dev/null +++ b/src/PubSub/RelayConsumer.php @@ -0,0 +1,114 @@ +statusFlags |= self::STATUS_SUBSCRIBED; + + $command = $this->client->createCommand('subscribe', [ + $channels, + function ($relay, $channel, $message) use ($callback) { + $callback((object) [ + 'kind' => is_null($message) ? self::SUBSCRIBE : self::MESSAGE, + 'channel' => $channel, + 'payload' => $message, + ], $relay); + }, + ]); + + $this->client->getConnection()->executeCommand($command); + + $this->invalidate(); + } + + /** + * Subscribes to the specified channels using a pattern. + * + * @param string ...$pattern One or more channel name patterns. + * @param callable $callback The message callback. + */ + public function psubscribe(...$pattern) // @phpstan-ignore-line + { + $patterns = func_get_args(); + $callback = array_pop($patterns); + + $this->statusFlags |= self::STATUS_PSUBSCRIBED; + + $command = $this->client->createCommand('psubscribe', [ + $patterns, + function ($relay, $pattern, $channel, $message) use ($callback) { + $callback((object) [ + 'kind' => is_null($message) ? self::PSUBSCRIBE : self::PMESSAGE, + 'pattern' => $pattern, + 'channel' => $channel, + 'payload' => $message, + ], $relay); + }, + ]); + + $this->client->getConnection()->executeCommand($command); + + $this->invalidate(); + } + + /** + * {@inheritDoc} + */ + protected function genericSubscribeInit($subscribeAction) + { + if (isset($this->options[$subscribeAction])) { + throw new NotSupportedException('Relay does not support Pub/Sub constructor options.'); + } + } + + /** + * {@inheritDoc} + */ + public function ping($payload = null) + { + throw new NotSupportedException('Relay does not support PING in Pub/Sub.'); + } + + /** + * {@inheritDoc} + */ + public function stop($drop = false) + { + return false; + } + + /** + * {@inheritDoc} + */ + public function __destruct() + { + // NOOP + } +} diff --git a/src/Transaction/MultiExec.php b/src/Transaction/MultiExec.php index 1f99d2a9..32ac1e12 100644 --- a/src/Transaction/MultiExec.php +++ b/src/Transaction/MultiExec.php @@ -20,11 +20,15 @@ use Predis\ClientInterface; use Predis\Command\CommandInterface; use Predis\CommunicationException; use Predis\Connection\Cluster\ClusterInterface; +use Predis\Connection\RelayConnection; use Predis\NotSupportedException; use Predis\Protocol\ProtocolException; +use Predis\Response\Error; use Predis\Response\ErrorInterface as ErrorResponseInterface; use Predis\Response\ServerException; use Predis\Response\Status as StatusResponse; +use Relay\Exception as RelayException; +use Relay\Relay; use SplQueue; /** @@ -175,9 +179,25 @@ class MultiExec implements ClientContextInterface */ protected function call($commandID, array $arguments = []) { - $response = $this->client->executeCommand( - $this->client->createCommand($commandID, $arguments) - ); + try { + $response = $this->client->executeCommand( + $this->client->createCommand($commandID, $arguments) + ); + } catch (ServerException $exception) { + if (!$this->client->getConnection() instanceof RelayConnection) { + throw $exception; + } + + if (strcasecmp($commandID, 'EXEC') != 0) { + throw $exception; + } + + if (!strpos($exception->getMessage(), 'RELAY_ERR_REDIS')) { + throw $exception; + } + + return null; + } if ($response instanceof ErrorResponseInterface) { throw new ServerException($response->getMessage()); @@ -207,6 +227,8 @@ class MultiExec implements ClientContextInterface if ($response instanceof StatusResponse && $response == 'QUEUED') { $this->commands->enqueue($command); + } elseif ($response instanceof Relay) { + $this->commands->enqueue($command); } elseif ($response instanceof ErrorResponseInterface) { throw new AbortedMultiExecException($this, $response->getMessage()); } else { @@ -375,7 +397,9 @@ class MultiExec implements ClientContextInterface $execResponse = $this->call('EXEC'); - if ($execResponse === null) { + // The additional `false` check is needed for Relay, + // let's hope it won't break anything + if ($execResponse === null || $execResponse === false) { if ($attempts === 0) { throw new AbortedMultiExecException( $this, 'The current transaction has been aborted by the server.' @@ -401,10 +425,20 @@ class MultiExec implements ClientContextInterface for ($i = 0; $i < $size; ++$i) { $cmdResponse = $execResponse[$i]; - if ($cmdResponse instanceof ErrorResponseInterface && $this->exceptions) { + if ($this->exceptions && $cmdResponse instanceof ErrorResponseInterface) { throw new ServerException($cmdResponse->getMessage()); } + if ($cmdResponse instanceof RelayException) { + if ($this->exceptions) { + throw new ServerException($cmdResponse->getMessage(), $cmdResponse->getCode(), $cmdResponse); + } + + $commands->dequeue(); + $response[$i] = new Error($cmdResponse->getMessage()); + continue; + } + $response[$i] = $commands->dequeue()->parseResponse($cmdResponse); } diff --git a/tests/PHPUnit/PredisConnectionTestCase.php b/tests/PHPUnit/PredisConnectionTestCase.php index 89e9419e..d5c7f30d 100644 --- a/tests/PHPUnit/PredisConnectionTestCase.php +++ b/tests/PHPUnit/PredisConnectionTestCase.php @@ -167,6 +167,7 @@ abstract class PredisConnectionTestCase extends PredisTestCase /** * @group connected + * @group relay-incompatible */ public function testDisconnectForcesDisconnection(): void { @@ -193,6 +194,7 @@ abstract class PredisConnectionTestCase extends PredisTestCase /** * @group connected + * @group relay-incompatible */ public function testGetResourceForcesConnection(): void { @@ -273,6 +275,7 @@ abstract class PredisConnectionTestCase extends PredisTestCase /** * @group connected + * @group relay-incompatible */ public function testWritesCommandToServer(): void { @@ -294,6 +297,7 @@ abstract class PredisConnectionTestCase extends PredisTestCase /** * @group connected + * @group relay-incompatible */ public function testReadsCommandFromServer(): void { @@ -316,6 +320,7 @@ abstract class PredisConnectionTestCase extends PredisTestCase /** * @group connected + * @group relay-incompatible */ public function testIsAbleToWriteMultipleCommandsAndReadThemBackForPipelining(): void { @@ -382,6 +387,7 @@ abstract class PredisConnectionTestCase extends PredisTestCase /** * @group connected + * @group relay-incompatible */ public function testReadsStatusResponses(): void { @@ -402,6 +408,7 @@ abstract class PredisConnectionTestCase extends PredisTestCase /** * @group connected + * @group relay-incompatible */ public function testReadsBulkResponses(): void { @@ -419,6 +426,7 @@ abstract class PredisConnectionTestCase extends PredisTestCase /** * @group connected + * @group relay-incompatible */ public function testReadsIntegerResponses(): void { @@ -433,6 +441,7 @@ abstract class PredisConnectionTestCase extends PredisTestCase /** * @group connected + * @group relay-incompatible */ public function testReadsErrorResponsesAsResponseErrorObjects(): void { @@ -450,6 +459,7 @@ abstract class PredisConnectionTestCase extends PredisTestCase /** * @group connected + * @group relay-incompatible */ public function testReadsMultibulkResponsesAsArrays(): void { diff --git a/tests/PHPUnit/PredisTestCase.php b/tests/PHPUnit/PredisTestCase.php index d4156b10..d334f59a 100644 --- a/tests/PHPUnit/PredisTestCase.php +++ b/tests/PHPUnit/PredisTestCase.php @@ -232,10 +232,9 @@ abstract class PredisTestCase extends \PHPUnit\Framework\TestCase ); $options = array_merge( - [ - 'commands' => $this->getCommandFactory(), - ], - $options ?: [] + ['commands' => $this->getCommandFactory()], + $options ?: [], + getenv('USE_RELAY') ? ['connections' => 'relay'] : [] ); $client = new Client($parameters, $options); diff --git a/tests/Predis/Command/Redis/BZMPOP_Test.php b/tests/Predis/Command/Redis/BZMPOP_Test.php index 8e4da84f..27f11046 100644 --- a/tests/Predis/Command/Redis/BZMPOP_Test.php +++ b/tests/Predis/Command/Redis/BZMPOP_Test.php @@ -81,7 +81,7 @@ class BZMPOP_Test extends PredisCommandTestCase $redis->zadd($key, ...$sortedSetDictionary); $actualResponse = $redis->bzmpop($timeout, [$key], $modifier, $count); - $this->assertSame($expectedResponse, $actualResponse); + $this->assertEquals($expectedResponse, $actualResponse); $this->assertSame($expectedModifiedSortedSet, $redis->zrange($key, 0, -1)); } diff --git a/tests/Predis/Command/Redis/BZPOPMAX_Test.php b/tests/Predis/Command/Redis/BZPOPMAX_Test.php index a83149fb..d4d7b9aa 100644 --- a/tests/Predis/Command/Redis/BZPOPMAX_Test.php +++ b/tests/Predis/Command/Redis/BZPOPMAX_Test.php @@ -47,7 +47,7 @@ class BZPOPMAX_Test extends PredisCommandTestCase $redis->zadd('test-bzpopmax', ...$sortedSetDictionary); - $this->assertSame($expectedResponse, $redis->bzpopmax(['empty sorted set', 'test-bzpopmax'], 0)); + $this->assertEquals($expectedResponse, $redis->bzpopmax(['empty sorted set', 'test-bzpopmax'], 0)); $this->assertSame($expectedModifiedSortedSet, $redis->zrange('test-bzpopmax', 0, -1)); } diff --git a/tests/Predis/Command/Redis/BZPOPMIN_Test.php b/tests/Predis/Command/Redis/BZPOPMIN_Test.php index e24c26c2..115506c8 100644 --- a/tests/Predis/Command/Redis/BZPOPMIN_Test.php +++ b/tests/Predis/Command/Redis/BZPOPMIN_Test.php @@ -47,7 +47,7 @@ class BZPOPMIN_Test extends PredisCommandTestCase $redis->zadd('test-bzpopmin', ...$sortedSetDictionary); - $this->assertSame($expectedResponse, $redis->bzpopmin(['empty sorted set', 'test-bzpopmin'], 0)); + $this->assertEquals($expectedResponse, $redis->bzpopmin(['empty sorted set', 'test-bzpopmin'], 0)); $this->assertSame($expectedModifiedSortedSet, $redis->zrange('test-bzpopmin', 0, -1)); } diff --git a/tests/Predis/Command/Redis/CLIENT_Test.php b/tests/Predis/Command/Redis/CLIENT_Test.php index e1ed3c79..41fe4176 100644 --- a/tests/Predis/Command/Redis/CLIENT_Test.php +++ b/tests/Predis/Command/Redis/CLIENT_Test.php @@ -145,6 +145,7 @@ BUFFER; /** * @group connected + * @group relay-incompatible * @requiresRedisVersion >= 2.6.9 */ public function testGetsNameOfConnection(): void diff --git a/tests/Predis/Command/Redis/COMMAND_Test.php b/tests/Predis/Command/Redis/COMMAND_Test.php index 988661d4..47233988 100644 --- a/tests/Predis/Command/Redis/COMMAND_Test.php +++ b/tests/Predis/Command/Redis/COMMAND_Test.php @@ -97,7 +97,11 @@ class COMMAND_Test extends PredisCommandTestCase /** * @group connected + * @group relay-incompatible + * @group relay-fixme * @requiresRedisVersion >= 2.8.13 + * + * Relay uses RESP3 maps, the `Predis\Command\Redis\COMMAND` needs a converter. */ public function testReturnsCommandInfoOnExistingCommand(): void { diff --git a/tests/Predis/Command/Redis/DISCARD_Test.php b/tests/Predis/Command/Redis/DISCARD_Test.php index 843fe58a..b54c92c3 100644 --- a/tests/Predis/Command/Redis/DISCARD_Test.php +++ b/tests/Predis/Command/Redis/DISCARD_Test.php @@ -55,6 +55,7 @@ class DISCARD_Test extends PredisCommandTestCase /** * @group connected + * @group relay-incompatible * @requiresRedisVersion >= 2.0.0 */ public function testAbortsTransactionAndRestoresNormalFlow(): void @@ -68,6 +69,22 @@ class DISCARD_Test extends PredisCommandTestCase $this->assertSame(0, $redis->exists('foo')); } + /** + * @group connected + * @group ext-relay + */ + public function testAbortsTransactionAndRestoresNormalFlowUsingRelay(): void + { + $redis = $this->getClient(); + $relay = $redis->getConnection()->getClient(); + + $redis->multi(); + + $this->assertSame($relay, $redis->set('foo', 'bar')); + $this->assertTrue($redis->discard()); + $this->assertSame(0, $redis->exists('foo')); + } + /** * @group connected * @requiresRedisVersion >= 2.0.0 @@ -75,7 +92,7 @@ class DISCARD_Test extends PredisCommandTestCase public function testThrowsExceptionWhenCallingOutsideTransaction(): void { $this->expectException('Predis\Response\ServerException'); - $this->expectExceptionMessage('ERR DISCARD without MULTI'); + $this->expectExceptionMessage('DISCARD without MULTI'); $redis = $this->getClient(); diff --git a/tests/Predis/Command/Redis/EXEC_Test.php b/tests/Predis/Command/Redis/EXEC_Test.php index 0d2a8270..5595db60 100644 --- a/tests/Predis/Command/Redis/EXEC_Test.php +++ b/tests/Predis/Command/Redis/EXEC_Test.php @@ -105,7 +105,7 @@ class EXEC_Test extends PredisCommandTestCase public function testThrowsExceptionWhenCallingOutsideTransaction(): void { $this->expectException('Predis\Response\ServerException'); - $this->expectExceptionMessage('ERR EXEC without MULTI'); + $this->expectExceptionMessage('EXEC without MULTI'); $redis = $this->getClient(); diff --git a/tests/Predis/Command/Redis/EXPIREAT_Test.php b/tests/Predis/Command/Redis/EXPIREAT_Test.php index 78490200..5ef1a051 100644 --- a/tests/Predis/Command/Redis/EXPIREAT_Test.php +++ b/tests/Predis/Command/Redis/EXPIREAT_Test.php @@ -93,8 +93,8 @@ class EXPIREAT_Test extends PredisCommandTestCase /** * @medium * @group connected - * @dataProvider keysProvider * @group slow + * @dataProvider keysProvider * @param array $firstKeyArguments * @param array $secondKeyArguments * @param array $positivePathArguments diff --git a/tests/Predis/Command/Redis/EXPIRE_Test.php b/tests/Predis/Command/Redis/EXPIRE_Test.php index cfe0584d..105898b8 100644 --- a/tests/Predis/Command/Redis/EXPIRE_Test.php +++ b/tests/Predis/Command/Redis/EXPIRE_Test.php @@ -90,8 +90,8 @@ class EXPIRE_Test extends PredisCommandTestCase /** * @medium * @group connected - * @dataProvider keysProvider * @group slow + * @dataProvider keysProvider * @param array $firstKeyArguments * @param array $secondKeyArguments * @param array $positivePathArguments diff --git a/tests/Predis/Command/Redis/FCALL_Test.php b/tests/Predis/Command/Redis/FCALL_Test.php index 516032af..af852518 100644 --- a/tests/Predis/Command/Redis/FCALL_Test.php +++ b/tests/Predis/Command/Redis/FCALL_Test.php @@ -17,6 +17,7 @@ use Predis\Response\ServerException; /** * @group commands * @group realm-scripting + * @requiresRedisVersion >= 7.0.0 */ class FCALL_Test extends PredisCommandTestCase { @@ -71,6 +72,7 @@ class FCALL_Test extends PredisCommandTestCase $expectedResponse ): void { $redis = $this->getClient(); + $redis->executeRaw(['FUNCTION', 'FLUSH']); $this->assertSame('mylib', $redis->function->load($function)); @@ -87,6 +89,7 @@ class FCALL_Test extends PredisCommandTestCase public function testThrowsExceptionOnNonExistingFunctionGiven(): void { $redis = $this->getClient(); + $redis->executeRaw(['FUNCTION', 'FLUSH']); $this->expectException(ServerException::class); $this->expectExceptionMessage('ERR Function not found'); diff --git a/tests/Predis/Command/Redis/FUNCTIONS_Test.php b/tests/Predis/Command/Redis/FUNCTIONS_Test.php index 3bf838cd..49fa20ad 100644 --- a/tests/Predis/Command/Redis/FUNCTIONS_Test.php +++ b/tests/Predis/Command/Redis/FUNCTIONS_Test.php @@ -17,6 +17,7 @@ use Predis\Response\ServerException; /** * @group commands * @group realm-scripting + * @requiresRedisVersion >= 7.0.0 */ class FUNCTIONS_Test extends PredisCommandTestCase { @@ -85,6 +86,7 @@ class FUNCTIONS_Test extends PredisCommandTestCase public function testLoadFunctionAddFunctionIntoGivenLibrary(): void { $redis = $this->getClient(); + $redis->executeRaw(['FUNCTION', 'FLUSH']); $actualResponse = $redis->function->load( "#!lua name={$this->libName} \n redis.register_function('myfunc', function(keys, args) return args[1] end)" @@ -103,6 +105,7 @@ class FUNCTIONS_Test extends PredisCommandTestCase public function testLoadFunctionOverridesExistingFunctionWithReplaceArgumentGiven(): void { $redis = $this->getClient(); + $redis->executeRaw(['FUNCTION', 'FLUSH']); $actualResponse = $redis->function->load( "#!lua name={$this->libName} \n redis.register_function('myfunc', function(keys, args) return args[1] end)" @@ -129,6 +132,7 @@ class FUNCTIONS_Test extends PredisCommandTestCase public function testLoadFunctionThrowsErrorOnAlreadyExistingLibraryGiven(): void { $redis = $this->getClient(); + $redis->executeRaw(['FUNCTION', 'FLUSH']); $actualResponse = $redis->function->load( "#!lua name={$this->libName} \n redis.register_function('myfunc', function(keys, args) return args[1] end)" @@ -156,6 +160,7 @@ class FUNCTIONS_Test extends PredisCommandTestCase public function testDeleteFunctionRemovesAlreadyExistingLibrary(): void { $redis = $this->getClient(); + $redis->executeRaw(['FUNCTION', 'FLUSH']); $actualResponse = $redis->function->load( "#!lua name={$this->libName} \n redis.register_function('myfunc', function(keys, args) return args[1] end)" @@ -173,6 +178,7 @@ class FUNCTIONS_Test extends PredisCommandTestCase public function testDeleteFunctionThrowsErrorOnNonExistingLibrary(): void { $redis = $this->getClient(); + $redis->executeRaw(['FUNCTION', 'FLUSH']); $this->expectException(ServerException::class); $this->expectExceptionMessage('ERR Library not found'); diff --git a/tests/Predis/Command/Redis/GEOADD_Test.php b/tests/Predis/Command/Redis/GEOADD_Test.php index dc54fd55..417f4805 100644 --- a/tests/Predis/Command/Redis/GEOADD_Test.php +++ b/tests/Predis/Command/Redis/GEOADD_Test.php @@ -88,7 +88,7 @@ class GEOADD_Test extends PredisCommandTestCase $redis = $this->getClient(); $redis->geoadd('Sicily', '13.361389', '38.115556', 'Palermo'); - $this->assertSame(['Palermo' => '3479099956230698'], $redis->zrange('Sicily', 0, -1, 'WITHSCORES')); + $this->assertEquals(['Palermo' => '3479099956230698'], $redis->zrange('Sicily', 0, -1, 'WITHSCORES')); } /** diff --git a/tests/Predis/Command/Redis/GETBIT_Test.php b/tests/Predis/Command/Redis/GETBIT_Test.php index c38bfbb1..7df11f26 100644 --- a/tests/Predis/Command/Redis/GETBIT_Test.php +++ b/tests/Predis/Command/Redis/GETBIT_Test.php @@ -80,8 +80,7 @@ class GETBIT_Test extends PredisCommandTestCase */ public function testThrowsExceptionOnNegativeOffset(): void { - $this->expectException('Predis\Response\ServerException'); - $this->expectExceptionMessage('ERR bit offset is not an integer or out of range'); + $this->expectExceptionMessage('bit offset is not an integer or out of range'); $redis = $this->getClient(); @@ -95,8 +94,7 @@ class GETBIT_Test extends PredisCommandTestCase */ public function testThrowsExceptionOnInvalidOffset(): void { - $this->expectException('Predis\Response\ServerException'); - $this->expectExceptionMessage('ERR bit offset is not an integer or out of range'); + $this->expectExceptionMessage('bit offset is not an integer or out of range'); $redis = $this->getClient(); diff --git a/tests/Predis/Command/Redis/HMGET_Test.php b/tests/Predis/Command/Redis/HMGET_Test.php index 989e94e5..573dfbb5 100644 --- a/tests/Predis/Command/Redis/HMGET_Test.php +++ b/tests/Predis/Command/Redis/HMGET_Test.php @@ -86,7 +86,31 @@ class HMGET_Test extends PredisCommandTestCase $redis->hmset('metavars', 'foo', 'bar', 'hoge', 'piyo', 'lol', 'wut'); $this->assertSame(['bar', 'piyo', null], $redis->hmget('metavars', 'foo', 'hoge', 'unknown')); + } + + /** + * @group connected + * @requiresRedisVersion >= 2.0.0 + */ + public function testReturnsDuplicateValues(): void + { + $redis = $this->getClient(); + + $redis->hmset('metavars', 'foo', 'bar', 'hoge', 'piyo', 'lol', 'wut'); + $this->assertSame(['bar', 'bar'], $redis->hmget('metavars', 'foo', 'foo')); + } + + /** + * @group connected + * @requiresRedisVersion >= 2.0.0 + */ + public function testReturnsNullValues(): void + { + $redis = $this->getClient(); + + $redis->hmset('metavars', 'foo', 'bar', 'hoge', 'piyo', 'lol', 'wut'); + $this->assertSame([null, null], $redis->hmget('metavars', 'unknown', 'unknown')); $this->assertSame([null, null], $redis->hmget('unknown', 'foo', 'hoge')); } diff --git a/tests/Predis/Command/Redis/MIGRATE_Test.php b/tests/Predis/Command/Redis/MIGRATE_Test.php index 6d4b27d6..bf789cf3 100644 --- a/tests/Predis/Command/Redis/MIGRATE_Test.php +++ b/tests/Predis/Command/Redis/MIGRATE_Test.php @@ -88,6 +88,7 @@ class MIGRATE_Test extends PredisCommandTestCase /** * @group connected + * @group relay-incompatible * @requiresRedisVersion >= 2.6.0 */ public function testReturnsStatusNOKEYOnNonExistingKey(): void @@ -98,6 +99,18 @@ class MIGRATE_Test extends PredisCommandTestCase $this->assertInstanceOf('Predis\Response\Status', $response); } + /** + * @group connected + * @group ext-relay + * @requiresRedisVersion >= 2.6.0 + */ + public function testReturnsStatusNOKEYOnNonExistingKeyUsingRelay(): void + { + $redis = $this->getClient(); + + $this->assertEquals('NOKEY', $redis->migrate('169.254.10.10', 16379, 'foo', 15, 1)); + } + /** * @group connected * @requiresRedisVersion >= 2.6.0 diff --git a/tests/Predis/Command/Redis/MONITOR_Test.php b/tests/Predis/Command/Redis/MONITOR_Test.php index 21f6ea4b..6a82705f 100644 --- a/tests/Predis/Command/Redis/MONITOR_Test.php +++ b/tests/Predis/Command/Redis/MONITOR_Test.php @@ -56,6 +56,7 @@ class MONITOR_Test extends PredisCommandTestCase /** * @group connected + * @group relay-incompatible */ public function testReturnsStatusResponseAndReadsEventsFromTheConnection(): void { diff --git a/tests/Predis/Command/Redis/MOVE_Test.php b/tests/Predis/Command/Redis/MOVE_Test.php index 6c9966f6..27c7e1fd 100644 --- a/tests/Predis/Command/Redis/MOVE_Test.php +++ b/tests/Predis/Command/Redis/MOVE_Test.php @@ -61,7 +61,6 @@ class MOVE_Test extends PredisCommandTestCase /** * @group connected - * * @todo Should be improved, this test fails when REDIS_SERVER_DBNUM is 0. */ public function testMovesKeysToDifferentDatabases(): void diff --git a/tests/Predis/Command/Redis/MULTI_Test.php b/tests/Predis/Command/Redis/MULTI_Test.php index 9992149d..e4d5b4e3 100644 --- a/tests/Predis/Command/Redis/MULTI_Test.php +++ b/tests/Predis/Command/Redis/MULTI_Test.php @@ -55,6 +55,7 @@ class MULTI_Test extends PredisCommandTestCase /** * @group connected + * @group relay-incompatible */ public function testInitializesNewTransaction(): void { @@ -67,6 +68,24 @@ class MULTI_Test extends PredisCommandTestCase /** * @group connected + * @group ext-relay + */ + public function testInitializesNewTransactionUsingRelay(): void + { + $redis = $this->getClient(); + $relay = $redis->getConnection()->getClient(); + + $this->assertSame($relay, $redis->multi()); + $this->assertSame($relay, $redis->echo('tx1')); + $this->assertSame($relay, $redis->echo('tx2')); + + $relay->discard(); + } + + /** + * @group connected + * @group relay-incompatible + * @group relay-fixme */ public function testActuallyReturnsResponseObjectAbstraction(): void { @@ -79,6 +98,8 @@ class MULTI_Test extends PredisCommandTestCase /** * @group connected + * @group relay-incompatible + * @group relay-fixme */ public function testThrowsExceptionWhenCallingMultiInsideTransaction(): void { diff --git a/tests/Predis/Command/Redis/PING_Test.php b/tests/Predis/Command/Redis/PING_Test.php index 731597b0..54b15fab 100644 --- a/tests/Predis/Command/Redis/PING_Test.php +++ b/tests/Predis/Command/Redis/PING_Test.php @@ -58,6 +58,7 @@ class PING_Test extends PredisCommandTestCase /** * @group connected + * @group relay-incompatible */ public function testAlwaysReturnsStatusResponse(): void { @@ -67,4 +68,19 @@ class PING_Test extends PredisCommandTestCase $this->assertInstanceOf('Predis\Response\Status', $response); $this->assertEquals('PONG', $response); } + + /** + * @group connected + * @group ext-relay + */ + public function testAlwaysReturnsResponseUsingRelay(): void + { + $redis = $this->getClient(); + + $response = $redis->ping(); + $this->assertEquals('PONG', $response); + + $response = $redis->ping('HELLO'); + $this->assertSame('HELLO', $response); + } } diff --git a/tests/Predis/Command/Redis/PSUBSCRIBE_Test.php b/tests/Predis/Command/Redis/PSUBSCRIBE_Test.php index 92e99b44..47ec3c36 100644 --- a/tests/Predis/Command/Redis/PSUBSCRIBE_Test.php +++ b/tests/Predis/Command/Redis/PSUBSCRIBE_Test.php @@ -15,6 +15,7 @@ namespace Predis\Command\Redis; /** * @group commands * @group realm-pubsub + * @group relay-incompatible */ class PSUBSCRIBE_Test extends PredisCommandTestCase { diff --git a/tests/Predis/Command/Redis/PUBLISH_Test.php b/tests/Predis/Command/Redis/PUBLISH_Test.php index 8d42ec85..bd810e36 100644 --- a/tests/Predis/Command/Redis/PUBLISH_Test.php +++ b/tests/Predis/Command/Redis/PUBLISH_Test.php @@ -58,6 +58,7 @@ class PUBLISH_Test extends PredisCommandTestCase /** * @group connected + * @group relay-incompatible * @requiresRedisVersion >= 2.0.0 */ public function testPublishesMessagesToChannel(): void diff --git a/tests/Predis/Command/Redis/PUNSUBSCRIBE_Test.php b/tests/Predis/Command/Redis/PUNSUBSCRIBE_Test.php index c3804bb6..0149526b 100644 --- a/tests/Predis/Command/Redis/PUNSUBSCRIBE_Test.php +++ b/tests/Predis/Command/Redis/PUNSUBSCRIBE_Test.php @@ -15,6 +15,7 @@ namespace Predis\Command\Redis; /** * @group commands * @group realm-pubsub + * @group relay-incompatible */ class PUNSUBSCRIBE_Test extends PredisCommandTestCase { diff --git a/tests/Predis/Command/Redis/QUIT_Test.php b/tests/Predis/Command/Redis/QUIT_Test.php index 12cd82f2..94848412 100644 --- a/tests/Predis/Command/Redis/QUIT_Test.php +++ b/tests/Predis/Command/Redis/QUIT_Test.php @@ -58,6 +58,7 @@ class QUIT_Test extends PredisCommandTestCase /** * @group connected + * @group relay-incompatible */ public function testReturnsStatusResponseWhenClosingConnection(): void { diff --git a/tests/Predis/Command/Redis/SELECT_Test.php b/tests/Predis/Command/Redis/SELECT_Test.php index 30d6bea8..ecaf4edc 100644 --- a/tests/Predis/Command/Redis/SELECT_Test.php +++ b/tests/Predis/Command/Redis/SELECT_Test.php @@ -84,6 +84,7 @@ class SELECT_Test extends PredisCommandTestCase /** * @group connected + * @group relay-incompatible */ public function testThrowsExceptionOnUnexpectedDatabaseName(): void { diff --git a/tests/Predis/Command/Redis/SUBSCRIBE_Test.php b/tests/Predis/Command/Redis/SUBSCRIBE_Test.php index 4ed3600b..92b19b2d 100644 --- a/tests/Predis/Command/Redis/SUBSCRIBE_Test.php +++ b/tests/Predis/Command/Redis/SUBSCRIBE_Test.php @@ -15,6 +15,7 @@ namespace Predis\Command\Redis; /** * @group commands * @group realm-pubsub + * @group relay-incompatible */ class SUBSCRIBE_Test extends PredisCommandTestCase { diff --git a/tests/Predis/Command/Redis/Search/FTAGGREGATE_Test.php b/tests/Predis/Command/Redis/Search/FTAGGREGATE_Test.php index 190c37b6..5518709e 100644 --- a/tests/Predis/Command/Redis/Search/FTAGGREGATE_Test.php +++ b/tests/Predis/Command/Redis/Search/FTAGGREGATE_Test.php @@ -20,6 +20,10 @@ use Predis\Command\Argument\Search\SchemaFields\TextField; use Predis\Command\Redis\PredisCommandTestCase; use Predis\Response\ServerException; +/** + * @group commands + * @group realm-stack + */ class FTAGGREGATE_Test extends PredisCommandTestCase { /** diff --git a/tests/Predis/Command/Redis/Search/FTCURSOR_Test.php b/tests/Predis/Command/Redis/Search/FTCURSOR_Test.php index 637c0be4..a814eaac 100644 --- a/tests/Predis/Command/Redis/Search/FTCURSOR_Test.php +++ b/tests/Predis/Command/Redis/Search/FTCURSOR_Test.php @@ -21,6 +21,10 @@ use Predis\Command\Argument\Search\SchemaFields\TextField; use Predis\Command\Redis\PredisCommandTestCase; use Predis\Response\ServerException; +/** + * @group commands + * @group realm-stack + */ class FTCURSOR_Test extends PredisCommandTestCase { /** diff --git a/tests/Predis/Command/Redis/Search/FTEXPLAIN_Test.php b/tests/Predis/Command/Redis/Search/FTEXPLAIN_Test.php index 11eeae12..8d6dcead 100644 --- a/tests/Predis/Command/Redis/Search/FTEXPLAIN_Test.php +++ b/tests/Predis/Command/Redis/Search/FTEXPLAIN_Test.php @@ -17,6 +17,10 @@ use Predis\Command\Argument\Search\SchemaFields\TextField; use Predis\Command\Redis\PredisCommandTestCase; use Predis\Response\ServerException; +/** + * @group commands + * @group realm-stack + */ class FTEXPLAIN_Test extends PredisCommandTestCase { /** diff --git a/tests/Predis/Command/Redis/Search/FTINFO_Test.php b/tests/Predis/Command/Redis/Search/FTINFO_Test.php index 276be34e..6915e006 100644 --- a/tests/Predis/Command/Redis/Search/FTINFO_Test.php +++ b/tests/Predis/Command/Redis/Search/FTINFO_Test.php @@ -63,8 +63,11 @@ class FTINFO_Test extends PredisCommandTestCase /** * @group connected + * @group relay-incompatible * @return void * @requiresRediSearchVersion >= 1.0.0 + * + * Prior to Redis 7.2 `-nan` is messing with Relay/hiredis. */ public function testInfoReturnsInformationAboutGivenIndex(): void { diff --git a/tests/Predis/Command/Redis/Search/FTSPELLCHECK_Test.php b/tests/Predis/Command/Redis/Search/FTSPELLCHECK_Test.php index 4bb77a12..16ee1f70 100644 --- a/tests/Predis/Command/Redis/Search/FTSPELLCHECK_Test.php +++ b/tests/Predis/Command/Redis/Search/FTSPELLCHECK_Test.php @@ -83,7 +83,7 @@ class FTSPELLCHECK_Test extends PredisCommandTestCase (new SpellcheckArguments())->distance(2)->terms('dict') ); - $this->assertSame($expectedResponse, $actualResponse); + $this->assertEquals($expectedResponse, $actualResponse); } /** diff --git a/tests/Predis/Command/Redis/Search/FTSUGGET_Test.php b/tests/Predis/Command/Redis/Search/FTSUGGET_Test.php index da05f156..3239d53d 100644 --- a/tests/Predis/Command/Redis/Search/FTSUGGET_Test.php +++ b/tests/Predis/Command/Redis/Search/FTSUGGET_Test.php @@ -16,6 +16,10 @@ use Predis\Command\Argument\Search\SugAddArguments; use Predis\Command\Argument\Search\SugGetArguments; use Predis\Command\Redis\PredisCommandTestCase; +/** + * @group commands + * @group realm-stack + */ class FTSUGGET_Test extends PredisCommandTestCase { /** @@ -74,7 +78,7 @@ class FTSUGGET_Test extends PredisCommandTestCase $actualResponse = $redis->ftsugget(...$getArguments); - $this->assertSame($expectedResponse, $actualResponse); + $this->assertEquals($expectedResponse, $actualResponse); } /** diff --git a/tests/Predis/Command/Redis/Search/FTSUGLEN_Test.php b/tests/Predis/Command/Redis/Search/FTSUGLEN_Test.php index 9d06cb8f..214ed246 100644 --- a/tests/Predis/Command/Redis/Search/FTSUGLEN_Test.php +++ b/tests/Predis/Command/Redis/Search/FTSUGLEN_Test.php @@ -14,6 +14,10 @@ namespace Predis\Command\Redis\Search; use Predis\Command\Redis\PredisCommandTestCase; +/** + * @group commands + * @group realm-stack + */ class FTSUGLEN_Test extends PredisCommandTestCase { /** diff --git a/tests/Predis/Command/Redis/TDigest/TDIGESTBYRANK_Test.php b/tests/Predis/Command/Redis/TDigest/TDIGESTBYRANK_Test.php index 47d9841a..4aadeb79 100644 --- a/tests/Predis/Command/Redis/TDigest/TDIGESTBYRANK_Test.php +++ b/tests/Predis/Command/Redis/TDigest/TDIGESTBYRANK_Test.php @@ -76,8 +76,8 @@ class TDIGESTBYRANK_Test extends PredisCommandTestCase $actualResponse = $redis->tdigestbyrank('key', 0, 1, 2, 3, 4, 5, 6); - $this->assertSame($expectedResponse, $actualResponse); - $this->assertSame(['nan', 'nan'], $redis->tdigestbyrank('empty_key', 0, 1)); + $this->assertEquals($expectedResponse, $actualResponse); + $this->assertEquals(['nan', 'nan'], $redis->tdigestbyrank('empty_key', 0, 1)); } /** diff --git a/tests/Predis/Command/Redis/TDigest/TDIGESTBYREVRANK_Test.php b/tests/Predis/Command/Redis/TDigest/TDIGESTBYREVRANK_Test.php index ee3c3040..7fc8a3a1 100644 --- a/tests/Predis/Command/Redis/TDigest/TDIGESTBYREVRANK_Test.php +++ b/tests/Predis/Command/Redis/TDigest/TDIGESTBYREVRANK_Test.php @@ -76,8 +76,8 @@ class TDIGESTBYREVRANK_Test extends PredisCommandTestCase $actualResponse = $redis->tdigestbyrevrank('key', 0, 1, 2, 3, 4, 5, 6); - $this->assertSame($expectedResponse, $actualResponse); - $this->assertSame(['nan', 'nan'], $redis->tdigestbyrevrank('empty_key', 0, 1)); + $this->assertEquals($expectedResponse, $actualResponse); + $this->assertEquals(['nan', 'nan'], $redis->tdigestbyrevrank('empty_key', 0, 1)); } /** diff --git a/tests/Predis/Command/Redis/TDigest/TDIGESTCDF_Test.php b/tests/Predis/Command/Redis/TDigest/TDIGESTCDF_Test.php index 5a844523..2b23e6ae 100644 --- a/tests/Predis/Command/Redis/TDigest/TDIGESTCDF_Test.php +++ b/tests/Predis/Command/Redis/TDigest/TDIGESTCDF_Test.php @@ -76,8 +76,8 @@ class TDIGESTCDF_Test extends PredisCommandTestCase $actualResponse = $redis->tdigestcdf('key', 0, 1, 2, 3, 4); - $this->assertSame($expectedResponse, $actualResponse); - $this->assertSame(['nan', 'nan'], $redis->tdigestcdf('empty_key', 0, 1)); + $this->assertEquals($expectedResponse, $actualResponse); + $this->assertEquals(['nan', 'nan'], $redis->tdigestcdf('empty_key', 0, 1)); } /** diff --git a/tests/Predis/Command/Redis/TDigest/TDIGESTMAX_Test.php b/tests/Predis/Command/Redis/TDigest/TDIGESTMAX_Test.php index f3c206ae..62b0a7a8 100644 --- a/tests/Predis/Command/Redis/TDigest/TDIGESTMAX_Test.php +++ b/tests/Predis/Command/Redis/TDigest/TDIGESTMAX_Test.php @@ -75,8 +75,8 @@ class TDIGESTMAX_Test extends PredisCommandTestCase $actualResponse = $redis->tdigestmax('key'); - $this->assertSame('5', $actualResponse); - $this->assertSame('nan', $redis->tdigestmax('empty_key')); + $this->assertEquals('5', $actualResponse); + $this->assertEquals('nan', $redis->tdigestmax('empty_key')); } /** diff --git a/tests/Predis/Command/Redis/TDigest/TDIGESTMERGE_Test.php b/tests/Predis/Command/Redis/TDigest/TDIGESTMERGE_Test.php index a6575498..b4d73071 100644 --- a/tests/Predis/Command/Redis/TDigest/TDIGESTMERGE_Test.php +++ b/tests/Predis/Command/Redis/TDigest/TDIGESTMERGE_Test.php @@ -84,7 +84,7 @@ class TDIGESTMERGE_Test extends PredisCommandTestCase $this->assertEquals('OK', $actualResponse); $this->assertSame($expectedCompression, $info['Compression']); - $this->assertSame( + $this->assertEquals( $expectedMergedSketchValues, $redis->tdigestbyrank('destination-key', 0, 1, 2, 3, 4) ); @@ -110,7 +110,7 @@ class TDIGESTMERGE_Test extends PredisCommandTestCase $this->assertEquals('OK', $actualResponse); $this->assertSame(1000, $info['Compression']); - $this->assertSame( + $this->assertEquals( ['1', '2', '3', '4', 'inf'], $redis->tdigestbyrank('destination-key', 0, 1, 2, 3, 4) ); @@ -133,7 +133,7 @@ class TDIGESTMERGE_Test extends PredisCommandTestCase $redis->tdigestadd('source-key2', 3, 4); $redis->tdigestadd('destination-key', 5, 6, 7, 8); - $this->assertSame( + $this->assertEquals( ['5', '6', '7', '8', 'inf'], $redis->tdigestbyrank('destination-key', 0, 1, 2, 3, 4) ); @@ -148,7 +148,7 @@ class TDIGESTMERGE_Test extends PredisCommandTestCase $this->assertEquals('OK', $actualResponse); $this->assertSame(100, $info['Compression']); - $this->assertSame( + $this->assertEquals( ['1', '2', '3', '4', 'inf'], $redis->tdigestbyrank('destination-key', 0, 1, 2, 3, 4) ); @@ -176,7 +176,7 @@ class TDIGESTMERGE_Test extends PredisCommandTestCase $this->assertEquals('OK', $actualResponse); $this->assertSame(100, $info['Compression']); - $this->assertSame( + $this->assertEquals( ['1', '2', '3', '4', '5', '6', '7', '8', 'inf'], $redis->tdigestbyrank('destination-key', 0, 1, 2, 3, 4, 5, 6, 7, 8) ); diff --git a/tests/Predis/Command/Redis/TDigest/TDIGESTMIN_Test.php b/tests/Predis/Command/Redis/TDigest/TDIGESTMIN_Test.php index cab0cf19..c7062995 100644 --- a/tests/Predis/Command/Redis/TDigest/TDIGESTMIN_Test.php +++ b/tests/Predis/Command/Redis/TDigest/TDIGESTMIN_Test.php @@ -75,8 +75,8 @@ class TDIGESTMIN_Test extends PredisCommandTestCase $actualResponse = $redis->tdigestmin('key'); - $this->assertSame('1', $actualResponse); - $this->assertSame('nan', $redis->tdigestmin('empty_key')); + $this->assertEquals('1', $actualResponse); + $this->assertEquals('nan', $redis->tdigestmin('empty_key')); } /** diff --git a/tests/Predis/Command/Redis/TDigest/TDIGESTQUANTILE_Test.php b/tests/Predis/Command/Redis/TDigest/TDIGESTQUANTILE_Test.php index 2e76ab91..b43cc533 100644 --- a/tests/Predis/Command/Redis/TDigest/TDIGESTQUANTILE_Test.php +++ b/tests/Predis/Command/Redis/TDigest/TDIGESTQUANTILE_Test.php @@ -74,10 +74,10 @@ class TDIGESTQUANTILE_Test extends PredisCommandTestCase $quantileResponse = $redis->tdigestquantile('key', 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0); $this->assertEquals('OK', $addResponse); - $this->assertSame(['1', '2', '3', '3', '4', '4', '4', '5', '5', '5', '5'], $quantileResponse); + $this->assertEquals(['1', '2', '3', '3', '4', '4', '4', '5', '5', '5', '5'], $quantileResponse); $redis->tdigestcreate('empty_key'); - $this->assertSame(['nan', 'nan'], $redis->tdigestquantile('empty_key', 0.0, 0.1)); + $this->assertEquals(['nan', 'nan'], $redis->tdigestquantile('empty_key', 0.0, 0.1)); } /** diff --git a/tests/Predis/Command/Redis/TDigest/TDIGESTRESET_Test.php b/tests/Predis/Command/Redis/TDigest/TDIGESTRESET_Test.php index 1a2a0ca1..bc3ebe25 100644 --- a/tests/Predis/Command/Redis/TDigest/TDIGESTRESET_Test.php +++ b/tests/Predis/Command/Redis/TDigest/TDIGESTRESET_Test.php @@ -71,7 +71,7 @@ class TDIGESTRESET_Test extends PredisCommandTestCase $redis->tdigestcreate('key', 500); $redis->tdigestadd('key', 1, 2, 2, 3, 3, 3); - $this->assertSame( + $this->assertEquals( ['1', '2', '2', '3', '3', '3'], $redis->tdigestbyrank('key', 0, 1, 2, 3, 4, 5) ); @@ -81,7 +81,7 @@ class TDIGESTRESET_Test extends PredisCommandTestCase $this->assertEquals('OK', $actualResponse); $this->assertSame(500, $info['Compression']); - $this->assertSame( + $this->assertEquals( ['nan', 'nan', 'nan', 'nan', 'nan', 'nan'], $redis->tdigestbyrank('key', 0, 1, 2, 3, 4, 5) ); diff --git a/tests/Predis/Command/Redis/TDigest/TDIGESTTRIMMED_MEAN_Test.php b/tests/Predis/Command/Redis/TDigest/TDIGESTTRIMMED_MEAN_Test.php index 4d7127de..15490426 100644 --- a/tests/Predis/Command/Redis/TDigest/TDIGESTTRIMMED_MEAN_Test.php +++ b/tests/Predis/Command/Redis/TDigest/TDIGESTTRIMMED_MEAN_Test.php @@ -82,7 +82,7 @@ class TDIGESTTRIMMED_MEAN_Test extends PredisCommandTestCase $actualResponse = $redis->tdigesttrimmed_mean(...$trimmedMeanArguments); - $this->assertSame($expectedResponse, $actualResponse); + $this->assertEquals($expectedResponse, $actualResponse); } /** @@ -97,7 +97,7 @@ class TDIGESTTRIMMED_MEAN_Test extends PredisCommandTestCase $redis->tdigestcreate('key'); $actualResponse = $redis->tdigesttrimmed_mean('key', 0, 1); - $this->assertSame('nan', $actualResponse); + $this->assertEquals('nan', $actualResponse); } /** diff --git a/tests/Predis/Command/Redis/TimeSeries/TSADD_Test.php b/tests/Predis/Command/Redis/TimeSeries/TSADD_Test.php index c4db6892..a969e88e 100644 --- a/tests/Predis/Command/Redis/TimeSeries/TSADD_Test.php +++ b/tests/Predis/Command/Redis/TimeSeries/TSADD_Test.php @@ -17,6 +17,10 @@ use Predis\Command\Argument\TimeSeries\CommonArguments; use Predis\Command\Argument\TimeSeries\CreateArguments; use Predis\Command\Redis\PredisCommandTestCase; +/** + * @group commands + * @group realm-stack + */ class TSADD_Test extends PredisCommandTestCase { /** diff --git a/tests/Predis/Command/Redis/TimeSeries/TSALTER_Test.php b/tests/Predis/Command/Redis/TimeSeries/TSALTER_Test.php index e8c5db63..01f6fd3e 100644 --- a/tests/Predis/Command/Redis/TimeSeries/TSALTER_Test.php +++ b/tests/Predis/Command/Redis/TimeSeries/TSALTER_Test.php @@ -18,6 +18,10 @@ use Predis\Command\Argument\TimeSeries\CreateArguments; use Predis\Command\Redis\PredisCommandTestCase; use Predis\Response\ServerException; +/** + * @group commands + * @group realm-stack + */ class TSALTER_Test extends PredisCommandTestCase { /** diff --git a/tests/Predis/Command/Redis/TimeSeries/TSCREATERULE_Test.php b/tests/Predis/Command/Redis/TimeSeries/TSCREATERULE_Test.php index d3eab4e6..25a448f2 100644 --- a/tests/Predis/Command/Redis/TimeSeries/TSCREATERULE_Test.php +++ b/tests/Predis/Command/Redis/TimeSeries/TSCREATERULE_Test.php @@ -16,6 +16,10 @@ use Predis\Command\Argument\TimeSeries\CreateArguments; use Predis\Command\Redis\PredisCommandTestCase; use Predis\Response\ServerException; +/** + * @group commands + * @group realm-stack + */ class TSCREATERULE_Test extends PredisCommandTestCase { /** diff --git a/tests/Predis/Command/Redis/TimeSeries/TSCREATE_Test.php b/tests/Predis/Command/Redis/TimeSeries/TSCREATE_Test.php index 62409d42..ef7c66ce 100644 --- a/tests/Predis/Command/Redis/TimeSeries/TSCREATE_Test.php +++ b/tests/Predis/Command/Redis/TimeSeries/TSCREATE_Test.php @@ -17,6 +17,10 @@ use Predis\Command\Argument\TimeSeries\CreateArguments; use Predis\Command\Redis\PredisCommandTestCase; use Predis\Response\ServerException; +/** + * @group commands + * @group realm-stack + */ class TSCREATE_Test extends PredisCommandTestCase { /** diff --git a/tests/Predis/Command/Redis/TimeSeries/TSDECRBY_Test.php b/tests/Predis/Command/Redis/TimeSeries/TSDECRBY_Test.php index b99888a7..b2d7e210 100644 --- a/tests/Predis/Command/Redis/TimeSeries/TSDECRBY_Test.php +++ b/tests/Predis/Command/Redis/TimeSeries/TSDECRBY_Test.php @@ -19,6 +19,10 @@ use Predis\Command\Argument\TimeSeries\DecrByArguments; use Predis\Command\Redis\PredisCommandTestCase; use Predis\Response\ServerException; +/** + * @group commands + * @group realm-stack + */ class TSDECRBY_Test extends PredisCommandTestCase { /** diff --git a/tests/Predis/Command/Redis/TimeSeries/TSDELETERULE_Test.php b/tests/Predis/Command/Redis/TimeSeries/TSDELETERULE_Test.php index 8b83840d..ac581894 100644 --- a/tests/Predis/Command/Redis/TimeSeries/TSDELETERULE_Test.php +++ b/tests/Predis/Command/Redis/TimeSeries/TSDELETERULE_Test.php @@ -16,6 +16,10 @@ use Predis\Command\Argument\TimeSeries\CreateArguments; use Predis\Command\Redis\PredisCommandTestCase; use Predis\Response\ServerException; +/** + * @group commands + * @group realm-stack + */ class TSDELETERULE_Test extends PredisCommandTestCase { /** diff --git a/tests/Predis/Command/Redis/TimeSeries/TSDEL_Test.php b/tests/Predis/Command/Redis/TimeSeries/TSDEL_Test.php index 671f44ce..a9506eab 100644 --- a/tests/Predis/Command/Redis/TimeSeries/TSDEL_Test.php +++ b/tests/Predis/Command/Redis/TimeSeries/TSDEL_Test.php @@ -17,6 +17,10 @@ use Predis\Command\Argument\TimeSeries\CreateArguments; use Predis\Command\Redis\PredisCommandTestCase; use Predis\Response\ServerException; +/** + * @group commands + * @group realm-stack + */ class TSDEL_Test extends PredisCommandTestCase { /** diff --git a/tests/Predis/Command/Redis/TimeSeries/TSGET_Test.php b/tests/Predis/Command/Redis/TimeSeries/TSGET_Test.php index 099a9f28..4ab298df 100644 --- a/tests/Predis/Command/Redis/TimeSeries/TSGET_Test.php +++ b/tests/Predis/Command/Redis/TimeSeries/TSGET_Test.php @@ -18,6 +18,10 @@ use Predis\Command\Argument\TimeSeries\GetArguments; use Predis\Command\Redis\PredisCommandTestCase; use Predis\Response\ServerException; +/** + * @group commands + * @group realm-stack + */ class TSGET_Test extends PredisCommandTestCase { /** diff --git a/tests/Predis/Command/Redis/TimeSeries/TSINCRBY_Test.php b/tests/Predis/Command/Redis/TimeSeries/TSINCRBY_Test.php index 95add6c9..fbfceaca 100644 --- a/tests/Predis/Command/Redis/TimeSeries/TSINCRBY_Test.php +++ b/tests/Predis/Command/Redis/TimeSeries/TSINCRBY_Test.php @@ -19,6 +19,10 @@ use Predis\Command\Argument\TimeSeries\IncrByArguments; use Predis\Command\Redis\PredisCommandTestCase; use Predis\Response\ServerException; +/** + * @group commands + * @group realm-stack + */ class TSINCRBY_Test extends PredisCommandTestCase { /** diff --git a/tests/Predis/Command/Redis/TimeSeries/TSINFO_Test.php b/tests/Predis/Command/Redis/TimeSeries/TSINFO_Test.php index 1720cbc4..20566d53 100644 --- a/tests/Predis/Command/Redis/TimeSeries/TSINFO_Test.php +++ b/tests/Predis/Command/Redis/TimeSeries/TSINFO_Test.php @@ -17,6 +17,10 @@ use Predis\Command\Argument\TimeSeries\CreateArguments; use Predis\Command\Argument\TimeSeries\InfoArguments; use Predis\Command\Redis\PredisCommandTestCase; +/** + * @group commands + * @group realm-stack + */ class TSINFO_Test extends PredisCommandTestCase { /** diff --git a/tests/Predis/Command/Redis/TimeSeries/TSMADD_Test.php b/tests/Predis/Command/Redis/TimeSeries/TSMADD_Test.php index 649139b5..a9f8a11a 100644 --- a/tests/Predis/Command/Redis/TimeSeries/TSMADD_Test.php +++ b/tests/Predis/Command/Redis/TimeSeries/TSMADD_Test.php @@ -17,6 +17,10 @@ use Predis\Command\Argument\TimeSeries\CreateArguments; use Predis\Command\Redis\PredisCommandTestCase; use Predis\Response\ServerException; +/** + * @group commands + * @group realm-stack + */ class TSMADD_Test extends PredisCommandTestCase { /** diff --git a/tests/Predis/Command/Redis/TimeSeries/TSMGET_Test.php b/tests/Predis/Command/Redis/TimeSeries/TSMGET_Test.php index 6b7acc47..74d5b981 100644 --- a/tests/Predis/Command/Redis/TimeSeries/TSMGET_Test.php +++ b/tests/Predis/Command/Redis/TimeSeries/TSMGET_Test.php @@ -17,6 +17,10 @@ use Predis\Command\Argument\TimeSeries\CreateArguments; use Predis\Command\Argument\TimeSeries\MGetArguments; use Predis\Command\Redis\PredisCommandTestCase; +/** + * @group commands + * @group realm-stack + */ class TSMGET_Test extends PredisCommandTestCase { /** diff --git a/tests/Predis/Command/Redis/TimeSeries/TSMRANGE_Test.php b/tests/Predis/Command/Redis/TimeSeries/TSMRANGE_Test.php index 25788b5e..cd7c126e 100644 --- a/tests/Predis/Command/Redis/TimeSeries/TSMRANGE_Test.php +++ b/tests/Predis/Command/Redis/TimeSeries/TSMRANGE_Test.php @@ -16,6 +16,10 @@ use Predis\Command\Argument\TimeSeries\CreateArguments; use Predis\Command\Argument\TimeSeries\MRangeArguments; use Predis\Command\Redis\PredisCommandTestCase; +/** + * @group commands + * @group realm-stack + */ class TSMRANGE_Test extends PredisCommandTestCase { /** diff --git a/tests/Predis/Command/Redis/TimeSeries/TSMREVRANGE_Test.php b/tests/Predis/Command/Redis/TimeSeries/TSMREVRANGE_Test.php index 214a4476..8d5a9adb 100644 --- a/tests/Predis/Command/Redis/TimeSeries/TSMREVRANGE_Test.php +++ b/tests/Predis/Command/Redis/TimeSeries/TSMREVRANGE_Test.php @@ -16,6 +16,10 @@ use Predis\Command\Argument\TimeSeries\CreateArguments; use Predis\Command\Argument\TimeSeries\MRangeArguments; use Predis\Command\Redis\PredisCommandTestCase; +/** + * @group commands + * @group realm-stack + */ class TSMREVRANGE_Test extends PredisCommandTestCase { /** diff --git a/tests/Predis/Command/Redis/TimeSeries/TSQUERYINDEX_Test.php b/tests/Predis/Command/Redis/TimeSeries/TSQUERYINDEX_Test.php index 927875c9..0630300c 100644 --- a/tests/Predis/Command/Redis/TimeSeries/TSQUERYINDEX_Test.php +++ b/tests/Predis/Command/Redis/TimeSeries/TSQUERYINDEX_Test.php @@ -16,6 +16,10 @@ use Predis\Command\Argument\TimeSeries\CreateArguments; use Predis\Command\Redis\PredisCommandTestCase; use Predis\Response\ServerException; +/** + * @group commands + * @group realm-stack + */ class TSQUERYINDEX_Test extends PredisCommandTestCase { /** diff --git a/tests/Predis/Command/Redis/TimeSeries/TSRANGE_Test.php b/tests/Predis/Command/Redis/TimeSeries/TSRANGE_Test.php index ae47a21f..b4c7b0df 100644 --- a/tests/Predis/Command/Redis/TimeSeries/TSRANGE_Test.php +++ b/tests/Predis/Command/Redis/TimeSeries/TSRANGE_Test.php @@ -17,6 +17,10 @@ use Predis\Command\Argument\TimeSeries\RangeArguments; use Predis\Command\Redis\PredisCommandTestCase; use Predis\Response\ServerException; +/** + * @group commands + * @group realm-stack + */ class TSRANGE_Test extends PredisCommandTestCase { /** diff --git a/tests/Predis/Command/Redis/TimeSeries/TSREVRANGE_Test.php b/tests/Predis/Command/Redis/TimeSeries/TSREVRANGE_Test.php index b607f608..1615f5c6 100644 --- a/tests/Predis/Command/Redis/TimeSeries/TSREVRANGE_Test.php +++ b/tests/Predis/Command/Redis/TimeSeries/TSREVRANGE_Test.php @@ -17,6 +17,10 @@ use Predis\Command\Argument\TimeSeries\RangeArguments; use Predis\Command\Redis\PredisCommandTestCase; use Predis\Response\ServerException; +/** + * @group commands + * @group realm-stack + */ class TSREVRANGE_Test extends PredisCommandTestCase { /** diff --git a/tests/Predis/Command/Redis/TopK/TOPKINFO_Test.php b/tests/Predis/Command/Redis/TopK/TOPKINFO_Test.php index 2b83eb06..2a0ca4c9 100644 --- a/tests/Predis/Command/Redis/TopK/TOPKINFO_Test.php +++ b/tests/Predis/Command/Redis/TopK/TOPKINFO_Test.php @@ -73,7 +73,7 @@ class TOPKINFO_Test extends PredisCommandTestCase $redis->topkreserve('key', 50); - $this->assertSame( + $this->assertEquals( ['k' => 50, 'width' => 8, 'depth' => 7, 'decay' => '0.90000000000000002'], $redis->topkinfo('key') ); diff --git a/tests/Predis/Command/Redis/TopK/TOPKRESERVE_Test.php b/tests/Predis/Command/Redis/TopK/TOPKRESERVE_Test.php index 66ae6739..08a978ee 100644 --- a/tests/Predis/Command/Redis/TopK/TOPKRESERVE_Test.php +++ b/tests/Predis/Command/Redis/TopK/TOPKRESERVE_Test.php @@ -77,7 +77,7 @@ class TOPKRESERVE_Test extends PredisCommandTestCase $actualInfoResponse = $redis->topkinfo($key); $this->assertEquals('OK', $actualResponse); - $this->assertSame($expectedInfoResponse, $actualInfoResponse); + $this->assertEquals($expectedInfoResponse, $actualInfoResponse); } /** diff --git a/tests/Predis/Command/Redis/UNSUBSCRIBE_Test.php b/tests/Predis/Command/Redis/UNSUBSCRIBE_Test.php index 418aa63e..9aedf18b 100644 --- a/tests/Predis/Command/Redis/UNSUBSCRIBE_Test.php +++ b/tests/Predis/Command/Redis/UNSUBSCRIBE_Test.php @@ -15,6 +15,7 @@ namespace Predis\Command\Redis; /** * @group commands * @group realm-pubsub + * @group relay-incompatible */ class UNSUBSCRIBE_Test extends PredisCommandTestCase { diff --git a/tests/Predis/Command/Redis/UNWATCH_Test.php b/tests/Predis/Command/Redis/UNWATCH_Test.php index 556d9340..efa9cc8d 100644 --- a/tests/Predis/Command/Redis/UNWATCH_Test.php +++ b/tests/Predis/Command/Redis/UNWATCH_Test.php @@ -75,6 +75,7 @@ class UNWATCH_Test extends PredisCommandTestCase /** * @group connected + * @group relay-incompatible * @requiresRedisVersion >= 2.2.0 */ public function testCanBeCalledInsideTransaction(): void @@ -84,4 +85,17 @@ class UNWATCH_Test extends PredisCommandTestCase $redis->multi(); $this->assertInstanceOf('Predis\Response\Status', $redis->unwatch()); } + + /** + * @group connected + * @group ext-relay + * @requiresRedisVersion >= 2.2.0 + */ + public function testCanBeCalledInsideTransactionUsingRelay(): void + { + $redis = $this->getClient(); + + $redis->multi(); + $this->assertInstanceOf('Relay\Relay', $redis->unwatch()); + } } diff --git a/tests/Predis/Command/Redis/WATCH_Test.php b/tests/Predis/Command/Redis/WATCH_Test.php index c963aade..fd2a4234 100644 --- a/tests/Predis/Command/Redis/WATCH_Test.php +++ b/tests/Predis/Command/Redis/WATCH_Test.php @@ -15,6 +15,7 @@ namespace Predis\Command\Redis; /** * @group commands * @group realm-transaction + * @group relay-incompatible */ class WATCH_Test extends PredisCommandTestCase { diff --git a/tests/Predis/Command/Redis/ZADD_Test.php b/tests/Predis/Command/Redis/ZADD_Test.php index bee4e21d..9f4827af 100644 --- a/tests/Predis/Command/Redis/ZADD_Test.php +++ b/tests/Predis/Command/Redis/ZADD_Test.php @@ -154,10 +154,10 @@ class ZADD_Test extends PredisCommandTestCase { $redis = $this->getClient(); - $this->assertSame('1', $redis->zadd('letters', 'INCR', 1, 'a')); - $this->assertSame('0', $redis->zadd('letters', 'INCR', -1, 'a')); - $this->assertSame('0.5', $redis->zadd('letters', 'INCR', 0.5, 'a')); - $this->assertSame('-10', $redis->zadd('letters', 'INCR', -10.5, 'a')); + $this->assertEquals('1', $redis->zadd('letters', 'INCR', 1, 'a')); + $this->assertEquals('0', $redis->zadd('letters', 'INCR', -1, 'a')); + $this->assertEquals('0.5', $redis->zadd('letters', 'INCR', 0.5, 'a')); + $this->assertEquals('-10', $redis->zadd('letters', 'INCR', -10.5, 'a')); } /** diff --git a/tests/Predis/Command/Redis/ZINCRBY_Test.php b/tests/Predis/Command/Redis/ZINCRBY_Test.php index 121eb35a..74f1cd8b 100644 --- a/tests/Predis/Command/Redis/ZINCRBY_Test.php +++ b/tests/Predis/Command/Redis/ZINCRBY_Test.php @@ -63,10 +63,10 @@ class ZINCRBY_Test extends PredisCommandTestCase { $redis = $this->getClient(); - $this->assertSame('1', $redis->zincrby('letters', 1, 'member')); - $this->assertSame('0', $redis->zincrby('letters', -1, 'member')); - $this->assertSame('0.5', $redis->zincrby('letters', 0.5, 'member')); - $this->assertSame('-10', $redis->zincrby('letters', -10.5, 'member')); + $this->assertEquals('1', $redis->zincrby('letters', 1, 'member')); + $this->assertEquals('0', $redis->zincrby('letters', -1, 'member')); + $this->assertEquals('0.5', $redis->zincrby('letters', 0.5, 'member')); + $this->assertEquals('-10', $redis->zincrby('letters', -10.5, 'member')); } /** diff --git a/tests/Predis/Command/Redis/ZINTERSTORE_Test.php b/tests/Predis/Command/Redis/ZINTERSTORE_Test.php index 758a5eb4..2f52e73f 100644 --- a/tests/Predis/Command/Redis/ZINTERSTORE_Test.php +++ b/tests/Predis/Command/Redis/ZINTERSTORE_Test.php @@ -92,7 +92,7 @@ class ZINTERSTORE_Test extends PredisCommandTestCase ); $this->assertSame($expectedResponse, $actualResponse); - $this->assertSame( + $this->assertEquals( $expectedResultSortedSet, $redis->zrange($destination, 0, -1, ['withscores' => true]) ); diff --git a/tests/Predis/Command/Redis/ZINTER_Test.php b/tests/Predis/Command/Redis/ZINTER_Test.php index 297d4387..9390cd5a 100644 --- a/tests/Predis/Command/Redis/ZINTER_Test.php +++ b/tests/Predis/Command/Redis/ZINTER_Test.php @@ -107,7 +107,7 @@ class ZINTER_Test extends PredisCommandTestCase $withScores ); - $this->assertSame($expectedResponse, $actualResponse); + $this->assertEquals($expectedResponse, $actualResponse); } /** diff --git a/tests/Predis/Command/Redis/ZMPOP_Test.php b/tests/Predis/Command/Redis/ZMPOP_Test.php index b57adba3..6d52005f 100644 --- a/tests/Predis/Command/Redis/ZMPOP_Test.php +++ b/tests/Predis/Command/Redis/ZMPOP_Test.php @@ -79,7 +79,7 @@ class ZMPOP_Test extends PredisCommandTestCase $redis->zadd($key, ...$sortedSetDictionary); $actualResponse = $redis->zmpop([$key], $modifier, $count); - $this->assertSame($expectedResponse, $actualResponse); + $this->assertEquals($expectedResponse, $actualResponse); $this->assertSame($expectedModifiedSortedSet, $redis->zrange($key, 0, -1)); } diff --git a/tests/Predis/Command/Redis/ZMSCORE_Test.php b/tests/Predis/Command/Redis/ZMSCORE_Test.php index 19f62c7a..db1d0941 100644 --- a/tests/Predis/Command/Redis/ZMSCORE_Test.php +++ b/tests/Predis/Command/Redis/ZMSCORE_Test.php @@ -78,7 +78,7 @@ class ZMSCORE_Test extends PredisCommandTestCase $redis->zadd($key, ...$membersDictionary); - $this->assertSame($expectedResponse, $redis->zmscore($key, ...$members)); + $this->assertEquals($expectedResponse, $redis->zmscore($key, ...$members)); $this->assertNull($redis->zmscore($key, $notExpectedMember)[0]); } diff --git a/tests/Predis/Command/Redis/ZPOPMAX_Test.php b/tests/Predis/Command/Redis/ZPOPMAX_Test.php index 5939c153..dad4dde4 100644 --- a/tests/Predis/Command/Redis/ZPOPMAX_Test.php +++ b/tests/Predis/Command/Redis/ZPOPMAX_Test.php @@ -66,9 +66,8 @@ class ZPOPMAX_Test extends PredisCommandTestCase } /** - * @requiresRedisVersion >= 5.0.0 - * * @group connected + * @requiresRedisVersion >= 5.0.0 */ public function testReturnsElements(): void { @@ -79,9 +78,9 @@ class ZPOPMAX_Test extends PredisCommandTestCase $redis->zadd('letters', -10, 'a', 0, 'b', 10, 'c', 20, 'd', 20, 'e', 30, 'f'); - $this->assertSame(['f' => '30'], $redis->zpopmax('letters')); - $this->assertSame(['e' => '20', 'd' => '20', 'c' => '10'], $redis->zpopmax('letters', 3)); - $this->assertSame(['b' => '0', 'a' => '-10'], $redis->zpopmax('letters', 3)); + $this->assertEquals(['f' => '30'], $redis->zpopmax('letters')); + $this->assertEquals(['e' => '20', 'd' => '20', 'c' => '10'], $redis->zpopmax('letters', 3)); + $this->assertEquals(['b' => '0', 'a' => '-10'], $redis->zpopmax('letters', 3)); } /** diff --git a/tests/Predis/Command/Redis/ZPOPMIN_Test.php b/tests/Predis/Command/Redis/ZPOPMIN_Test.php index a15abade..43849803 100644 --- a/tests/Predis/Command/Redis/ZPOPMIN_Test.php +++ b/tests/Predis/Command/Redis/ZPOPMIN_Test.php @@ -66,9 +66,8 @@ class ZPOPMIN_Test extends PredisCommandTestCase } /** - * @requiresRedisVersion >= 5.0.0 - * * @group connected + * @requiresRedisVersion >= 5.0.0 */ public function testReturnsElements(): void { @@ -79,9 +78,9 @@ class ZPOPMIN_Test extends PredisCommandTestCase $redis->zadd('letters', -10, 'a', 0, 'b', 10, 'c', 20, 'd', 20, 'e', 30, 'f'); - $this->assertSame(['a' => '-10'], $redis->zpopmin('letters')); - $this->assertSame(['b' => '0', 'c' => '10', 'd' => '20'], $redis->zpopmin('letters', 3)); - $this->assertSame(['e' => '20', 'f' => '30'], $redis->zpopmin('letters', 3)); + $this->assertEquals(['a' => '-10'], $redis->zpopmin('letters')); + $this->assertEquals(['b' => '0', 'c' => '10', 'd' => '20'], $redis->zpopmin('letters', 3)); + $this->assertEquals(['e' => '20', 'f' => '30'], $redis->zpopmin('letters', 3)); } /** diff --git a/tests/Predis/Command/Redis/ZRANGEBYSCORE_Test.php b/tests/Predis/Command/Redis/ZRANGEBYSCORE_Test.php index 8d370062..b933a6ec 100644 --- a/tests/Predis/Command/Redis/ZRANGEBYSCORE_Test.php +++ b/tests/Predis/Command/Redis/ZRANGEBYSCORE_Test.php @@ -180,8 +180,8 @@ class ZRANGEBYSCORE_Test extends PredisCommandTestCase $redis->zadd('letters', -10, 'a', 0, 'b', 10, 'c', 20, 'd', 20, 'e', 30, 'f'); $expected = ['c' => '10', 'd' => '20', 'e' => '20']; - $this->assertSame($expected, $redis->zrangebyscore('letters', 10, 20, 'withscores')); - $this->assertSame($expected, $redis->zrangebyscore('letters', 10, 20, ['withscores' => true])); + $this->assertEquals($expected, $redis->zrangebyscore('letters', 10, 20, 'withscores')); + $this->assertEquals($expected, $redis->zrangebyscore('letters', 10, 20, ['withscores' => true])); } /** @@ -210,7 +210,7 @@ class ZRANGEBYSCORE_Test extends PredisCommandTestCase $options = ['limit' => [1, 2], 'withscores' => true]; $expected = ['d' => '20', 'e' => '20']; - $this->assertSame($expected, $redis->zrangebyscore('letters', 10, 20, $options)); + $this->assertEquals($expected, $redis->zrangebyscore('letters', 10, 20, $options)); } /** diff --git a/tests/Predis/Command/Redis/ZRANGE_Test.php b/tests/Predis/Command/Redis/ZRANGE_Test.php index 9c63ca3e..3e58516a 100644 --- a/tests/Predis/Command/Redis/ZRANGE_Test.php +++ b/tests/Predis/Command/Redis/ZRANGE_Test.php @@ -137,8 +137,8 @@ class ZRANGE_Test extends PredisCommandTestCase $redis->zadd('letters', -10, 'a', 0, 'b', 10, 'c', 20, 'd', 20, 'e', 30, 'f'); $expected = ['c' => '10', 'd' => '20', 'e' => '20']; - $this->assertSame($expected, $redis->zrange('letters', 2, 4, 'withscores')); - $this->assertSame($expected, $redis->zrange('letters', 2, 4, ['withscores' => true])); + $this->assertEquals($expected, $redis->zrange('letters', 2, 4, 'withscores')); + $this->assertEquals($expected, $redis->zrange('letters', 2, 4, ['withscores' => true])); } /** diff --git a/tests/Predis/Command/Redis/ZREVRANGEBYSCORE_Test.php b/tests/Predis/Command/Redis/ZREVRANGEBYSCORE_Test.php index f8a2a319..e1545432 100644 --- a/tests/Predis/Command/Redis/ZREVRANGEBYSCORE_Test.php +++ b/tests/Predis/Command/Redis/ZREVRANGEBYSCORE_Test.php @@ -184,8 +184,8 @@ class ZREVRANGEBYSCORE_Test extends PredisCommandTestCase $redis->zadd('letters', -10, 'a', 0, 'b', 10, 'c', 20, 'd', 20, 'e', 30, 'f'); $expected = ['e' => '20', 'd' => '20', 'c' => '10']; - $this->assertSame($expected, $redis->zrevrangebyscore('letters', 20, 10, 'withscores')); - $this->assertSame($expected, $redis->zrevrangebyscore('letters', 20, 10, ['withscores' => true])); + $this->assertEquals($expected, $redis->zrevrangebyscore('letters', 20, 10, 'withscores')); + $this->assertEquals($expected, $redis->zrevrangebyscore('letters', 20, 10, ['withscores' => true])); } /** @@ -216,7 +216,7 @@ class ZREVRANGEBYSCORE_Test extends PredisCommandTestCase $options = ['limit' => [1, 2], 'withscores' => true]; $expected = ['d' => '20', 'c' => '10']; - $this->assertSame($expected, $redis->zrevrangebyscore('letters', 20, 10, $options)); + $this->assertEquals($expected, $redis->zrevrangebyscore('letters', 20, 10, $options)); } /** diff --git a/tests/Predis/Command/Redis/ZREVRANGE_Test.php b/tests/Predis/Command/Redis/ZREVRANGE_Test.php index 8ae88d78..ac2e228e 100644 --- a/tests/Predis/Command/Redis/ZREVRANGE_Test.php +++ b/tests/Predis/Command/Redis/ZREVRANGE_Test.php @@ -137,8 +137,8 @@ class ZREVRANGE_Test extends PredisCommandTestCase $redis->zadd('letters', -10, 'a', 0, 'b', 10, 'c', 20, 'd', 20, 'e', 30, 'f'); $expected = ['d' => '20', 'c' => '10', 'b' => '0']; - $this->assertSame($expected, $redis->zrevrange('letters', 2, 4, 'withscores')); - $this->assertSame($expected, $redis->zrevrange('letters', 2, 4, ['withscores' => true])); + $this->assertEquals($expected, $redis->zrevrange('letters', 2, 4, 'withscores')); + $this->assertEquals($expected, $redis->zrevrange('letters', 2, 4, ['withscores' => true])); } /** diff --git a/tests/Predis/Command/Redis/ZSCORE_Test.php b/tests/Predis/Command/Redis/ZSCORE_Test.php index dc50820c..680788d5 100644 --- a/tests/Predis/Command/Redis/ZSCORE_Test.php +++ b/tests/Predis/Command/Redis/ZSCORE_Test.php @@ -65,9 +65,9 @@ class ZSCORE_Test extends PredisCommandTestCase $redis->zadd('letters', -10, 'a', 0, 'b', 10, 'c', 20, 'd', 20, 'e', 30, 'f'); - $this->assertSame('-10', $redis->zscore('letters', 'a')); - $this->assertSame('0', $redis->zscore('letters', 'b')); - $this->assertSame('20', $redis->zscore('letters', 'e')); + $this->assertEquals('-10', $redis->zscore('letters', 'a')); + $this->assertEquals('0', $redis->zscore('letters', 'b')); + $this->assertEquals('20', $redis->zscore('letters', 'e')); $this->assertNull($redis->zscore('unknown', 'a')); } diff --git a/tests/Predis/Command/Redis/ZUNIONSTORE_Test.php b/tests/Predis/Command/Redis/ZUNIONSTORE_Test.php index 72c8724a..61405d83 100644 --- a/tests/Predis/Command/Redis/ZUNIONSTORE_Test.php +++ b/tests/Predis/Command/Redis/ZUNIONSTORE_Test.php @@ -92,7 +92,7 @@ class ZUNIONSTORE_Test extends PredisCommandTestCase ); $this->assertSame($expectedResponse, $actualResponse); - $this->assertSame( + $this->assertEquals( $expectedResultSortedSet, $redis->zrange($destination, 0, -1, ['withscores' => true]) ); diff --git a/tests/Predis/Command/Redis/ZUNION_Test.php b/tests/Predis/Command/Redis/ZUNION_Test.php index eef3941a..2e1d3ed4 100644 --- a/tests/Predis/Command/Redis/ZUNION_Test.php +++ b/tests/Predis/Command/Redis/ZUNION_Test.php @@ -81,7 +81,7 @@ class ZUNION_Test extends PredisCommandTestCase $withScores ); - $this->assertSame($expectedResponse, $actualResponse); + $this->assertEquals($expectedResponse, $actualResponse); } /** diff --git a/tests/Predis/Configuration/Option/ConnectionsTest.php b/tests/Predis/Configuration/Option/ConnectionsTest.php index fc46308b..346049b0 100644 --- a/tests/Predis/Configuration/Option/ConnectionsTest.php +++ b/tests/Predis/Configuration/Option/ConnectionsTest.php @@ -66,7 +66,7 @@ class ConnectionsTest extends PredisTestCase * @group disconnected * @dataProvider provideSupportedStringValuesForOption */ - public function testAcceptsStringToConfigurePhpiredisStreamBackend($value, $classFQCN) + public function testAcceptsStringToConfigureRelayBackend($value, $classFQCN) { $options = $this->getMockBuilder('Predis\Configuration\OptionsInterface')->getMock(); @@ -232,6 +232,7 @@ class ConnectionsTest extends PredisTestCase ['phpiredis-stream', 'Predis\Connection\PhpiredisStreamConnection'], ['phpiredis-socket', 'Predis\Connection\PhpiredisSocketConnection'], ['phpiredis', 'Predis\Connection\PhpiredisStreamConnection'], + ['relay', \Predis\Connection\RelayConnection::class], ]; } } diff --git a/tests/Predis/Connection/Cluster/RedisClusterTest.php b/tests/Predis/Connection/Cluster/RedisClusterTest.php index 7cf28a66..cf021b2c 100644 --- a/tests/Predis/Connection/Cluster/RedisClusterTest.php +++ b/tests/Predis/Connection/Cluster/RedisClusterTest.php @@ -737,6 +737,7 @@ class RedisClusterTest extends PredisTestCase /** * @group disconnected + * @group slow */ public function testThrowsClientExceptionWhenExecutingCommandWithEmptyPool(): void { diff --git a/tests/Predis/Connection/ParametersTest.php b/tests/Predis/Connection/ParametersTest.php index 700ec4a4..eaab5baf 100644 --- a/tests/Predis/Connection/ParametersTest.php +++ b/tests/Predis/Connection/ParametersTest.php @@ -386,6 +386,23 @@ class ParametersTest extends PredisTestCase $this->assertSame($uri, (string) $parameters); } + /** + * @group disconnected + */ + public function testSettingRelayOptions(): void + { + $uri = 'tcp://10.10.10.10?serializer=igbinary&compression=lz4'; + + $expected = [ + 'scheme' => 'tcp', + 'host' => '10.10.10.10', + 'serializer' => 'igbinary', + 'compression' => 'lz4', + ]; + + $this->assertSame($expected, Parameters::parse($uri)); + } + // ******************************************************************** // // ---- HELPER METHODS ------------------------------------------------ // // ******************************************************************** // diff --git a/tests/Predis/Connection/RelayConnectionTest.php b/tests/Predis/Connection/RelayConnectionTest.php new file mode 100644 index 00000000..11bc72e3 --- /dev/null +++ b/tests/Predis/Connection/RelayConnectionTest.php @@ -0,0 +1,234 @@ +expectException('Predis\Connection\ConnectionException'); + $this->expectExceptionMessage('`SELECT` failed: ERR invalid DB index [tcp://127.0.0.1:6379]'); + + $cmdSelect = RawCommand::create('SELECT', '1000'); + + /** @var NodeConnectionInterface|MockObject */ + $connection = $this + ->getMockBuilder($this->getConnectionClass()) + ->onlyMethods(['executeCommand', 'createResource']) + ->setConstructorArgs([new Parameters()]) + ->getMock(); + $connection + ->method('executeCommand') + ->with($cmdSelect) + ->willReturn( + new ErrorResponse('ERR invalid DB index') + ); + + $connection->method('createResource'); + + $connection->addConnectCommand($cmdSelect); + $connection->connect(); + } + + // ******************************************************************** // + // ---- INTEGRATION TESTS --------------------------------------------- // + // ******************************************************************** // + + /** + * @group connected + */ + public function testGetResourceForcesConnection(): void + { + $connection = $this->createConnection(); + + $this->assertFalse($connection->isConnected()); + $connection->getResource(); + $this->assertTrue($connection->isConnected()); + } + + /** + * @group connected + * @group slow + * @requires PHP 5.4 + */ + public function testThrowsExceptionOnReadWriteTimeout(): void + { + $this->expectException('Predis\Connection\ConnectionException'); + + $connection = $this->createConnectionWithParams([ + 'read_write_timeout' => 0.5, + ], true); + + $connection->executeCommand( + $this->getCommandFactory()->create('brpop', ['foo', 3]) + ); + } + + /** + * @medium + * @group connected + * @group relay-incompatible + */ + public function testThrowsExceptionOnProtocolDesynchronizationErrors(): void + { + $this->expectException('Predis\Protocol\ProtocolException'); + + $connection = $this->createConnection(); + $stream = $connection->getResource(); + + $connection->writeRequest($this->getCommandFactory()->create('ping')); + stream_socket_recvfrom($stream, 1); + + $connection->read(); + } + + /** + * @group connected + * @group relay-incompatible + * @requires PHP 5.4 + */ + public function testPersistentParameterWithFalseLikeValues(): void + { + $connection1 = $this->createConnectionWithParams(['persistent' => 0]); + $this->assertNonPersistentConnection($connection1); + + $connection2 = $this->createConnectionWithParams(['persistent' => false]); + $this->assertNonPersistentConnection($connection2); + + $connection3 = $this->createConnectionWithParams(['persistent' => '0']); + $this->assertNonPersistentConnection($connection3); + + $connection4 = $this->createConnectionWithParams(['persistent' => 'false']); + $this->assertNonPersistentConnection($connection4); + } + + /** + * @group connected + * @group relay-incompatible + * @requires PHP 5.4 + */ + public function testPersistentParameterWithTrueLikeValues(): void + { + $connection1 = $this->createConnectionWithParams(['persistent' => 1]); + $this->assertPersistentConnection($connection1); + + $connection2 = $this->createConnectionWithParams(['persistent' => true]); + $this->assertPersistentConnection($connection2); + + $connection3 = $this->createConnectionWithParams(['persistent' => '1']); + $this->assertPersistentConnection($connection3); + + $connection4 = $this->createConnectionWithParams(['persistent' => 'true']); + $this->assertPersistentConnection($connection4); + + $connection1->disconnect(); + } + + /** + * @group connected + * @group relay-incompatible + * @requires PHP 5.4 + */ + public function testPersistentConnectionsToSameNodeShareResource(): void + { + $connection1 = $this->createConnectionWithParams(['persistent' => true]); + $connection2 = $this->createConnectionWithParams(['persistent' => true]); + + $this->assertPersistentConnection($connection1); + $this->assertPersistentConnection($connection2); + + $this->assertSame($connection1->getResource(), $connection2->getResource()); + + $connection1->disconnect(); + } + + /** + * @group connected + * @group relay-incompatible + * @requires PHP 5.4 + */ + public function testPersistentConnectionsToSameNodeDoNotShareResourceUsingDifferentPersistentID(): void + { + $connection1 = $this->createConnectionWithParams(['persistent' => 'conn1']); + $connection2 = $this->createConnectionWithParams(['persistent' => 'conn2']); + + $this->assertPersistentConnection($connection1); + $this->assertPersistentConnection($connection2); + + $this->assertNotSame($connection1->getResource(), $connection2->getResource()); + } + + /** + * @group connected + * @group relay-incompatible + */ + public function testTcpNodelayParameterSetsContextFlagWhenTrue() + { + $connection = $this->createConnectionWithParams(['tcp_nodelay' => true]); + $options = stream_context_get_options($connection->getResource()); + + $this->assertIsArray($options); + $this->assertArrayHasKey('socket', $options); + $this->assertArrayHasKey('tcp_nodelay', $options['socket']); + $this->assertTrue($options['socket']['tcp_nodelay']); + } + + /** + * @group connected + * @group relay-incompatible + */ + public function testTcpNodelayParameterDoesNotSetContextFlagWhenFalse() + { + $connection = $this->createConnectionWithParams(['tcp_nodelay' => false]); + $options = stream_context_get_options($connection->getResource()); + + $this->assertIsArray($options); + $this->assertArrayHasKey('socket', $options); + $this->assertArrayHasKey('tcp_nodelay', $options['socket']); + $this->assertFalse($options['socket']['tcp_nodelay']); + } + + /** + * @group connected + * @group relay-incompatible + */ + public function testTcpDelayContextFlagIsNotSetByDefault() + { + $connection = $this->createConnectionWithParams([]); + $options = stream_context_get_options($connection->getResource()); + + $this->assertIsArray($options); + $this->assertArrayHasKey('socket', $options); + $this->assertArrayHasKey('tcp_nodelay', $options['socket']); + $this->assertFalse($options['socket']['tcp_nodelay']); + } +} diff --git a/tests/Predis/Transaction/MultiExecTest.php b/tests/Predis/Transaction/MultiExecTest.php index e42d0251..c250961c 100644 --- a/tests/Predis/Transaction/MultiExecTest.php +++ b/tests/Predis/Transaction/MultiExecTest.php @@ -723,6 +723,7 @@ class MultiExecTest extends PredisTestCase /** * @group connected + * @group relay-incompatible */ public function testIntegrationReturnsErrorObjectOnRedisErrorInBlock(): void { @@ -739,6 +740,25 @@ class MultiExecTest extends PredisTestCase $this->assertSame('foobar', $responses[2]); } + /** + * @group connected + * @group ext-relay + */ + public function testIntegrationReturnsErrorObjectOnRedisErrorInBlockWhenUsingRelay(): void + { + $client = $this->getClient([], ['exceptions' => false]); + + $responses = $client->transaction(function (MultiExec $tx) { + $tx->set('foo', 'bar'); + $tx->lpush('foo', 'bar'); + $tx->echo('foobar'); + }); + + $this->assertSame('OK', $responses[0]); + $this->assertInstanceOf('Predis\Response\Error', $responses[1]); + $this->assertSame('foobar', $responses[2]); + } + /** * @group connected * @requiresRedisVersion >= 2.0.0 diff --git a/tests/README.md b/tests/README.md index 5d2e46a1..34189925 100644 --- a/tests/README.md +++ b/tests/README.md @@ -27,7 +27,7 @@ line test runner. Please note that due to a bug in PHPUnit, older versions ignor option when the group is excluded in the XML configuration file. More details about this issue are available on [PHPUnit's bug tracker](http://github.com/sebastianbergmann/phpunit/issues/320). -Certain groups of tests requiring native extensions, such as `ext-curl` or `ext-phpiredis`, are +Certain groups of tests requiring native extensions, such as `ext-relay`, are disabled by default in the configuration file. To enable these groups of tests you should remove them from the exclusion list in `phpunit.xml`. From 95c23fb94d5cac0e8ca71f6f888f1b5c74bfbf61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Till=20Kru=CC=88ss?= Date: Tue, 9 May 2023 10:45:20 -0700 Subject: [PATCH 6/9] tag 2.2.0-RC1 --- CHANGELOG.md | 14 ++++++-------- VERSION | 2 +- src/Client.php | 2 +- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f89c35f2..b26e739e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,20 +1,18 @@ ## Changelog -## Unreleased +## v2.2.0-RC1 (2023-05-09) ### Added - Added support for [Relay](https://github.com/predis/predis/wiki/Using-Relay) (#1263) -- Added support for `FCALL_RO` command -- Added support for `Redis JSON` module -- Added support for `Redis Bloom` module -- Added support for `Redis Search` module -- Added support for `Redis TimeSeries` module -- Added support for `ACL SETUSER, GETUSER, DRYRUN` commands +- Added support for `FCALL_RO` command (#1191) +- Added support for Redis `JSON`, `Bloom`, `Search` and `TimeSeries` module (#1253) +- Added support for `ACL SETUSER, GETUSER, DRYRUN` commands (#1193) ### Fixed -- Fixed prefixes for `XTRIM` and `XREVRANGE` commands +- Fixed prefixes for `XTRIM` and `XREVRANGE` commands (#1230) - Fix `fclose()` being called on invalid stream resource (#1199) - Fix `BitByte` and `ExpireOptions` traits skip processing on null values (#1169) +- Fix missing `@return` annotations (#1265) ## v2.1.2 (2023-03-02) diff --git a/VERSION b/VERSION index eca07e4c..17831900 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.1.2 +2.2.0-RC1 diff --git a/src/Client.php b/src/Client.php index 6e89678a..cf1cfb96 100644 --- a/src/Client.php +++ b/src/Client.php @@ -53,7 +53,7 @@ use Traversable; */ class Client implements ClientInterface, IteratorAggregate { - public const VERSION = '2.1.2'; + public const VERSION = '2.2.0-RC1'; /** @var OptionsInterface */ private $options; From f28d4074fea952bdae063c04dc20031fd1ae2c39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Till=20Kr=C3=BCss?= Date: Tue, 9 May 2023 10:53:21 -0700 Subject: [PATCH 7/9] bump dev version --- VERSION | 2 +- src/Client.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index 17831900..2468aa9e 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.2.0-RC1 +3.0.0-dev diff --git a/src/Client.php b/src/Client.php index cf1cfb96..1636cc6f 100644 --- a/src/Client.php +++ b/src/Client.php @@ -53,7 +53,7 @@ use Traversable; */ class Client implements ClientInterface, IteratorAggregate { - public const VERSION = '2.2.0-RC1'; + public const VERSION = '3.0.0-dev'; /** @var OptionsInterface */ private $options; From 6fbbb8973fee1edbad180ca5e47d7df5e879d174 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Till=20Kr=C3=BCss?= Date: Tue, 9 May 2023 11:11:22 -0700 Subject: [PATCH 8/9] Remove Webdis and phpiredis (#1291) * remove webdis and phpiredis * update changelog * add pr number --- CHANGELOG.md | 8 + phpstan.dist.neon | 3 - phpunit.relay.xml | 2 - phpunit.xml.dist | 2 - src/Cluster/Hash/PhpiredisCRC16.php | 42 -- src/Configuration/Option/CRC16.php | 10 +- src/Configuration/Option/Connections.php | 18 - src/Connection/Factory.php | 1 - src/Connection/PhpiredisSocketConnection.php | 420 ------------------ src/Connection/PhpiredisStreamConnection.php | 262 ----------- src/Connection/WebdisConnection.php | 366 --------------- .../Cluster/Hash/PhpiredisCRC16Test.php | 42 -- .../Predis/Configuration/Option/CRC16Test.php | 24 +- .../Configuration/Option/ConnectionsTest.php | 3 - .../PhpiredisSocketConnectionTest.php | 120 ----- .../PhpiredisStreamConnectionTest.php | 240 ---------- .../Connection/WebdisConnectionTest.php | 227 ---------- 17 files changed, 13 insertions(+), 1777 deletions(-) delete mode 100644 src/Cluster/Hash/PhpiredisCRC16.php delete mode 100644 src/Connection/PhpiredisSocketConnection.php delete mode 100644 src/Connection/PhpiredisStreamConnection.php delete mode 100644 src/Connection/WebdisConnection.php delete mode 100644 tests/Predis/Cluster/Hash/PhpiredisCRC16Test.php delete mode 100644 tests/Predis/Connection/PhpiredisSocketConnectionTest.php delete mode 100644 tests/Predis/Connection/PhpiredisStreamConnectionTest.php delete mode 100644 tests/Predis/Connection/WebdisConnectionTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index b26e739e..fd468fff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ ## Changelog +## Unreleased + +### Changed +- Added `PrefixableCommandInterface` (#1262) + +### Removed +- Removed Webdis and Phpiredis support (#1291) + ## v2.2.0-RC1 (2023-05-09) ### Added diff --git a/phpstan.dist.neon b/phpstan.dist.neon index f7bb09a5..b9df88b3 100644 --- a/phpstan.dist.neon +++ b/phpstan.dist.neon @@ -12,9 +12,6 @@ parameters: - message: "#^Cannot cast Predis\\\\Connection\\\\ConnectionInterface to string\\.$#" count: 1 path: src/Client.php - # phpiredis extension is not installed - - "#^Function phpiredis_\\w+ not found\\.$#" - - "#^Constant PHPIREDIS_#" # "new static" in non-final classes - message: "#^Unsafe usage of new static\\(\\)\\.$#" count: 3 diff --git a/phpunit.relay.xml b/phpunit.relay.xml index 731f29c2..bfe4f52a 100644 --- a/phpunit.relay.xml +++ b/phpunit.relay.xml @@ -20,10 +20,8 @@ relay-incompatible - realm-webdis realm-stack ext-curl - ext-phpiredis diff --git a/phpunit.xml.dist b/phpunit.xml.dist index d47afa8d..662e1fd4 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -28,11 +28,9 @@ - realm-webdis realm-stack ext-relay ext-curl - ext-phpiredis diff --git a/src/Cluster/Hash/PhpiredisCRC16.php b/src/Cluster/Hash/PhpiredisCRC16.php deleted file mode 100644 index 04f58a0e..00000000 --- a/src/Cluster/Hash/PhpiredisCRC16.php +++ /dev/null @@ -1,42 +0,0 @@ -getDefault($options); switch (strtolower($value)) { - case 'phpiredis': - case 'phpiredis-stream': - $factory->define('tcp', PhpiredisStreamConnection::class); - $factory->define('redis', PhpiredisStreamConnection::class); - $factory->define('unix', PhpiredisStreamConnection::class); - break; - - case 'phpiredis-socket': - $factory->define('tcp', PhpiredisSocketConnection::class); - $factory->define('redis', PhpiredisSocketConnection::class); - $factory->define('unix', PhpiredisSocketConnection::class); - break; - case 'relay': $factory->define('tcp', RelayConnection::class); $factory->define('redis', RelayConnection::class); diff --git a/src/Connection/Factory.php b/src/Connection/Factory.php index ad472360..7647af53 100644 --- a/src/Connection/Factory.php +++ b/src/Connection/Factory.php @@ -30,7 +30,6 @@ class Factory implements FactoryInterface 'tls' => 'Predis\Connection\StreamConnection', 'redis' => 'Predis\Connection\StreamConnection', 'rediss' => 'Predis\Connection\StreamConnection', - 'http' => 'Predis\Connection\WebdisConnection', ]; /** diff --git a/src/Connection/PhpiredisSocketConnection.php b/src/Connection/PhpiredisSocketConnection.php deleted file mode 100644 index 6ff1f77b..00000000 --- a/src/Connection/PhpiredisSocketConnection.php +++ /dev/null @@ -1,420 +0,0 @@ -assertExtensions(); - - parent::__construct($parameters); - - $this->reader = $this->createReader(); - } - - /** - * Disconnects from the server and destroys the underlying resource and the - * protocol reader resource when PHP's garbage collector kicks in. - */ - public function __destruct() - { - parent::__destruct(); - - phpiredis_reader_destroy($this->reader); - } - - /** - * Checks if the socket and phpiredis extensions are loaded in PHP. - */ - protected function assertExtensions() - { - if (!extension_loaded('sockets')) { - throw new NotSupportedException( - 'The "sockets" extension is required by this connection backend.' - ); - } - - if (!extension_loaded('phpiredis')) { - throw new NotSupportedException( - 'The "phpiredis" extension is required by this connection backend.' - ); - } - } - - /** - * {@inheritdoc} - */ - protected function assertParameters(ParametersInterface $parameters) - { - switch ($parameters->scheme) { - case 'tcp': - case 'redis': - case 'unix': - break; - - default: - throw new InvalidArgumentException("Invalid scheme: '$parameters->scheme'."); - } - - if (isset($parameters->persistent)) { - throw new NotSupportedException( - 'Persistent connections are not supported by this connection backend.' - ); - } - - return $parameters; - } - - /** - * Creates a new instance of the protocol reader resource. - * - * @return resource - */ - private function createReader() - { - $reader = phpiredis_reader_create(); - - phpiredis_reader_set_status_handler($reader, $this->getStatusHandler()); - phpiredis_reader_set_error_handler($reader, $this->getErrorHandler()); - - return $reader; - } - - /** - * Returns the underlying protocol reader resource. - * - * @return resource - */ - protected function getReader() - { - return $this->reader; - } - - /** - * Returns the handler used by the protocol reader for inline responses. - * - * @return Closure - */ - protected function getStatusHandler() - { - static $statusHandler; - - if (!$statusHandler) { - $statusHandler = function ($payload) { - return StatusResponse::get($payload); - }; - } - - return $statusHandler; - } - - /** - * Returns the handler used by the protocol reader for error responses. - * - * @return Closure - */ - protected function getErrorHandler() - { - static $errorHandler; - - if (!$errorHandler) { - $errorHandler = function ($errorMessage) { - return new ErrorResponse($errorMessage); - }; - } - - return $errorHandler; - } - - /** - * Helper method used to throw exceptions on socket errors. - */ - private function emitSocketError() - { - $errno = socket_last_error(); - $errstr = socket_strerror($errno); - - $this->disconnect(); - - $this->onConnectionError(trim($errstr), $errno); - } - - /** - * Gets the address of an host from connection parameters. - * - * @param ParametersInterface $parameters Parameters used to initialize the connection. - * - * @return string - */ - protected static function getAddress(ParametersInterface $parameters) - { - if (filter_var($host = $parameters->host, FILTER_VALIDATE_IP)) { - return $host; - } - - if ($host === $address = gethostbyname($host)) { - return false; - } - - return $address; - } - - /** - * {@inheritdoc} - */ - protected function createResource() - { - $parameters = $this->parameters; - - if ($parameters->scheme === 'unix') { - $address = $parameters->path; - $domain = AF_UNIX; - $protocol = 0; - } else { - if (false === $address = self::getAddress($parameters)) { - $this->onConnectionError("Cannot resolve the address of '$parameters->host'."); - } - - $domain = filter_var($address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) ? AF_INET6 : AF_INET; - $protocol = SOL_TCP; - } - - if (false === $socket = @socket_create($domain, SOCK_STREAM, $protocol)) { - $this->emitSocketError(); - } - - $this->setSocketOptions($socket, $parameters); - $this->connectWithTimeout($socket, $address, $parameters); - - return $socket; - } - - /** - * Sets options on the socket resource from the connection parameters. - * - * @param resource $socket Socket resource. - * @param ParametersInterface $parameters Parameters used to initialize the connection. - */ - private function setSocketOptions($socket, ParametersInterface $parameters) - { - if ($parameters->scheme !== 'unix') { - if (!socket_set_option($socket, SOL_TCP, TCP_NODELAY, 1)) { - $this->emitSocketError(); - } - - if (!socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1)) { - $this->emitSocketError(); - } - } - - if (isset($parameters->read_write_timeout)) { - $rwtimeout = (float) $parameters->read_write_timeout; - $timeoutSec = floor($rwtimeout); - $timeoutUsec = ($rwtimeout - $timeoutSec) * 1000000; - - $timeout = [ - 'sec' => $timeoutSec, - 'usec' => $timeoutUsec, - ]; - - if (!socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, $timeout)) { - $this->emitSocketError(); - } - - if (!socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, $timeout)) { - $this->emitSocketError(); - } - } - } - - /** - * Opens the actual connection to the server with a timeout. - * - * @param resource $socket Socket resource. - * @param string $address IP address (DNS-resolved from hostname) - * @param ParametersInterface $parameters Parameters used to initialize the connection. - * - * @return void - */ - private function connectWithTimeout($socket, $address, ParametersInterface $parameters) - { - socket_set_nonblock($socket); - - if (@socket_connect($socket, $address, (int) $parameters->port) === false) { - $error = socket_last_error(); - - if ($error != SOCKET_EINPROGRESS && $error != SOCKET_EALREADY) { - $this->emitSocketError(); - } - } - - socket_set_block($socket); - - $null = null; - $selectable = [$socket]; - - $timeout = (isset($parameters->timeout) ? (float) $parameters->timeout : 5.0); - $timeoutSecs = floor($timeout); - $timeoutUSecs = ($timeout - $timeoutSecs) * 1000000; - - $selected = socket_select($selectable, $selectable, $null, $timeoutSecs, $timeoutUSecs); - - if ($selected === 2) { - $this->onConnectionError('Connection refused.', SOCKET_ECONNREFUSED); - } - - if ($selected === 0) { - $this->onConnectionError('Connection timed out.', SOCKET_ETIMEDOUT); - } - - if ($selected === false) { - $this->emitSocketError(); - } - } - - /** - * {@inheritdoc} - */ - public function connect() - { - if (parent::connect() && $this->initCommands) { - foreach ($this->initCommands as $command) { - $response = $this->executeCommand($command); - - if ($response instanceof ErrorResponseInterface) { - $this->onConnectionError("`{$command->getId()}` failed: {$response->getMessage()}", 0); - } - } - } - } - - /** - * {@inheritdoc} - */ - public function disconnect() - { - if ($this->isConnected()) { - phpiredis_reader_reset($this->reader); - socket_close($this->getResource()); - - parent::disconnect(); - } - } - - /** - * {@inheritdoc} - */ - protected function write($buffer) - { - $socket = $this->getResource(); - - while (($length = strlen($buffer)) > 0) { - $written = socket_write($socket, $buffer, $length); - - if ($length === $written) { - return; - } - - if ($written === false) { - $this->onConnectionError('Error while writing bytes to the server.'); - } - - $buffer = substr($buffer, $written); - } - } - - /** - * {@inheritdoc} - */ - public function read() - { - $socket = $this->getResource(); - $reader = $this->reader; - - while (PHPIREDIS_READER_STATE_INCOMPLETE === $state = phpiredis_reader_get_state($reader)) { - if (@socket_recv($socket, $buffer, 4096, 0) === false || $buffer === '' || $buffer === null) { - $this->emitSocketError(); - } - - phpiredis_reader_feed($reader, $buffer); - } - - if ($state === PHPIREDIS_READER_STATE_COMPLETE) { - return phpiredis_reader_get_reply($reader); - } else { - $this->onProtocolError(phpiredis_reader_get_error($reader)); - - return; - } - } - - /** - * {@inheritdoc} - */ - public function writeRequest(CommandInterface $command) - { - $arguments = $command->getArguments(); - array_unshift($arguments, $command->getId()); - - $this->write(phpiredis_format_command($arguments)); - } - - /** - * {@inheritdoc} - */ - public function __wakeup() - { - $this->assertExtensions(); - $this->reader = $this->createReader(); - } -} diff --git a/src/Connection/PhpiredisStreamConnection.php b/src/Connection/PhpiredisStreamConnection.php deleted file mode 100644 index e3dbfd8a..00000000 --- a/src/Connection/PhpiredisStreamConnection.php +++ /dev/null @@ -1,262 +0,0 @@ -assertExtensions(); - - parent::__construct($parameters); - - $this->reader = $this->createReader(); - } - - /** - * {@inheritdoc} - */ - public function __destruct() - { - parent::__destruct(); - - phpiredis_reader_destroy($this->reader); - } - - /** - * {@inheritdoc} - */ - public function disconnect() - { - phpiredis_reader_reset($this->reader); - - parent::disconnect(); - } - - /** - * Checks if the phpiredis extension is loaded in PHP. - */ - private function assertExtensions() - { - if (!extension_loaded('phpiredis')) { - throw new NotSupportedException( - 'The "phpiredis" extension is required by this connection backend.' - ); - } - } - - /** - * {@inheritdoc} - */ - protected function assertParameters(ParametersInterface $parameters) - { - switch ($parameters->scheme) { - case 'tcp': - case 'redis': - case 'unix': - break; - - case 'tls': - case 'rediss': - throw new InvalidArgumentException('SSL encryption is not supported by this connection backend.'); - default: - throw new InvalidArgumentException("Invalid scheme: '$parameters->scheme'."); - } - - return $parameters; - } - - /** - * {@inheritdoc} - */ - protected function createStreamSocket(ParametersInterface $parameters, $address, $flags) - { - $socket = null; - $timeout = (isset($parameters->timeout) ? (float) $parameters->timeout : 5.0); - $context = stream_context_create(['socket' => ['tcp_nodelay' => (bool) $parameters->tcp_nodelay]]); - - if (!$resource = @stream_socket_client($address, $errno, $errstr, $timeout, $flags, $context)) { - $this->onConnectionError(trim($errstr), $errno); - } - - if (isset($parameters->read_write_timeout) && function_exists('socket_import_stream')) { - $rwtimeout = (float) $parameters->read_write_timeout; - $rwtimeout = $rwtimeout > 0 ? $rwtimeout : -1; - - $timeout = [ - 'sec' => $timeoutSeconds = floor($rwtimeout), - 'usec' => ($rwtimeout - $timeoutSeconds) * 1000000, - ]; - - $socket = $socket ?: socket_import_stream($resource); - @socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, $timeout); - @socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, $timeout); - } - - if (isset($parameters->tcp_nodelay) && function_exists('socket_import_stream')) { - $socket = $socket ?: socket_import_stream($resource); - socket_set_option($socket, SOL_TCP, TCP_NODELAY, (int) $parameters->tcp_nodelay); - } - - return $resource; - } - - /** - * Creates a new instance of the protocol reader resource. - * - * @return resource - */ - private function createReader() - { - $reader = phpiredis_reader_create(); - - phpiredis_reader_set_status_handler($reader, $this->getStatusHandler()); - phpiredis_reader_set_error_handler($reader, $this->getErrorHandler()); - - return $reader; - } - - /** - * Returns the underlying protocol reader resource. - * - * @return resource - */ - protected function getReader() - { - return $this->reader; - } - - /** - * Returns the handler used by the protocol reader for inline responses. - * - * @return Closure - */ - protected function getStatusHandler() - { - static $statusHandler; - - if (!$statusHandler) { - $statusHandler = function ($payload) { - return StatusResponse::get($payload); - }; - } - - return $statusHandler; - } - - /** - * Returns the handler used by the protocol reader for error responses. - * - * @return Closure - */ - protected function getErrorHandler() - { - static $errorHandler; - - if (!$errorHandler) { - $errorHandler = function ($errorMessage) { - return new ErrorResponse($errorMessage); - }; - } - - return $errorHandler; - } - - /** - * {@inheritdoc} - */ - public function read() - { - $socket = $this->getResource(); - $reader = $this->reader; - - while (PHPIREDIS_READER_STATE_INCOMPLETE === $state = phpiredis_reader_get_state($reader)) { - $buffer = stream_socket_recvfrom($socket, 4096); - - if ($buffer === false || $buffer === '') { - $this->onConnectionError('Error while reading bytes from the server.'); - } - - phpiredis_reader_feed($reader, $buffer); - } - - if ($state === PHPIREDIS_READER_STATE_COMPLETE) { - return phpiredis_reader_get_reply($reader); - } else { - $this->onProtocolError(phpiredis_reader_get_error($reader)); - - return; - } - } - - /** - * {@inheritdoc} - */ - public function writeRequest(CommandInterface $command) - { - $arguments = $command->getArguments(); - array_unshift($arguments, $command->getId()); - - $this->write(phpiredis_format_command($arguments)); - } - - /** - * {@inheritdoc} - */ - public function __wakeup() - { - $this->assertExtensions(); - $this->reader = $this->createReader(); - } -} diff --git a/src/Connection/WebdisConnection.php b/src/Connection/WebdisConnection.php deleted file mode 100644 index bd533783..00000000 --- a/src/Connection/WebdisConnection.php +++ /dev/null @@ -1,366 +0,0 @@ -assertExtensions(); - - if ($parameters->scheme !== 'http') { - throw new InvalidArgumentException("Invalid scheme: '{$parameters->scheme}'."); - } - - $this->parameters = $parameters; - - $this->resource = $this->createCurl(); - $this->reader = $this->createReader(); - } - - /** - * Frees the underlying cURL and protocol reader resources when the garbage - * collector kicks in. - */ - public function __destruct() - { - curl_close($this->resource); - phpiredis_reader_destroy($this->reader); - } - - /** - * Helper method used to throw on unsupported methods. - * - * @param string $method Name of the unsupported method. - * - * @throws NotSupportedException - */ - private function throwNotSupportedException($method) - { - $class = __CLASS__; - throw new NotSupportedException("The method $class::$method() is not supported."); - } - - /** - * Checks if the cURL and phpiredis extensions are loaded in PHP. - */ - private function assertExtensions() - { - if (!extension_loaded('curl')) { - throw new NotSupportedException( - 'The "curl" extension is required by this connection backend.' - ); - } - - if (!extension_loaded('phpiredis')) { - throw new NotSupportedException( - 'The "phpiredis" extension is required by this connection backend.' - ); - } - } - - /** - * Initializes cURL. - * - * @return resource - */ - private function createCurl() - { - $parameters = $this->getParameters(); - $timeout = (isset($parameters->timeout) ? (float) $parameters->timeout : 5.0) * 1000; - - if (filter_var($host = $parameters->host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { - $host = "[$host]"; - } - - $options = [ - CURLOPT_FAILONERROR => true, - CURLOPT_CONNECTTIMEOUT_MS => $timeout, - CURLOPT_URL => "$parameters->scheme://$host:$parameters->port", - CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, - CURLOPT_POST => true, - CURLOPT_WRITEFUNCTION => [$this, 'feedReader'], - ]; - - if (isset($parameters->user, $parameters->pass)) { - $options[CURLOPT_USERPWD] = "{$parameters->user}:{$parameters->pass}"; - } - - curl_setopt_array($resource = curl_init(), $options); - - return $resource; - } - - /** - * Initializes the phpiredis protocol reader. - * - * @return resource - */ - private function createReader() - { - $reader = phpiredis_reader_create(); - - phpiredis_reader_set_status_handler($reader, $this->getStatusHandler()); - phpiredis_reader_set_error_handler($reader, $this->getErrorHandler()); - - return $reader; - } - - /** - * Returns the handler used by the protocol reader for inline responses. - * - * @return Closure - */ - protected function getStatusHandler() - { - static $statusHandler; - - if (!$statusHandler) { - $statusHandler = function ($payload) { - return StatusResponse::get($payload); - }; - } - - return $statusHandler; - } - - /** - * Returns the handler used by the protocol reader for error responses. - * - * @return Closure - */ - protected function getErrorHandler() - { - static $errorHandler; - - if (!$errorHandler) { - $errorHandler = function ($errorMessage) { - return new ErrorResponse($errorMessage); - }; - } - - return $errorHandler; - } - - /** - * Feeds the phpredis reader resource with the data read from the network. - * - * @param resource $resource Reader resource. - * @param string $buffer Buffer of data read from a connection. - * - * @return int - */ - protected function feedReader($resource, $buffer) - { - phpiredis_reader_feed($this->reader, $buffer); - - return strlen($buffer); - } - - /** - * {@inheritdoc} - */ - public function connect() - { - // NOOP - } - - /** - * {@inheritdoc} - */ - public function disconnect() - { - // NOOP - } - - /** - * {@inheritdoc} - */ - public function isConnected() - { - return true; - } - - /** - * Checks if the specified command is supported by this connection class. - * - * @param CommandInterface $command Command instance. - * - * @return string - * @throws NotSupportedException - */ - protected function getCommandId(CommandInterface $command) - { - switch ($commandID = $command->getId()) { - case 'AUTH': - case 'SELECT': - case 'MULTI': - case 'EXEC': - case 'WATCH': - case 'UNWATCH': - case 'DISCARD': - case 'MONITOR': - throw new NotSupportedException("Command '$commandID' is not allowed by Webdis."); - default: - return $commandID; - } - } - - /** - * {@inheritdoc} - */ - public function writeRequest(CommandInterface $command) - { - $this->throwNotSupportedException(__FUNCTION__); - } - - /** - * {@inheritdoc} - */ - public function readResponse(CommandInterface $command) - { - $this->throwNotSupportedException(__FUNCTION__); - } - - /** - * {@inheritdoc} - */ - public function executeCommand(CommandInterface $command) - { - $resource = $this->resource; - $commandId = $this->getCommandId($command); - - if ($arguments = $command->getArguments()) { - $arguments = implode('/', array_map('urlencode', $arguments)); - $serializedCommand = "$commandId/$arguments.raw"; - } else { - $serializedCommand = "$commandId.raw"; - } - - curl_setopt($resource, CURLOPT_POSTFIELDS, $serializedCommand); - - if (curl_exec($resource) === false) { - $error = trim(curl_error($resource)); - $errno = curl_errno($resource); - - throw new ConnectionException($this, "$error{$this->getParameters()}]", $errno); - } - - if (phpiredis_reader_get_state($this->reader) !== PHPIREDIS_READER_STATE_COMPLETE) { - throw new ProtocolException($this, phpiredis_reader_get_error($this->reader)); - } - - return phpiredis_reader_get_reply($this->reader); - } - - /** - * {@inheritdoc} - */ - public function getResource() - { - return $this->resource; - } - - /** - * {@inheritdoc} - */ - public function getParameters() - { - return $this->parameters; - } - - /** - * {@inheritdoc} - */ - public function addConnectCommand(CommandInterface $command) - { - $this->throwNotSupportedException(__FUNCTION__); - } - - /** - * {@inheritdoc} - */ - public function read() - { - $this->throwNotSupportedException(__FUNCTION__); - } - - /** - * {@inheritdoc} - */ - public function __toString() - { - return "{$this->parameters->host}:{$this->parameters->port}"; - } - - /** - * {@inheritdoc} - */ - public function __sleep() - { - return ['parameters']; - } - - /** - * {@inheritdoc} - */ - public function __wakeup() - { - $this->assertExtensions(); - - $this->resource = $this->createCurl(); - $this->reader = $this->createReader(); - } -} diff --git a/tests/Predis/Cluster/Hash/PhpiredisCRC16Test.php b/tests/Predis/Cluster/Hash/PhpiredisCRC16Test.php deleted file mode 100644 index b274887e..00000000 --- a/tests/Predis/Cluster/Hash/PhpiredisCRC16Test.php +++ /dev/null @@ -1,42 +0,0 @@ -assertSame(58359, $crc16->hash('key:000')); - $this->assertSame(62422, $crc16->hash('key:001')); - $this->assertSame(50101, $crc16->hash('key:002')); - $this->assertSame(54164, $crc16->hash('key:003')); - $this->assertSame(41843, $crc16->hash('key:004')); - $this->assertSame(45906, $crc16->hash('key:005')); - $this->assertSame(33585, $crc16->hash('key:006')); - $this->assertSame(37648, $crc16->hash('key:007')); - $this->assertSame(25343, $crc16->hash('key:008')); - $this->assertSame(29406, $crc16->hash('key:009')); - } -} diff --git a/tests/Predis/Configuration/Option/CRC16Test.php b/tests/Predis/Configuration/Option/CRC16Test.php index 54173d92..41d80318 100644 --- a/tests/Predis/Configuration/Option/CRC16Test.php +++ b/tests/Predis/Configuration/Option/CRC16Test.php @@ -30,11 +30,7 @@ class CRC16Test extends PredisTestCase $this->assertInstanceOf('Predis\Cluster\Hash\HashGeneratorInterface', $hashGenerator); - if (function_exists('phpiredis_utils_crc16')) { - $this->assertInstanceOf('Predis\Cluster\Hash\PhpiredisCRC16', $hashGenerator); - } else { - $this->assertInstanceOf('Predis\Cluster\Hash\CRC16', $hashGenerator); - } + $this->assertInstanceOf('Predis\Cluster\Hash\CRC16', $hashGenerator); } /** @@ -113,29 +109,13 @@ class CRC16Test extends PredisTestCase $this->assertInstanceOf('Predis\Cluster\Hash\CRC16', $option->filter($options, 'predis')); } - /** - * @group disconnected - * @group ext-phpiredis - * @requires extension phpiredis - * @requires function phpiredis_utils_crc16 - */ - public function testAcceptsShortNameStringPhpiredis(): void - { - $option = new CRC16(); - - /** @var OptionsInterface */ - $options = $this->getMockBuilder('Predis\Configuration\OptionsInterface')->getMock(); - - $this->assertInstanceOf('Predis\Cluster\Hash\PhpiredisCRC16', $option->filter($options, 'phpiredis')); - } - /** * @group disconnected */ public function testThrowsExceptionOnInvalidShortNameString(): void { $this->expectException('InvalidArgumentException'); - $this->expectExceptionMessage('String value for the crc16 option must be either `predis` or `phpiredis`'); + $this->expectExceptionMessage('String value for the crc16 option must be either `predis`'); $option = new CRC16(); diff --git a/tests/Predis/Configuration/Option/ConnectionsTest.php b/tests/Predis/Configuration/Option/ConnectionsTest.php index 346049b0..1fb0a391 100644 --- a/tests/Predis/Configuration/Option/ConnectionsTest.php +++ b/tests/Predis/Configuration/Option/ConnectionsTest.php @@ -229,9 +229,6 @@ class ConnectionsTest extends PredisTestCase public function provideSupportedStringValuesForOption() { return [ - ['phpiredis-stream', 'Predis\Connection\PhpiredisStreamConnection'], - ['phpiredis-socket', 'Predis\Connection\PhpiredisSocketConnection'], - ['phpiredis', 'Predis\Connection\PhpiredisStreamConnection'], ['relay', \Predis\Connection\RelayConnection::class], ]; } diff --git a/tests/Predis/Connection/PhpiredisSocketConnectionTest.php b/tests/Predis/Connection/PhpiredisSocketConnectionTest.php deleted file mode 100644 index 8c4dd117..00000000 --- a/tests/Predis/Connection/PhpiredisSocketConnectionTest.php +++ /dev/null @@ -1,120 +0,0 @@ -expectException('InvalidArgumentException'); - $this->expectExceptionMessage("Invalid scheme: 'tls'"); - - $connection = $this->createConnectionWithParams(['scheme' => 'tls']); - - $this->assertInstanceOf('Predis\Connection\NodeConnectionInterface', $connection); - } - - /** - * @group disconnected - */ - public function testSupportsSchemeRediss(): void - { - $this->expectException('InvalidArgumentException'); - $this->expectExceptionMessage("Invalid scheme: 'rediss'"); - - $connection = $this->createConnectionWithParams(['scheme' => 'rediss']); - - $this->assertInstanceOf('Predis\Connection\NodeConnectionInterface', $connection); - } - - /** - * @group disconnected - */ - public function testThrowsExceptionOnInitializationCommandFailure(): void - { - $this->expectException('Predis\Connection\ConnectionException'); - $this->expectExceptionMessage('`SELECT` failed: ERR invalid DB index [tcp://127.0.0.1:6379]'); - - $cmdSelect = RawCommand::create('SELECT', '1000'); - - /** @var NodeConnectionInterface|MockObject */ - $connection = $this - ->getMockBuilder($this->getConnectionClass()) - ->onlyMethods(['executeCommand', 'createResource']) - ->setConstructorArgs([new Parameters()]) - ->getMock(); - $connection - ->method('executeCommand') - ->with($cmdSelect) - ->willReturn( - new ErrorResponse('ERR invalid DB index') - ); - - $connection->method('createResource'); - - $connection->addConnectCommand($cmdSelect); - $connection->connect(); - } - - // ******************************************************************** // - // ---- INTEGRATION TESTS --------------------------------------------- // - // ******************************************************************** // - - /** - * @group connected - */ - public function testThrowsExceptionOnUnresolvableHostname(): void - { - $this->expectException('Predis\Connection\ConnectionException'); - $this->expectExceptionMessage("Cannot resolve the address of 'bogus.tld'"); - - $connection = $this->createConnectionWithParams(['host' => 'bogus.tld']); - $connection->connect(); - } - - /** - * @medium - * @group connected - */ - public function testThrowsExceptionOnProtocolDesynchronizationErrors(): void - { - $this->expectException('Predis\Protocol\ProtocolException'); - - $connection = $this->createConnection(); - $socket = $connection->getResource(); - - $connection->writeRequest($this->getCommandFactory()->create('ping')); - socket_read($socket, 1); - - $connection->read(); - } -} diff --git a/tests/Predis/Connection/PhpiredisStreamConnectionTest.php b/tests/Predis/Connection/PhpiredisStreamConnectionTest.php deleted file mode 100644 index 83c5d2a5..00000000 --- a/tests/Predis/Connection/PhpiredisStreamConnectionTest.php +++ /dev/null @@ -1,240 +0,0 @@ -expectException('InvalidArgumentException'); - $this->expectExceptionMessage('SSL encryption is not supported by this connection backend'); - - $connection = $this->createConnectionWithParams(['scheme' => 'tls']); - - $this->assertInstanceOf('Predis\Connection\NodeConnectionInterface', $connection); - } - - /** - * @group disconnected - */ - public function testSupportsSchemeRediss(): void - { - $this->expectException('InvalidArgumentException'); - $this->expectExceptionMessage('SSL encryption is not supported by this connection backend'); - - $connection = $this->createConnectionWithParams(['scheme' => 'rediss']); - - $this->assertInstanceOf('Predis\Connection\NodeConnectionInterface', $connection); - } - - /** - * @group disconnected - */ - public function testThrowsExceptionOnInitializationCommandFailure(): void - { - $this->expectException('Predis\Connection\ConnectionException'); - $this->expectExceptionMessage('`SELECT` failed: ERR invalid DB index [tcp://127.0.0.1:6379]'); - - $cmdSelect = RawCommand::create('SELECT', '1000'); - - /** @var NodeConnectionInterface|MockObject */ - $connection = $this - ->getMockBuilder($this->getConnectionClass()) - ->onlyMethods(['executeCommand', 'createResource']) - ->setConstructorArgs([new Parameters()]) - ->getMock(); - $connection - ->method('executeCommand') - ->with($cmdSelect) - ->willReturn( - new ErrorResponse('ERR invalid DB index') - ); - - $connection->method('createResource'); - - $connection->addConnectCommand($cmdSelect); - $connection->connect(); - } - - // ******************************************************************** // - // ---- INTEGRATION TESTS --------------------------------------------- // - // ******************************************************************** // - - /** - * @group connected - * @group slow - * @requires PHP 5.4 - */ - public function testThrowsExceptionOnReadWriteTimeout(): void - { - $this->expectException('Predis\Connection\ConnectionException'); - - $connection = $this->createConnectionWithParams([ - 'read_write_timeout' => 0.5, - ], true); - - $connection->executeCommand( - $this->getCommandFactory()->create('brpop', ['foo', 3]) - ); - } - - /** - * @medium - * @group connected - */ - public function testThrowsExceptionOnProtocolDesynchronizationErrors(): void - { - $this->expectException('Predis\Protocol\ProtocolException'); - - $connection = $this->createConnection(); - $stream = $connection->getResource(); - - $connection->writeRequest($this->getCommandFactory()->create('ping')); - stream_socket_recvfrom($stream, 1); - - $connection->read(); - } - - /** - * @group connected - * @requires PHP 5.4 - */ - public function testPersistentParameterWithFalseLikeValues(): void - { - $connection1 = $this->createConnectionWithParams(['persistent' => 0]); - $this->assertNonPersistentConnection($connection1); - - $connection2 = $this->createConnectionWithParams(['persistent' => false]); - $this->assertNonPersistentConnection($connection2); - - $connection3 = $this->createConnectionWithParams(['persistent' => '0']); - $this->assertNonPersistentConnection($connection3); - - $connection4 = $this->createConnectionWithParams(['persistent' => 'false']); - $this->assertNonPersistentConnection($connection4); - } - - /** - * @group connected - * @requires PHP 5.4 - */ - public function testPersistentParameterWithTrueLikeValues(): void - { - $connection1 = $this->createConnectionWithParams(['persistent' => 1]); - $this->assertPersistentConnection($connection1); - - $connection2 = $this->createConnectionWithParams(['persistent' => true]); - $this->assertPersistentConnection($connection2); - - $connection3 = $this->createConnectionWithParams(['persistent' => '1']); - $this->assertPersistentConnection($connection3); - - $connection4 = $this->createConnectionWithParams(['persistent' => 'true']); - $this->assertPersistentConnection($connection4); - - $connection1->disconnect(); - } - - /** - * @group connected - * @requires PHP 5.4 - */ - public function testPersistentConnectionsToSameNodeShareResource(): void - { - $connection1 = $this->createConnectionWithParams(['persistent' => true]); - $connection2 = $this->createConnectionWithParams(['persistent' => true]); - - $this->assertPersistentConnection($connection1); - $this->assertPersistentConnection($connection2); - - $this->assertSame($connection1->getResource(), $connection2->getResource()); - - $connection1->disconnect(); - } - - /** - * @group connected - * @requires PHP 5.4 - */ - public function testPersistentConnectionsToSameNodeDoNotShareResourceUsingDifferentPersistentID(): void - { - $connection1 = $this->createConnectionWithParams(['persistent' => 'conn1']); - $connection2 = $this->createConnectionWithParams(['persistent' => 'conn2']); - - $this->assertPersistentConnection($connection1); - $this->assertPersistentConnection($connection2); - - $this->assertNotSame($connection1->getResource(), $connection2->getResource()); - } - - /** - * @group connected - */ - public function testTcpNodelayParameterSetsContextFlagWhenTrue() - { - $connection = $this->createConnectionWithParams(['tcp_nodelay' => true]); - $options = stream_context_get_options($connection->getResource()); - - $this->assertIsArray($options); - $this->assertArrayHasKey('socket', $options); - $this->assertArrayHasKey('tcp_nodelay', $options['socket']); - $this->assertTrue($options['socket']['tcp_nodelay']); - } - - /** - * @group connected - */ - public function testTcpNodelayParameterDoesNotSetContextFlagWhenFalse() - { - $connection = $this->createConnectionWithParams(['tcp_nodelay' => false]); - $options = stream_context_get_options($connection->getResource()); - - $this->assertIsArray($options); - $this->assertArrayHasKey('socket', $options); - $this->assertArrayHasKey('tcp_nodelay', $options['socket']); - $this->assertFalse($options['socket']['tcp_nodelay']); - } - - /** - * @group connected - */ - public function testTcpDelayContextFlagIsNotSetByDefault() - { - $connection = $this->createConnectionWithParams([]); - $options = stream_context_get_options($connection->getResource()); - - $this->assertIsArray($options); - $this->assertArrayHasKey('socket', $options); - $this->assertArrayHasKey('tcp_nodelay', $options['socket']); - $this->assertFalse($options['socket']['tcp_nodelay']); - } -} diff --git a/tests/Predis/Connection/WebdisConnectionTest.php b/tests/Predis/Connection/WebdisConnectionTest.php deleted file mode 100644 index e0d6797e..00000000 --- a/tests/Predis/Connection/WebdisConnectionTest.php +++ /dev/null @@ -1,227 +0,0 @@ -createConnection(); - - $this->assertTrue($connection->isConnected()); - } - - /** - * @group disconnected - */ - public function testSupportsSchemeUnix(): void - { - $connection = $this->createConnectionWithParams(['scheme' => 'http']); - - $this->assertInstanceOf('Predis\Connection\NodeConnectionInterface', $connection); - } - - /** - * @group disconnected - */ - public function testThrowsExceptionOnInvalidScheme(): void - { - $this->expectException('InvalidArgumentException'); - $this->expectExceptionMessage("Invalid scheme: 'tcp'"); - - $connection = $this->createConnectionWithParams(['scheme' => 'tcp']); - } - - /** - * @group disconnected - */ - public function testWritingCommandsIsNotSupported(): void - { - $this->expectException('Predis\NotSupportedException'); - $this->expectExceptionMessage("The method Predis\Connection\WebdisConnection::writeRequest() is not supported"); - - $connection = $this->createConnection(); - $connection->writeRequest($this->getCommandFactory()->create('ping')); - } - - /** - * @group disconnected - */ - public function testReadingResponsesIsNotSupported(): void - { - $this->expectException('Predis\NotSupportedException'); - $this->expectExceptionMessage("The method Predis\Connection\WebdisConnection::readResponse() is not supported"); - - $connection = $this->createConnection(); - $connection->readResponse($this->getCommandFactory()->create('ping')); - } - - /** - * @group disconnected - */ - public function testReadingFromConnectionIsNotSupported(): void - { - $this->expectException('Predis\NotSupportedException'); - $this->expectExceptionMessage("The method Predis\Connection\WebdisConnection::read() is not supported"); - - $connection = $this->createConnection(); - $connection->read(); - } - - /** - * @group disconnected - */ - public function testAddingConnectCommandsIsNotSupported(): void - { - $this->expectException('Predis\NotSupportedException'); - $this->expectExceptionMessage("The method Predis\Connection\WebdisConnection::addConnectCommand() is not supported"); - - $connection = $this->createConnection(); - $connection->addConnectCommand($this->getCommandFactory()->create('ping')); - } - - /** - * @group disconnected - */ - public function testRejectCommandSelect(): void - { - $this->expectException('Predis\NotSupportedException'); - $this->expectExceptionMessage("Command 'SELECT' is not allowed by Webdis"); - - $connection = $this->createConnection(); - $connection->executeCommand($this->getCommandFactory()->create('select', [0])); - } - - /** - * @group disconnected - */ - public function testRejectCommandAuth(): void - { - $this->expectException('Predis\NotSupportedException'); - $this->expectExceptionMessage("Command 'AUTH' is not allowed by Webdis"); - - $connection = $this->createConnection(); - $connection->executeCommand($this->getCommandFactory()->create('auth', ['foobar'])); - } - - /** - * @group disconnected - */ - public function testCanBeSerialized(): void - { - $parameters = $this->getParameters([ - 'alias' => 'redis', - 'read_write_timeout' => 10, - ]); - - $connection = $this->createConnectionWithParams($parameters); - - $unserialized = unserialize(serialize($connection)); - - $this->assertInstanceOf('Predis\Connection\WebdisConnection', $unserialized); - $this->assertEquals($parameters, $unserialized->getParameters()); - } - - // ******************************************************************** // - // ---- INTEGRATION TESTS --------------------------------------------- // - // ******************************************************************** // - - /** - * @group connected - */ - public function testExecutesMultipleCommandsOnServer(): void - { - $commands = $this->getCommandFactory(); - - $cmdPing = $commands->create('ping'); - $cmdEcho = $commands->create('echo', ['echoed']); - $cmdGet = $commands->create('get', ['foobar']); - $cmdRpush = $commands->create('rpush', ['metavars', 'foo', 'hoge', 'lol']); - $cmdLrange = $commands->create('lrange', ['metavars', 0, -1]); - - $connection = $this->createConnection(true); - - $this->assertEquals('PONG', $connection->executeCommand($cmdPing)); - $this->assertSame('echoed', $connection->executeCommand($cmdEcho)); - $this->assertNull($connection->executeCommand($cmdGet)); - $this->assertSame(3, $connection->executeCommand($cmdRpush)); - $this->assertSame(['foo', 'hoge', 'lol'], $connection->executeCommand($cmdLrange)); - } - - /** - * @medium - * @group disconnected - * @group slow - */ - public function testThrowExceptionWhenUnableToConnect(): void - { - $this->expectException('Predis\Connection\ConnectionException'); - - $connection = $this->createConnectionWithParams(['host' => '169.254.10.10']); - $connection->executeCommand($this->getCommandFactory()->create('ping')); - } - - // ******************************************************************** // - // ---- HELPER METHODS ------------------------------------------------ // - // ******************************************************************** // - - /** - * Returns a named array with the default connection parameters and their values. - * - * @return array Default connection parameters - */ - protected function getDefaultParametersArray(): array - { - return [ - 'scheme' => 'http', - 'host' => constant('WEBDIS_SERVER_HOST'), - 'port' => constant('WEBDIS_SERVER_PORT'), - ]; - } - - /** - * {@inheritdoc} - */ - protected function createConnection(): NodeConnectionInterface - { - return $this->createConnectionWithParams([]); - } - - /** - * {@inheritdoc} - */ - protected function createConnectionWithParams($parameters): NodeConnectionInterface - { - if (!$parameters instanceof ParametersInterface) { - $parameters = $this->getParameters($parameters); - } - - $connection = new WebdisConnection($parameters); - $connection->executeCommand($this->getCommandFactory()->create('flushdb')); - - return $connection; - } -} From e831a3ef3436647a0844e01141ae3d2d7ce5a7c3 Mon Sep 17 00:00:00 2001 From: Vladyslav Vildanov <117659936+vladvildanov@users.noreply.github.com> Date: Tue, 13 Jun 2023 12:41:44 +0300 Subject: [PATCH 9/9] 2.x main sync (#1317) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Added support for Redis JSON module commands, added JSON.SET and JSON.GET commands (#868) * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Fixed bug with incorrect tests skip * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Fixed bug with incorrect tests skip * Fixed naming issue with nxXx argument * Removed redundant trait * Fixed NxXxArgument test * add Redis stack tests * don't run tests twice * use * Update stack.yml * Rename workflows * Added version 6.x to workflow * Removed exception thrown to avoid version bug * Resolve conflicts within tests.yml * Codestyle fixes * Removew trailing whitespaces Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss * Added support for Bloom Filters module, added support for BF.ADD, BF.EXISTS commands (#874) * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Added support for BF.ADD and BF.EXISTS commands * Fixed bug with incorrect tests skip * Changed module name according to original naming * Revert some old changes * Fixed misspelling Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss * Added support for Cuckoo Filter, added CF.ADD and CF.EXISTS commands (#907) * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Added support for BF.ADD and BF.EXISTS commands * Fixed bug with incorrect tests skip * Changed module name according to original naming * Added support for CF.ADD and CF.EXISTS commands * Removed old files * Revert old changes Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss * Extended Bloom filters by implementing BF.INFO command (#886) * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Added support for BF.ADD and BF.EXISTS commands * Added support for BF.INFO command * Fixed arguments data provider * Fixed bug with incorrect tests skip * Added command description * Removed unused import * Removed old directory Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss * Extend Bloom filters by imlplementing BFMADD and BFMEXISTS commands (#887) * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Added support for BF.ADD and BF.EXISTS commands * Fixed bug with incorrect tests skip * Added support for BF.MADD and BF.MEXISTS commands * Removed old file * Revert changes Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss * Extended Bloom Filters by implementing BF.RESERVE command (#888) * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Added support for BF.ADD and BF.EXISTS commands * Added support for BF.INFO command * Fixed arguments data provider * Fixed bug with incorrect tests skip * Added support for BF.RESERVE command * Added command description * Codestyle fixes * Added missing test Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss * Extended Bloom Filter by implementing BF.SCANDUMP command (#889) * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Added support for BF.ADD and BF.EXISTS commands * Fixed bug with incorrect tests skip * Added support for BF.SCANDUMP command Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss * Extended Bloom Filters by implementing BF.LOADCHUNK command (#890) * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Added support for BF.ADD and BF.EXISTS commands * Fixed bug with incorrect tests skip * Added support for BF.SCANDUMP command * Added support for BF.LOADCHUNK command * Codestyle fixes * Sort alphabetical Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss * Extended Bloom Filter support by implementing BF.INSERT command (#891) * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Added support for BF.ADD and BF.EXISTS commands * Added support for BF.INFO command * Fixed arguments data provider * Fixed bug with incorrect tests skip * Added support for BF.RESERVE command * Added command description * Added support for BF.INSERT command Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss * Extended Redis JSON support by implementing JSON.MGET (#892) * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Fixed bug with incorrect tests skip * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Fixed bug with incorrect tests skip * Fixed naming issue with nxXx argument * Removed redundant trait * Fixed NxXxArgument test * Added support for JSON.MGET command Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss * Extended RedisJson support by implementing JSON.DEL command (#909) * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Fixed bug with incorrect tests skip * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Fixed bug with incorrect tests skip * Fixed naming issue with nxXx argument * Removed redundant trait * Fixed NxXxArgument test * Added support for JSON.DEL command Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss * Extended RedisJson support by implementing JSON.OBJKEYS command (#911) * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Fixed bug with incorrect tests skip * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Fixed bug with incorrect tests skip * Fixed naming issue with nxXx argument * Removed redundant trait * Fixed NxXxArgument test * Add support for JSON.OBJKEYS command Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss * Extended RedisJson support by implementing JSON.OBJLEN command (#913) * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Fixed bug with incorrect tests skip * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Fixed bug with incorrect tests skip * Fixed naming issue with nxXx argument * Removed redundant trait * Fixed NxXxArgument test * Added support for JSON.OBJLEN command Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss * Extended RedisJson support by implementing JSON.STRAPPEND command (#915) * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Fixed bug with incorrect tests skip * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Fixed bug with incorrect tests skip * Fixed naming issue with nxXx argument * Removed redundant trait * Fixed NxXxArgument test * Added support for JSON.STRAPPEND command * Codestyle fix Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss * Extended RedisJson support by implementing JSON.STRLEN command (#917) * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Fixed bug with incorrect tests skip * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Fixed bug with incorrect tests skip * Fixed naming issue with nxXx argument * Removed redundant trait * Fixed NxXxArgument test * Added support for JSON.STRLEN command Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss * Extended RedisJson support by implementing JSON.NUMINCRBY command (#919) * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Fixed bug with incorrect tests skip * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Fixed bug with incorrect tests skip * Fixed naming issue with nxXx argument * Removed redundant trait * Fixed NxXxArgument test * Added support for JSON.NUMINCRBY command Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss * Extended RedisJson support by implementing JSON.ARRAPPEND command (#924) * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Fixed bug with incorrect tests skip * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Fixed bug with incorrect tests skip * Fixed naming issue with nxXx argument * Removed redundant trait * Fixed NxXxArgument test * Added support for JSON.ARRAPPEND command Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss * Extended RedisJson support by implementing JSON.ARRINDEX command (#927) * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Fixed bug with incorrect tests skip * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Fixed bug with incorrect tests skip * Fixed naming issue with nxXx argument * Removed redundant trait * Fixed NxXxArgument test * Added support for JSON.ARRINDEX command * Codestyle fies Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss * Extended RedisJson support by implementing JSON.ARRINSERT command (#929) * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Fixed bug with incorrect tests skip * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Fixed bug with incorrect tests skip * Fixed naming issue with nxXx argument * Removed redundant trait * Fixed NxXxArgument test * Added support for JSON.ARRINSERT command * Revert changes Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss * Extended RedisJson support by implementing JSON.ARRLEN command (#931) * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Fixed bug with incorrect tests skip * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Fixed bug with incorrect tests skip * Fixed naming issue with nxXx argument * Removed redundant trait * Fixed NxXxArgument test * Add support for JSON.ARRLEN command Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss * Extended RedisJson support by implementing JSON.ARRPOP command (#933) * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Fixed bug with incorrect tests skip * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Fixed bug with incorrect tests skip * Fixed naming issue with nxXx argument * Removed redundant trait * Fixed NxXxArgument test * Added support for JSON.ARRPOP command Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss * Extended RedisJson support by implementing JSON.ARRTRIM command (#936) * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Fixed bug with incorrect tests skip * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Fixed bug with incorrect tests skip * Fixed naming issue with nxXx argument * Removed redundant trait * Fixed NxXxArgument test * Added support for JSON.ARRTRIM command Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss * Extended RedisJson support by implementing JSON.CLEAR command (#1004) * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Fixed bug with incorrect tests skip * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Fixed bug with incorrect tests skip * Fixed naming issue with nxXx argument * Removed redundant trait * Fixed NxXxArgument test * Added support for JSON.CLEAR command Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss * Extended RedisJson support by implementing JSON.RESP command (#1006) * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Fixed bug with incorrect tests skip * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Fixed bug with incorrect tests skip * Fixed naming issue with nxXx argument * Removed redundant trait * Fixed NxXxArgument test * Added support for JSON.RESP command * Removed debugger Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss * Extended RedisJson support by implementing JSON.TOGGLE command (#1008) * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Fixed bug with incorrect tests skip * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Fixed bug with incorrect tests skip * Fixed naming issue with nxXx argument * Removed redundant trait * Fixed NxXxArgument test * Added support for JSON.TOGGLE command Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss * Extended RedisJson support by implementing JSON.TYPE command (#1010) * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Fixed bug with incorrect tests skip * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Fixed bug with incorrect tests skip * Fixed naming issue with nxXx argument * Removed redundant trait * Fixed NxXxArgument test * Added support for JSON.TYPE command Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss * Extending RedisJson support by implementing JSON.FORGET command (#1012) * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Fixed bug with incorrect tests skip * Added CommandResolver, moved resolve command logic there, added ClientConfiguration object * Fixed test, added dependecies * Added resolved command to commands array * Used aggregation approach for modules * Added decorator to check Redis JSON module version * Added support for JSON.SET and JSON.GET commands * Added separate workflow for redis-stack tests * Changed docker imange name to correct one * Fixed indentation * Added test coverage for JSON.GET command * Changed module version resolving using annotations mapping * Re-written CommandResolver test * Update ClientInterface.php * Changes to CI, readme, removed unused modules from configuration * Fixed build badge URL * Refactored annotation check to be generic for each module * Fixed bug with incorrect tests skip * Fixed naming issue with nxXx argument * Removed redundant trait * Fixed NxXxArgument test * Added support for JSON.FORGET command Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss * Add Support for CF.ADDNX (#1048) * add support for CF.ADDNX * fix key name * fix wrong command * Added support for CF.COUNT command (#1052) Co-authored-by: Vladyslav Vildanov * Support CF.MEXISTS Command (#1081) * add support for CF.ADDNX * fix key name * fix wrong command * Support CF.MEXISTS Command * fix test * Add more assertions * Added support for CF.INFO command (#1082) Co-authored-by: Vladyslav Vildanov * Added support for CF.DEL command (#1080) Co-authored-by: Vladyslav Vildanov * Extended BloomFilters support by implementing CF.INSERT command (#1083) * Added support for CF.INSERT command * Override argument position offset value to default one * Codestyle fixes --------- Co-authored-by: Vladyslav Vildanov * Extended CuckooFilters support by implementing CF.RESERVE command (#1086) * Added support for CF.RESERVE command * Codestyle fixes --------- Co-authored-by: Vladyslav Vildanov * Added support for CF.LOADCHUNK, CF.SCANDUMP commands (#1085) Co-authored-by: Vladyslav Vildanov * Added support for CF.INSERTNX command (#1087) Co-authored-by: Vladyslav Vildanov * Added support for Count-Min Sketch with base commands CMS.INITBYDIM, CMS.INFO (#1088) * Added support for Count-Min Sketches submodule, added support for CMS.INITBYDIM adn CMS.INFO commands * Codestyle fixes --------- Co-authored-by: Vladyslav Vildanov * Extended Count-Min Sketch support by implementing CMS.INITBYPROB command (#1090) * Added support for CMS.INITBYPROB command * Codestyle fixes --------- Co-authored-by: Vladyslav Vildanov * Extended Count-Min Sketch support by implementing CMS.INCRBY and CMS.QUERY commands (#1091) * Added support for CMS.INCRBY and CMS.QUERY commands * Codestyle fixes --------- Co-authored-by: Vladyslav Vildanov * Extended Count-Min Sketch support by implementing CMS.MERGE command (#1092) * Added support for CMS.MERGE command * Added command description --------- Co-authored-by: Vladyslav Vildanov * Added support for TDigest sketch, added TDIGEST.CREATE, TDIGEST.INFO commands (#1093) Co-authored-by: Vladyslav Vildanov * Extended TDigest Sketch support by implementing TDIGEST.ADD command (#1094) * Added support for TDIGEST.ADD command * Codestyle fixes --------- Co-authored-by: Vladyslav Vildanov * Added support for TDIGEST.BYRANK command (#1096) Co-authored-by: Vladyslav Vildanov * Extended TDigest support by implementing TDIGEST.BYREVRANK command (#1097) * Added support for TDIGEST.BYREVRANK command * Codestyle fixes --------- Co-authored-by: Vladyslav Vildanov * Added support for TDIGEST.CDF command (#1098) Co-authored-by: Vladyslav Vildanov * Extended support by implementing TDIGEST.MAX command (#1099) * Added support for TDIGEST.MAX command * Codestyle fixes --------- Co-authored-by: Vladyslav Vildanov * Extended support by implementing TDIGEST.MIN command (#1100) * add support for CF.ADDNX * fix key name * fix wrong command * Pulling changes * Support TDIGEST.MIN * Add support for TDIGEST.RANK command (#1103) Co-authored-by: Vladyslav Vildanov * Extended TDigest support by implementing TDIGEST.RESET command (#1104) * Added support for TDIGEST.RESET command * Codestyle fixes --------- Co-authored-by: Vladyslav Vildanov * Extended support by implementing TDIGEST.QUANTILE command (#1101) * add support for CF.ADDNX * fix key name * fix wrong command * Pulling changes * Support TDIGEST.QUANTILE * fix returned value * fix test * fix linter error * add not exsist key test * fixes after review * fix linter problem * Add support for TDIGEST.REVRANK command (#1105) Co-authored-by: Vladyslav Vildanov * Added support for TDIGEST.TRIMMED_MEAN command (#1106) Co-authored-by: Vladyslav Vildanov * Added support for TOPK.RESERVE, TOPK.INFO commands (#1107) Co-authored-by: Vladyslav Vildanov * Added commands support (#1108) Co-authored-by: Vladyslav Vildanov * Added support for TOPK.INCRBY command (#1109) Co-authored-by: Vladyslav Vildanov * Added support for TOPK.QUERY command (#1110) Co-authored-by: Vladyslav Vildanov * Added support for TDIGEST.MERGE command (#1102) Co-authored-by: Vladyslav Vildanov Co-authored-by: shacharPash <93581407+shacharPash@users.noreply.github.com> * Codestyle fixes * Changed return annotation * Sync branch with 2.x (#1169) * Added support for new arguments for BITPOS, BITCOUNT commands (#1045) * Added support for new arguments for EXPIRE, EXPIREAT commands (#1046) * Extended core support by implementing SORT_RO command (#1044) * Added support for SORT_RO command * Codestyle fixes * Added command description --------- Co-authored-by: Vladyslav Vildanov * fix deprecated call * Added support for container commands (#1049) * Added support for container commands FUNCTION LOAD, FUNCTION DELETE and FCALL * Changed ContainerInterface and AbstractContainer * Re-implement logic of abstract methods --------- Co-authored-by: Vladyslav Vildanov * Added stream commands to KeyPrefixProcessor (#1051) Co-authored-by: Vladyslav Vildanov * Fix return type of ReplicationInterface::getSlaves (#1111) * Codestyle fixes * Changed return annotation --------- Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss Co-authored-by: Stephan * Revert "Sync branch with 2.x (#1169)" (#1170) This reverts commit bc5f07daf906c925aea03ed01507ebe2abc02dd2. * Sync branch with 2.x (#1171) * Added support for new arguments for BITPOS, BITCOUNT commands (#1045) * Added support for new arguments for EXPIRE, EXPIREAT commands (#1046) * Extended core support by implementing SORT_RO command (#1044) * Added support for SORT_RO command * Codestyle fixes * Added command description --------- Co-authored-by: Vladyslav Vildanov * fix deprecated call * Added support for container commands (#1049) * Added support for container commands FUNCTION LOAD, FUNCTION DELETE and FCALL * Changed ContainerInterface and AbstractContainer * Re-implement logic of abstract methods --------- Co-authored-by: Vladyslav Vildanov * Added stream commands to KeyPrefixProcessor (#1051) Co-authored-by: Vladyslav Vildanov * Fix return type of ReplicationInterface::getSlaves (#1111) * Codestyle fixes * Changed return annotation --------- Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss Co-authored-by: Stephan * Container commands naming fixes (#1172) * Added support for new arguments for BITPOS, BITCOUNT commands (#1045) * Added support for new arguments for EXPIRE, EXPIREAT commands (#1046) * Extended core support by implementing SORT_RO command (#1044) * Added support for SORT_RO command * Codestyle fixes * Added command description --------- Co-authored-by: Vladyslav Vildanov * fix deprecated call * Added support for container commands (#1049) * Added support for container commands FUNCTION LOAD, FUNCTION DELETE and FCALL * Changed ContainerInterface and AbstractContainer * Re-implement logic of abstract methods --------- Co-authored-by: Vladyslav Vildanov * Added stream commands to KeyPrefixProcessor (#1051) Co-authored-by: Vladyslav Vildanov * Fix return type of ReplicationInterface::getSlaves (#1111) * Codestyle fixes * Changed return annotation * Changed container commands names into uppercase * Changed container commands names into uppercase --------- Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss Co-authored-by: Stephan * Added support for RediSearch, implemented FT.CREATE command (#1143) * Added support for new arguments for BITPOS, BITCOUNT commands (#1045) * Added support for new arguments for EXPIRE, EXPIREAT commands (#1046) * add support for CF.ADDNX * Extended core support by implementing SORT_RO command (#1044) * Added support for SORT_RO command * Codestyle fixes * Added command description --------- Co-authored-by: Vladyslav Vildanov * fix deprecated call * fix key name * fix wrong command * Added support for container commands (#1049) * Added support for container commands FUNCTION LOAD, FUNCTION DELETE and FCALL * Changed ContainerInterface and AbstractContainer * Re-implement logic of abstract methods --------- Co-authored-by: Vladyslav Vildanov * Added stream commands to KeyPrefixProcessor (#1051) Co-authored-by: Vladyslav Vildanov * Pulling changes * Fix return type of ReplicationInterface::getSlaves (#1111) * Added support for FT.CREATE command * Fixed tests to choose correct DB * Added test coverage * Revert changes for missing commands * Added data types enums, added methods default assignments * Fixed vector field, removed default assignments, fixed tests * Added constants enum for Sortable argument, renamed arguments object * Codestyle fixes * Rename test class * Codestyle fixes * Changed return annotation * Separate common and create interfaces * Codestyle fixes * Revert changes --------- Co-authored-by: shacharPash Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss Co-authored-by: Stephan * Extended RediSearch support by implementing FT.SEARCH command (#1145) * Added support for new arguments for BITPOS, BITCOUNT commands (#1045) * Added support for new arguments for EXPIRE, EXPIREAT commands (#1046) * add support for CF.ADDNX * Extended core support by implementing SORT_RO command (#1044) * Added support for SORT_RO command * Codestyle fixes * Added command description --------- Co-authored-by: Vladyslav Vildanov * fix deprecated call * fix key name * fix wrong command * Added support for container commands (#1049) * Added support for container commands FUNCTION LOAD, FUNCTION DELETE and FCALL * Changed ContainerInterface and AbstractContainer * Re-implement logic of abstract methods --------- Co-authored-by: Vladyslav Vildanov * Added stream commands to KeyPrefixProcessor (#1051) Co-authored-by: Vladyslav Vildanov * Pulling changes * Fix return type of ReplicationInterface::getSlaves (#1111) * Added support for FT.CREATE command * Fixed tests to choose correct DB * Added test coverage * Revert changes for missing commands * Added data types enums, added methods default assignments * Added support for search command arguments, implemented FT.SEARCH command * Fixed vector field, removed default assignments, fixed tests * Tests fixes * Added constants enum for Sortable argument, renamed arguments object * Codestyle fixes * Rename test class * Merge conflicts * Codestyle fixes * Changed return annotation * Separate common and create interfaces * Codestyle fixes * Changed search arguments to condiional * Codestyle fixes --------- Co-authored-by: shacharPash Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss Co-authored-by: Stephan * Extended RediSearch support by implementing FT.INFO command (#1148) * add support for CF.ADDNX * fix key name * fix wrong command * Pulling changes * Added support for FT.CREATE command * Fixed tests to choose correct DB * Added test coverage * Revert changes for missing commands * Added data types enums, added methods default assignments * Added support for FT.INFO command * Codestyle fixes * Fixed vector field, removed default assignments, fixed tests * Added constants enum for Sortable argument, renamed arguments object * Codestyle fixes * Rename test class --------- Co-authored-by: shacharPash Co-authored-by: Vladyslav Vildanov * Extended RediSearch support by implementing FT.ALIASADD command (#1150) * add support for CF.ADDNX * fix key name * fix wrong command * Pulling changes * Added support for FT.CREATE command * Fixed tests to choose correct DB * Added test coverage * Revert changes for missing commands * Added data types enums, added methods default assignments * Added support for FT.ALIASADD command * Fixed expected exception message * Fixed vector field, removed default assignments, fixed tests * Added constants enum for Sortable argument, renamed arguments object * Codestyle fixes * Rename test class --------- Co-authored-by: shacharPash Co-authored-by: Vladyslav Vildanov * Extended RediSearch support by implementing FT.ALIASDEL command (#1151) * add support for CF.ADDNX * fix key name * fix wrong command * Pulling changes * Added support for FT.CREATE command * Fixed tests to choose correct DB * Added test coverage * Revert changes for missing commands * Added data types enums, added methods default assignments * Added support for FT.ALIASADD command * Fixed expected exception message * Fixed vector field, removed default assignments, fixed tests * Added support for FT.ALIASDEL command * Codestyle fixes * Added constants enum for Sortable argument, renamed arguments object * Codestyle fixes * Rename test class --------- Co-authored-by: shacharPash Co-authored-by: Vladyslav Vildanov * Extended RediSearch support by implementing FT.ALIASUPDATE command (#1152) * add support for CF.ADDNX * fix key name * fix wrong command * Pulling changes * Added support for FT.CREATE command * Fixed tests to choose correct DB * Added test coverage * Revert changes for missing commands * Added data types enums, added methods default assignments * Added support for FT.ALIASADD command * Fixed expected exception message * Fixed vector field, removed default assignments, fixed tests * Added support for FT.ALIASUPDATE command * Added constants enum for Sortable argument, renamed arguments object * Codestyle fixes * Rename test class --------- Co-authored-by: shacharPash Co-authored-by: Vladyslav Vildanov * Extended RediSearch support by implementing FT.DICTADD command (#1155) * add support for CF.ADDNX * fix key name * fix wrong command * Pulling changes * Added support for FT.CREATE command * Fixed tests to choose correct DB * Added test coverage * Revert changes for missing commands * Added data types enums, added methods default assignments * Fixed vector field, removed default assignments, fixed tests * Added constants enum for Sortable argument, renamed arguments object * Codestyle fixes * Rename test class * Added support for FT.DICTADD command --------- Co-authored-by: shacharPash Co-authored-by: Vladyslav Vildanov * Extended RediSearch support by implementing FT.DICTDEL support (#1156) * add support for CF.ADDNX * fix key name * fix wrong command * Pulling changes * Added support for FT.CREATE command * Fixed tests to choose correct DB * Added test coverage * Revert changes for missing commands * Added data types enums, added methods default assignments * Fixed vector field, removed default assignments, fixed tests * Added constants enum for Sortable argument, renamed arguments object * Codestyle fixes * Rename test class * Added support for FT.DICTADD command * Added support for FT.DICTDEL command --------- Co-authored-by: shacharPash Co-authored-by: Vladyslav Vildanov * Extended RediSearch support by implementing FT.DICTDUMP command (#1157) * add support for CF.ADDNX * fix key name * fix wrong command * Pulling changes * Added support for FT.CREATE command * Fixed tests to choose correct DB * Added test coverage * Revert changes for missing commands * Added data types enums, added methods default assignments * Fixed vector field, removed default assignments, fixed tests * Added constants enum for Sortable argument, renamed arguments object * Codestyle fixes * Rename test class * Added support for FT.DICTADD command * Added support for FT.DICTDUMP command * Codestyle fixes --------- Co-authored-by: shacharPash Co-authored-by: Vladyslav Vildanov * Extended RediSearch support by implementing FT.DROPINDEX command (#1158) * add support for CF.ADDNX * fix key name * fix wrong command * Pulling changes * Added support for FT.CREATE command * Fixed tests to choose correct DB * Added test coverage * Revert changes for missing commands * Added data types enums, added methods default assignments * Fixed vector field, removed default assignments, fixed tests * Added constants enum for Sortable argument, renamed arguments object * Codestyle fixes * Rename test class * Added support for FT.DROPINDEX command * Changed arguments handling --------- Co-authored-by: shacharPash Co-authored-by: Vladyslav Vildanov * Added Redis stack test group for Redis stack tests (#1178) * Added support for new arguments for BITPOS, BITCOUNT commands (#1045) * Added support for new arguments for EXPIRE, EXPIREAT commands (#1046) * Extended core support by implementing SORT_RO command (#1044) * Added support for SORT_RO command * Codestyle fixes * Added command description --------- Co-authored-by: Vladyslav Vildanov * fix deprecated call * Added support for container commands (#1049) * Added support for container commands FUNCTION LOAD, FUNCTION DELETE and FCALL * Changed ContainerInterface and AbstractContainer * Re-implement logic of abstract methods --------- Co-authored-by: Vladyslav Vildanov * Added stream commands to KeyPrefixProcessor (#1051) Co-authored-by: Vladyslav Vildanov * Fix return type of ReplicationInterface::getSlaves (#1111) * Codestyle fixes * Changed return annotation * Marked redis stack tests with appropriate annotation --------- Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss Co-authored-by: Stephan * Extended RediSearch support by implementing FT.PROFILE command (#1161) * add support for CF.ADDNX * fix key name * fix wrong command * Pulling changes * Added support for FT.CREATE command * Fixed tests to choose correct DB * Added test coverage * Revert changes for missing commands * Added data types enums, added methods default assignments * Added support for search command arguments, implemented FT.SEARCH command * Fixed vector field, removed default assignments, fixed tests * Tests fixes * Added constants enum for Sortable argument, renamed arguments object * Codestyle fixes * Rename test class * Merge conflicts * Added support for FT.PROFILE command --------- Co-authored-by: shacharPash Co-authored-by: Vladyslav Vildanov * Extended RediSearch support by implementing FT.SPELLCHECK command (#1162) * add support for CF.ADDNX * fix key name * fix wrong command * Pulling changes * Added support for FT.CREATE command * Fixed tests to choose correct DB * Added test coverage * Revert changes for missing commands * Added data types enums, added methods default assignments * Fixed vector field, removed default assignments, fixed tests * Added constants enum for Sortable argument, renamed arguments object * Codestyle fixes * Rename test class * Added support for FT.DICTADD command * Added support for FT.SPELLCHECK command * Added test group, fixed description --------- Co-authored-by: shacharPash Co-authored-by: Vladyslav Vildanov * Extended RediSearch support by implementing FT.SYNUPDATE command (#1164) * add support for CF.ADDNX * fix key name * fix wrong command * Pulling changes * Added support for FT.CREATE command * Fixed tests to choose correct DB * Added test coverage * Revert changes for missing commands * Added data types enums, added methods default assignments * Fixed vector field, removed default assignments, fixed tests * Added constants enum for Sortable argument, renamed arguments object * Codestyle fixes * Rename test class * Added support for FT.SYNUPDATE command * Added command description --------- Co-authored-by: shacharPash Co-authored-by: Vladyslav Vildanov * Extended RediSearch support by implementing FT.SYNDUMP command (#1165) * add support for CF.ADDNX * fix key name * fix wrong command * Pulling changes * Added support for FT.CREATE command * Fixed tests to choose correct DB * Added test coverage * Revert changes for missing commands * Added data types enums, added methods default assignments * Fixed vector field, removed default assignments, fixed tests * Added constants enum for Sortable argument, renamed arguments object * Codestyle fixes * Rename test class * Added support for FT.SYNUPDATE command * Added support for FT.SYNDUMP command * Fixed order number --------- Co-authored-by: shacharPash Co-authored-by: Vladyslav Vildanov * Extended RediSearch support by implementing FT.TAGVALS command (#1166) * add support for CF.ADDNX * fix key name * fix wrong command * Pulling changes * Added support for FT.CREATE command * Fixed tests to choose correct DB * Added test coverage * Revert changes for missing commands * Added data types enums, added methods default assignments * Fixed vector field, removed default assignments, fixed tests * Added constants enum for Sortable argument, renamed arguments object * Codestyle fixes * Rename test class * Added support for FT.TAGVALS command * Added example * Fixed tests --------- Co-authored-by: shacharPash Co-authored-by: Vladyslav Vildanov * Extended RediSearch support by implementing FT.ALTER command (#1153) * add support for CF.ADDNX * fix key name * fix wrong command * Pulling changes * Added support for FT.CREATE command * Fixed tests to choose correct DB * Added test coverage * Revert changes for missing commands * Added data types enums, added methods default assignments * Fixed vector field, removed default assignments, fixed tests * Added support for FT.ALTER command * Added constants enum for Sortable argument, renamed arguments object * Codestyle fixes * Rename test class * Added example, changed command arguments interface * Updated example --------- Co-authored-by: shacharPash Co-authored-by: Vladyslav Vildanov * Extended RediSearch by implementing FT.SUGADD command (#1167) * add support for CF.ADDNX * fix key name * fix wrong command * Pulling changes * Added support for FT.CREATE command * Fixed tests to choose correct DB * Added test coverage * Revert changes for missing commands * Added data types enums, added methods default assignments * Added support for search command arguments, implemented FT.SEARCH command * Fixed vector field, removed default assignments, fixed tests * Tests fixes * Added constants enum for Sortable argument, renamed arguments object * Codestyle fixes * Rename test class * Merge conflicts * Added support for FT.SUGADD command --------- Co-authored-by: shacharPash Co-authored-by: Vladyslav Vildanov * Extended RediSearch support by implementing FT.CONFIG SET and FT.CONFIG GET commands (#1173) * Added support for new arguments for BITPOS, BITCOUNT commands (#1045) * Added support for new arguments for EXPIRE, EXPIREAT commands (#1046) * add support for CF.ADDNX * Extended core support by implementing SORT_RO command (#1044) * Added support for SORT_RO command * Codestyle fixes * Added command description --------- Co-authored-by: Vladyslav Vildanov * fix deprecated call * fix key name * fix wrong command * Added support for container commands (#1049) * Added support for container commands FUNCTION LOAD, FUNCTION DELETE and FCALL * Changed ContainerInterface and AbstractContainer * Re-implement logic of abstract methods --------- Co-authored-by: Vladyslav Vildanov * Added stream commands to KeyPrefixProcessor (#1051) Co-authored-by: Vladyslav Vildanov * Pulling changes * Fix return type of ReplicationInterface::getSlaves (#1111) * Added support for FT.CREATE command * Fixed tests to choose correct DB * Added test coverage * Revert changes for missing commands * Added data types enums, added methods default assignments * Fixed vector field, removed default assignments, fixed tests * Added constants enum for Sortable argument, renamed arguments object * Codestyle fixes * Rename test class * Codestyle fixes * Changed return annotation * Separate common and create interfaces * Codestyle fixes * Added support for FT.CONFIG SET, FT.CONFIG GET commands * Revert changes * Added examples * Added test group --------- Co-authored-by: shacharPash Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss Co-authored-by: Stephan * Extended RediSearch support by implementing FT.CONFIG HELP command (#1174) * Added support for new arguments for BITPOS, BITCOUNT commands (#1045) * Added support for new arguments for EXPIRE, EXPIREAT commands (#1046) * add support for CF.ADDNX * Extended core support by implementing SORT_RO command (#1044) * Added support for SORT_RO command * Codestyle fixes * Added command description --------- Co-authored-by: Vladyslav Vildanov * fix deprecated call * fix key name * fix wrong command * Added support for container commands (#1049) * Added support for container commands FUNCTION LOAD, FUNCTION DELETE and FCALL * Changed ContainerInterface and AbstractContainer * Re-implement logic of abstract methods --------- Co-authored-by: Vladyslav Vildanov * Added stream commands to KeyPrefixProcessor (#1051) Co-authored-by: Vladyslav Vildanov * Pulling changes * Fix return type of ReplicationInterface::getSlaves (#1111) * Added support for FT.CREATE command * Fixed tests to choose correct DB * Added test coverage * Revert changes for missing commands * Added data types enums, added methods default assignments * Fixed vector field, removed default assignments, fixed tests * Added constants enum for Sortable argument, renamed arguments object * Codestyle fixes * Rename test class * Codestyle fixes * Changed return annotation * Separate common and create interfaces * Codestyle fixes * Added support for FT.CONFIG SET, FT.CONFIG GET commands * Revert changes * Added support for FT.CONFIG HELP command * Revert interface changes for bitcount command --------- Co-authored-by: shacharPash Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss Co-authored-by: Stephan * Extended Json support by implementing JSON.DEBUG command (#1182) * Added support for new arguments for BITPOS, BITCOUNT commands (#1045) * Added support for new arguments for EXPIRE, EXPIREAT commands (#1046) * Extended core support by implementing SORT_RO command (#1044) * Added support for SORT_RO command * Codestyle fixes * Added command description --------- Co-authored-by: Vladyslav Vildanov * fix deprecated call * Added support for container commands (#1049) * Added support for container commands FUNCTION LOAD, FUNCTION DELETE and FCALL * Changed ContainerInterface and AbstractContainer * Re-implement logic of abstract methods --------- Co-authored-by: Vladyslav Vildanov * Added stream commands to KeyPrefixProcessor (#1051) Co-authored-by: Vladyslav Vildanov * Fix return type of ReplicationInterface::getSlaves (#1111) * Codestyle fixes * Changed return annotation * Added support for JSON.DEBUG command * Codestyle fixes --------- Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss Co-authored-by: Stephan * Extended RediSearch support by implementing FT.SUGDEL command (#1183) * Added support for new arguments for BITPOS, BITCOUNT commands (#1045) * Added support for new arguments for EXPIRE, EXPIREAT commands (#1046) * Extended core support by implementing SORT_RO command (#1044) * Added support for SORT_RO command * Codestyle fixes * Added command description --------- Co-authored-by: Vladyslav Vildanov * fix deprecated call * Added support for container commands (#1049) * Added support for container commands FUNCTION LOAD, FUNCTION DELETE and FCALL * Changed ContainerInterface and AbstractContainer * Re-implement logic of abstract methods --------- Co-authored-by: Vladyslav Vildanov * Added stream commands to KeyPrefixProcessor (#1051) Co-authored-by: Vladyslav Vildanov * Fix return type of ReplicationInterface::getSlaves (#1111) * Codestyle fixes * Changed return annotation * Added support for FT.SUGDEL command --------- Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss Co-authored-by: Stephan * Extended RediSearch support by implementing FT.SUGGET command (#1185) * Added support for new arguments for BITPOS, BITCOUNT commands (#1045) * Added support for new arguments for EXPIRE, EXPIREAT commands (#1046) * Extended core support by implementing SORT_RO command (#1044) * Added support for SORT_RO command * Codestyle fixes * Added command description --------- Co-authored-by: Vladyslav Vildanov * fix deprecated call * Added support for container commands (#1049) * Added support for container commands FUNCTION LOAD, FUNCTION DELETE and FCALL * Changed ContainerInterface and AbstractContainer * Re-implement logic of abstract methods --------- Co-authored-by: Vladyslav Vildanov * Added stream commands to KeyPrefixProcessor (#1051) Co-authored-by: Vladyslav Vildanov * Fix return type of ReplicationInterface::getSlaves (#1111) * Codestyle fixes * Changed return annotation * Added support for FT.SUGGET command, added examples for suggestion API usage * Include SUGGET command files to codespell ignore * Added file extension --------- Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss Co-authored-by: Stephan * Extended RediSearch support by implementing FT.SUGLEN command (#1186) * Added support for new arguments for BITPOS, BITCOUNT commands (#1045) * Added support for new arguments for EXPIRE, EXPIREAT commands (#1046) * Extended core support by implementing SORT_RO command (#1044) * Added support for SORT_RO command * Codestyle fixes * Added command description --------- Co-authored-by: Vladyslav Vildanov * fix deprecated call * Added support for container commands (#1049) * Added support for container commands FUNCTION LOAD, FUNCTION DELETE and FCALL * Changed ContainerInterface and AbstractContainer * Re-implement logic of abstract methods --------- Co-authored-by: Vladyslav Vildanov * Added stream commands to KeyPrefixProcessor (#1051) Co-authored-by: Vladyslav Vildanov * Fix return type of ReplicationInterface::getSlaves (#1111) * Codestyle fixes * Changed return annotation * Added support for FT.SUGLEN command --------- Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss Co-authored-by: Stephan * Unbreak RedisFactory interface (#1190) * Added support for new arguments for BITPOS, BITCOUNT commands (#1045) * Added support for new arguments for EXPIRE, EXPIREAT commands (#1046) * Extended core support by implementing SORT_RO command (#1044) * Added support for SORT_RO command * Codestyle fixes * Added command description --------- Co-authored-by: Vladyslav Vildanov * fix deprecated call * Added support for container commands (#1049) * Added support for container commands FUNCTION LOAD, FUNCTION DELETE and FCALL * Changed ContainerInterface and AbstractContainer * Re-implement logic of abstract methods --------- Co-authored-by: Vladyslav Vildanov * Added stream commands to KeyPrefixProcessor (#1051) Co-authored-by: Vladyslav Vildanov * Fix return type of ReplicationInterface::getSlaves (#1111) * Codestyle fixes * Changed return annotation * Unbreak RedisFactory interface * Fixed tests to be more generic and less dependant on json module --------- Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss Co-authored-by: Stephan * Low-level implementation for FT.CREATE command (#1187) * Added support for new arguments for BITPOS, BITCOUNT commands (#1045) * Added support for new arguments for EXPIRE, EXPIREAT commands (#1046) * Extended core support by implementing SORT_RO command (#1044) * Added support for SORT_RO command * Codestyle fixes * Added command description --------- Co-authored-by: Vladyslav Vildanov * fix deprecated call * Added support for container commands (#1049) * Added support for container commands FUNCTION LOAD, FUNCTION DELETE and FCALL * Changed ContainerInterface and AbstractContainer * Re-implement logic of abstract methods --------- Co-authored-by: Vladyslav Vildanov * Added stream commands to KeyPrefixProcessor (#1051) Co-authored-by: Vladyslav Vildanov * Fix return type of ReplicationInterface::getSlaves (#1111) * Codestyle fixes * Changed return annotation * Implemented low-level solution with builder under the hood * Renamed variable * Codestyle fixes * New Schema implementation * Removed deprecated payload_field argument * Changed command argument name to more meaningful * Added arguments default values according to documentation * Changed letter to capital * Changed arguments inteface, using builder directly * Removed unused interface * Fix misspelling error * Fixed tests, remove old Schema object * Removed SchemaTest * Removed broken references --------- Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss Co-authored-by: Stephan Co-authored-by: Chayim * Extended RediSearch support by implementing FT.AGGREGATE command (#1176) * Added support for new arguments for BITPOS, BITCOUNT commands (#1045) * Added support for new arguments for EXPIRE, EXPIREAT commands (#1046) * Extended core support by implementing SORT_RO command (#1044) * Added support for SORT_RO command * Codestyle fixes * Added command description --------- Co-authored-by: Vladyslav Vildanov * fix deprecated call * Added support for container commands (#1049) * Added support for container commands FUNCTION LOAD, FUNCTION DELETE and FCALL * Changed ContainerInterface and AbstractContainer * Re-implement logic of abstract methods --------- Co-authored-by: Vladyslav Vildanov * Added stream commands to KeyPrefixProcessor (#1051) Co-authored-by: Vladyslav Vildanov * Fix return type of ReplicationInterface::getSlaves (#1111) * Codestyle fixes * Changed return annotation * Added support for FT.AGGREGATE command * Added command usage example --------- Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss Co-authored-by: Stephan * Extended RediSearch support by implementing FT.EXPLAIN command (#1159) * add support for CF.ADDNX * fix key name * fix wrong command * Pulling changes * Added support for FT.CREATE command * Fixed tests to choose correct DB * Added test coverage * Revert changes for missing commands * Added data types enums, added methods default assignments * Added support for search command arguments, implemented FT.SEARCH command * Fixed vector field, removed default assignments, fixed tests * Tests fixes * Added constants enum for Sortable argument, renamed arguments object * Codestyle fixes * Rename test class * Merge conflicts * Added support for FT.EXPLAIN command * Added FTEXPLAIN_Test to ignored file for eclint * Codestyle fixes * Fixed tests, added separate .editorconfig file --------- Co-authored-by: shacharPash Co-authored-by: Vladyslav Vildanov * Extended TimeSeries support by implementing TS.CREATE command (#1197) * Added support for new arguments for BITPOS, BITCOUNT commands (#1045) * Added support for new arguments for EXPIRE, EXPIREAT commands (#1046) * Extended core support by implementing SORT_RO command (#1044) * Added support for SORT_RO command * Codestyle fixes * Added command description --------- Co-authored-by: Vladyslav Vildanov * fix deprecated call * Added support for container commands (#1049) * Added support for container commands FUNCTION LOAD, FUNCTION DELETE and FCALL * Changed ContainerInterface and AbstractContainer * Re-implement logic of abstract methods --------- Co-authored-by: Vladyslav Vildanov * Added stream commands to KeyPrefixProcessor (#1051) Co-authored-by: Vladyslav Vildanov * Fix return type of ReplicationInterface::getSlaves (#1111) * Codestyle fixes * Changed return annotation * Added support for Time Series commands, TSCREATE command * Fixed param annotation --------- Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss Co-authored-by: Stephan * Extended TimeSeries support by implementing TS.ADD command (#1198) * Added support for new arguments for BITPOS, BITCOUNT commands (#1045) * Added support for new arguments for EXPIRE, EXPIREAT commands (#1046) * Extended core support by implementing SORT_RO command (#1044) * Added support for SORT_RO command * Codestyle fixes * Added command description --------- Co-authored-by: Vladyslav Vildanov * fix deprecated call * Added support for container commands (#1049) * Added support for container commands FUNCTION LOAD, FUNCTION DELETE and FCALL * Changed ContainerInterface and AbstractContainer * Re-implement logic of abstract methods --------- Co-authored-by: Vladyslav Vildanov * Added stream commands to KeyPrefixProcessor (#1051) Co-authored-by: Vladyslav Vildanov * Fix return type of ReplicationInterface::getSlaves (#1111) * Codestyle fixes * Changed return annotation * Added support for Time Series commands, TSCREATE command * Fixed param annotation * Added support for TS.ADD command --------- Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss Co-authored-by: Stephan * assert resource type before calling fclose on it (#1199) * Extended TimeSeries support by implementing TS.GET command (#1218) * Added support for new arguments for BITPOS, BITCOUNT commands (#1045) * Added support for new arguments for EXPIRE, EXPIREAT commands (#1046) * Extended core support by implementing SORT_RO command (#1044) * Added support for SORT_RO command * Codestyle fixes * Added command description --------- Co-authored-by: Vladyslav Vildanov * fix deprecated call * Added support for container commands (#1049) * Added support for container commands FUNCTION LOAD, FUNCTION DELETE and FCALL * Changed ContainerInterface and AbstractContainer * Re-implement logic of abstract methods --------- Co-authored-by: Vladyslav Vildanov * Added stream commands to KeyPrefixProcessor (#1051) Co-authored-by: Vladyslav Vildanov * Fix return type of ReplicationInterface::getSlaves (#1111) * Codestyle fixes * Changed return annotation * Added support for TS.GET command * Codestyle fixes --------- Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss Co-authored-by: Stephan * Extended TimeSeries support by implementing TS.DEL command (#1219) * Added support for new arguments for BITPOS, BITCOUNT commands (#1045) * Added support for new arguments for EXPIRE, EXPIREAT commands (#1046) * Extended core support by implementing SORT_RO command (#1044) * Added support for SORT_RO command * Codestyle fixes * Added command description --------- Co-authored-by: Vladyslav Vildanov * fix deprecated call * Added support for container commands (#1049) * Added support for container commands FUNCTION LOAD, FUNCTION DELETE and FCALL * Changed ContainerInterface and AbstractContainer * Re-implement logic of abstract methods --------- Co-authored-by: Vladyslav Vildanov * Added stream commands to KeyPrefixProcessor (#1051) Co-authored-by: Vladyslav Vildanov * Fix return type of ReplicationInterface::getSlaves (#1111) * Codestyle fixes * Changed return annotation * Added support for TS.GET command * Codestyle fixes * Added support for TS.DEL command --------- Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss Co-authored-by: Stephan * Extended TimeSeries support by implementing TS.ALTER command (#1220) * Added support for new arguments for BITPOS, BITCOUNT commands (#1045) * Added support for new arguments for EXPIRE, EXPIREAT commands (#1046) * Extended core support by implementing SORT_RO command (#1044) * Added support for SORT_RO command * Codestyle fixes * Added command description --------- Co-authored-by: Vladyslav Vildanov * fix deprecated call * Added support for container commands (#1049) * Added support for container commands FUNCTION LOAD, FUNCTION DELETE and FCALL * Changed ContainerInterface and AbstractContainer * Re-implement logic of abstract methods --------- Co-authored-by: Vladyslav Vildanov * Added stream commands to KeyPrefixProcessor (#1051) Co-authored-by: Vladyslav Vildanov * Fix return type of ReplicationInterface::getSlaves (#1111) * Codestyle fixes * Changed return annotation * Added support for TS.ALTER command --------- Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss Co-authored-by: Stephan * Extended TimeSeries support by implementing TS.INCRBY command (#1222) * Added support for new arguments for BITPOS, BITCOUNT commands (#1045) * Added support for new arguments for EXPIRE, EXPIREAT commands (#1046) * Extended core support by implementing SORT_RO command (#1044) * Added support for SORT_RO command * Codestyle fixes * Added command description --------- Co-authored-by: Vladyslav Vildanov * fix deprecated call * Added support for container commands (#1049) * Added support for container commands FUNCTION LOAD, FUNCTION DELETE and FCALL * Changed ContainerInterface and AbstractContainer * Re-implement logic of abstract methods --------- Co-authored-by: Vladyslav Vildanov * Added stream commands to KeyPrefixProcessor (#1051) Co-authored-by: Vladyslav Vildanov * Fix return type of ReplicationInterface::getSlaves (#1111) * Codestyle fixes * Changed return annotation * Added support for TS.INCRBY commands * Fixed return type * Removed part of string to avoid spelling CI breaking --------- Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss Co-authored-by: Stephan * Extended TimeSeries support by implementing TS.DECRBY command (#1223) * Added support for new arguments for BITPOS, BITCOUNT commands (#1045) * Added support for new arguments for EXPIRE, EXPIREAT commands (#1046) * Extended core support by implementing SORT_RO command (#1044) * Added support for SORT_RO command * Codestyle fixes * Added command description --------- Co-authored-by: Vladyslav Vildanov * fix deprecated call * Added support for container commands (#1049) * Added support for container commands FUNCTION LOAD, FUNCTION DELETE and FCALL * Changed ContainerInterface and AbstractContainer * Re-implement logic of abstract methods --------- Co-authored-by: Vladyslav Vildanov * Added stream commands to KeyPrefixProcessor (#1051) Co-authored-by: Vladyslav Vildanov * Fix return type of ReplicationInterface::getSlaves (#1111) * Codestyle fixes * Changed return annotation * Added support for TS.DECRBY command --------- Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss Co-authored-by: Stephan * Extended TimeSeries support by implementing TS.MADD command (#1224) * Added support for new arguments for BITPOS, BITCOUNT commands (#1045) * Added support for new arguments for EXPIRE, EXPIREAT commands (#1046) * Extended core support by implementing SORT_RO command (#1044) * Added support for SORT_RO command * Codestyle fixes * Added command description --------- Co-authored-by: Vladyslav Vildanov * fix deprecated call * Added support for container commands (#1049) * Added support for container commands FUNCTION LOAD, FUNCTION DELETE and FCALL * Changed ContainerInterface and AbstractContainer * Re-implement logic of abstract methods --------- Co-authored-by: Vladyslav Vildanov * Added stream commands to KeyPrefixProcessor (#1051) Co-authored-by: Vladyslav Vildanov * Fix return type of ReplicationInterface::getSlaves (#1111) * Codestyle fixes * Changed return annotation * Added support for TS.MADD command * Fixed exception message --------- Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss Co-authored-by: Stephan * Extended TimeSeries support by implementing TS.MGET command (#1225) * Added support for new arguments for BITPOS, BITCOUNT commands (#1045) * Added support for new arguments for EXPIRE, EXPIREAT commands (#1046) * Extended core support by implementing SORT_RO command (#1044) * Added support for SORT_RO command * Codestyle fixes * Added command description --------- Co-authored-by: Vladyslav Vildanov * fix deprecated call * Added support for container commands (#1049) * Added support for container commands FUNCTION LOAD, FUNCTION DELETE and FCALL * Changed ContainerInterface and AbstractContainer * Re-implement logic of abstract methods --------- Co-authored-by: Vladyslav Vildanov * Added stream commands to KeyPrefixProcessor (#1051) Co-authored-by: Vladyslav Vildanov * Fix return type of ReplicationInterface::getSlaves (#1111) * Codestyle fixes * Changed return annotation * Added support for TS.MGET command --------- Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss Co-authored-by: Stephan * Added alias option for Vector field (#1221) * Added support for new arguments for BITPOS, BITCOUNT commands (#1045) * Added support for new arguments for EXPIRE, EXPIREAT commands (#1046) * Extended core support by implementing SORT_RO command (#1044) * Added support for SORT_RO command * Codestyle fixes * Added command description --------- Co-authored-by: Vladyslav Vildanov * fix deprecated call * Added support for container commands (#1049) * Added support for container commands FUNCTION LOAD, FUNCTION DELETE and FCALL * Changed ContainerInterface and AbstractContainer * Re-implement logic of abstract methods --------- Co-authored-by: Vladyslav Vildanov * Added stream commands to KeyPrefixProcessor (#1051) Co-authored-by: Vladyslav Vildanov * Fix return type of ReplicationInterface::getSlaves (#1111) * Codestyle fixes * Changed return annotation * Added alias option for Vector field --------- Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss Co-authored-by: Stephan * Extended TimeSeries support by implementing TS.INFO command (#1228) * Added support for new arguments for BITPOS, BITCOUNT commands (#1045) * Added support for new arguments for EXPIRE, EXPIREAT commands (#1046) * Extended core support by implementing SORT_RO command (#1044) * Added support for SORT_RO command * Codestyle fixes * Added command description --------- Co-authored-by: Vladyslav Vildanov * fix deprecated call * Added support for container commands (#1049) * Added support for container commands FUNCTION LOAD, FUNCTION DELETE and FCALL * Changed ContainerInterface and AbstractContainer * Re-implement logic of abstract methods --------- Co-authored-by: Vladyslav Vildanov * Added stream commands to KeyPrefixProcessor (#1051) Co-authored-by: Vladyslav Vildanov * Fix return type of ReplicationInterface::getSlaves (#1111) * Codestyle fixes * Changed return annotation * Added support for TS.INFO command * Rename method to be more consistent --------- Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss Co-authored-by: Stephan * Extended TimeSeries support by implementing TS.QUERYINDEX command (#1229) * Added support for new arguments for BITPOS, BITCOUNT commands (#1045) * Added support for new arguments for EXPIRE, EXPIREAT commands (#1046) * Extended core support by implementing SORT_RO command (#1044) * Added support for SORT_RO command * Codestyle fixes * Added command description --------- Co-authored-by: Vladyslav Vildanov * fix deprecated call * Added support for container commands (#1049) * Added support for container commands FUNCTION LOAD, FUNCTION DELETE and FCALL * Changed ContainerInterface and AbstractContainer * Re-implement logic of abstract methods --------- Co-authored-by: Vladyslav Vildanov * Added stream commands to KeyPrefixProcessor (#1051) Co-authored-by: Vladyslav Vildanov * Fix return type of ReplicationInterface::getSlaves (#1111) * Codestyle fixes * Changed return annotation * Added support for TS.QUERYINDEX command --------- Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss Co-authored-by: Stephan * Extended TimeSeries by implementing TS.RANGE command (#1231) * Added support for new arguments for BITPOS, BITCOUNT commands (#1045) * Added support for new arguments for EXPIRE, EXPIREAT commands (#1046) * Extended core support by implementing SORT_RO command (#1044) * Added support for SORT_RO command * Codestyle fixes * Added command description --------- Co-authored-by: Vladyslav Vildanov * fix deprecated call * Added support for container commands (#1049) * Added support for container commands FUNCTION LOAD, FUNCTION DELETE and FCALL * Changed ContainerInterface and AbstractContainer * Re-implement logic of abstract methods --------- Co-authored-by: Vladyslav Vildanov * Added stream commands to KeyPrefixProcessor (#1051) Co-authored-by: Vladyslav Vildanov * Fix return type of ReplicationInterface::getSlaves (#1111) * Codestyle fixes * Changed return annotation * Added support for TS.RANGE command --------- Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss Co-authored-by: Stephan * Extended TimeSeries by implementing TS.REVRANGE command (#1232) * Added support for new arguments for BITPOS, BITCOUNT commands (#1045) * Added support for new arguments for EXPIRE, EXPIREAT commands (#1046) * Extended core support by implementing SORT_RO command (#1044) * Added support for SORT_RO command * Codestyle fixes * Added command description --------- Co-authored-by: Vladyslav Vildanov * fix deprecated call * Added support for container commands (#1049) * Added support for container commands FUNCTION LOAD, FUNCTION DELETE and FCALL * Changed ContainerInterface and AbstractContainer * Re-implement logic of abstract methods --------- Co-authored-by: Vladyslav Vildanov * Added stream commands to KeyPrefixProcessor (#1051) Co-authored-by: Vladyslav Vildanov * Fix return type of ReplicationInterface::getSlaves (#1111) * Codestyle fixes * Changed return annotation * Added support for TS.RANGE command * Added support for TS.REVRANGE command --------- Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss Co-authored-by: Stephan * Extended RediSearch support by implementing TS.CREATERULE command (#1226) * Added support for new arguments for BITPOS, BITCOUNT commands (#1045) * Added support for new arguments for EXPIRE, EXPIREAT commands (#1046) * Extended core support by implementing SORT_RO command (#1044) * Added support for SORT_RO command * Codestyle fixes * Added command description --------- Co-authored-by: Vladyslav Vildanov * fix deprecated call * Added support for container commands (#1049) * Added support for container commands FUNCTION LOAD, FUNCTION DELETE and FCALL * Changed ContainerInterface and AbstractContainer * Re-implement logic of abstract methods --------- Co-authored-by: Vladyslav Vildanov * Added stream commands to KeyPrefixProcessor (#1051) Co-authored-by: Vladyslav Vildanov * Fix return type of ReplicationInterface::getSlaves (#1111) * Codestyle fixes * Changed return annotation * Added support for TS.CREATERULE command --------- Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss Co-authored-by: Stephan * Extended TimeSeries support by implementing TS.DELETERULE command (#1227) * Added support for new arguments for BITPOS, BITCOUNT commands (#1045) * Added support for new arguments for EXPIRE, EXPIREAT commands (#1046) * Extended core support by implementing SORT_RO command (#1044) * Added support for SORT_RO command * Codestyle fixes * Added command description --------- Co-authored-by: Vladyslav Vildanov * fix deprecated call * Added support for container commands (#1049) * Added support for container commands FUNCTION LOAD, FUNCTION DELETE and FCALL * Changed ContainerInterface and AbstractContainer * Re-implement logic of abstract methods --------- Co-authored-by: Vladyslav Vildanov * Added stream commands to KeyPrefixProcessor (#1051) Co-authored-by: Vladyslav Vildanov * Fix return type of ReplicationInterface::getSlaves (#1111) * Codestyle fixes * Changed return annotation * Added support for TS.CREATERULE command * Added support for TS.DELETERULE command --------- Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss Co-authored-by: Stephan * Extended TimeSeries support by implementing TS.MRANGE command (#1233) * Added support for new arguments for BITPOS, BITCOUNT commands (#1045) * Added support for new arguments for EXPIRE, EXPIREAT commands (#1046) * Extended core support by implementing SORT_RO command (#1044) * Added support for SORT_RO command * Codestyle fixes * Added command description --------- Co-authored-by: Vladyslav Vildanov * fix deprecated call * Added support for container commands (#1049) * Added support for container commands FUNCTION LOAD, FUNCTION DELETE and FCALL * Changed ContainerInterface and AbstractContainer * Re-implement logic of abstract methods --------- Co-authored-by: Vladyslav Vildanov * Added stream commands to KeyPrefixProcessor (#1051) Co-authored-by: Vladyslav Vildanov * Fix return type of ReplicationInterface::getSlaves (#1111) * Codestyle fixes * Changed return annotation * Added support for TS.MRANGE command --------- Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss Co-authored-by: Stephan * Extended TimeSeries support by implementing TS.MREVRANGE command (#1234) * Added support for new arguments for BITPOS, BITCOUNT commands (#1045) * Added support for new arguments for EXPIRE, EXPIREAT commands (#1046) * Extended core support by implementing SORT_RO command (#1044) * Added support for SORT_RO command * Codestyle fixes * Added command description --------- Co-authored-by: Vladyslav Vildanov * fix deprecated call * Added support for container commands (#1049) * Added support for container commands FUNCTION LOAD, FUNCTION DELETE and FCALL * Changed ContainerInterface and AbstractContainer * Re-implement logic of abstract methods --------- Co-authored-by: Vladyslav Vildanov * Added stream commands to KeyPrefixProcessor (#1051) Co-authored-by: Vladyslav Vildanov * Fix return type of ReplicationInterface::getSlaves (#1111) * Codestyle fixes * Changed return annotation * Added support for TS.MRANGE command * Added support for TS.MREVRANGE command --------- Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss Co-authored-by: Stephan * Extended RediSearch support by implementing FT.CURSOR READ, DEL commands (#1196) * Added support for new arguments for BITPOS, BITCOUNT commands (#1045) * Added support for new arguments for EXPIRE, EXPIREAT commands (#1046) * Extended core support by implementing SORT_RO command (#1044) * Added support for SORT_RO command * Codestyle fixes * Added command description --------- Co-authored-by: Vladyslav Vildanov * fix deprecated call * Added support for container commands (#1049) * Added support for container commands FUNCTION LOAD, FUNCTION DELETE and FCALL * Changed ContainerInterface and AbstractContainer * Re-implement logic of abstract methods --------- Co-authored-by: Vladyslav Vildanov * Added stream commands to KeyPrefixProcessor (#1051) Co-authored-by: Vladyslav Vildanov * Fix return type of ReplicationInterface::getSlaves (#1111) * Codestyle fixes * Changed return annotation * Added support for FT.CURSOR READ, DEL commands --------- Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss Co-authored-by: Stephan * Codestyle fix * Changed idx name for different index types * Resolve merge conflicts between v2.x and main (#1247) * Added support for new arguments for BITPOS, BITCOUNT commands (#1045) * Added support for new arguments for EXPIRE, EXPIREAT commands (#1046) * Extended core support by implementing SORT_RO command (#1044) * Added support for SORT_RO command * Codestyle fixes * Added command description --------- Co-authored-by: Vladyslav Vildanov * fix deprecated call * Added support for container commands (#1049) * Added support for container commands FUNCTION LOAD, FUNCTION DELETE and FCALL * Changed ContainerInterface and AbstractContainer * Re-implement logic of abstract methods --------- Co-authored-by: Vladyslav Vildanov * Added stream commands to KeyPrefixProcessor (#1051) Co-authored-by: Vladyslav Vildanov * Fix return type of ReplicationInterface::getSlaves (#1111) * Codestyle fixes * Changed return annotation * Add option for disabling reads to slaves in replication topologies (#1168) * Add option for disabling reads to slaves in replication topologies (cherry picked from commit e132c312a97a9b071e5b206277070b0b5fa0fb9b) * remove empty line --------- Co-authored-by: Till Krüss * match `MasterSlaveReplication` (#1175) * match `MasterSlaveReplication` also the name of this method 😬 * Update SentinelReplication.php * Added CODEOWNERS file (#1181) * Added CODEOWNERS file * Update CODEOWNERS * Applied whole Redis commands path as @vladvildanov codeowner * Set @predis/team as Redis commands codeowners * Update CODEOWNERS --------- Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss * Deprecate webdis and phpiredis (#1179) * Deprecate webdis and phpiredis * remove space * tag v2.1.2 * Extended core support by implementing FCALL_RO command (#1191) * typo * Extended core support by implementing ACL SETUSER, GETUSER, DRYRUN (#1193) * Added support for ACL GETUSER, SETUSER, DRYRUN commands * Change test to support Redis > 6.0.0 * Removed selectors check * Add missing stream key prefixes (#1230) * Added missing stream key prefixes * Tested stream command key prefixing * Codestyle fix * Changed idx name for different index types --------- Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss Co-authored-by: Stephan Co-authored-by: David Bomba Co-authored-by: Till Krüss Co-authored-by: Jess Archer * Resolve merge conflicts * Revert changes * Codestyle fixes * Codestyle changes related to php-cs-fixer update (#1311) * Codestyle changes * Added missing type-hints * Added GETDEL command to KeyPrefixProcessor (#1306) * Added GETDEL command to KeyPrefixProcessor * Added test coverage * Codestyle fixes * Added timeout after FT.CREATE call * Codestyle changes * Added support for JSON.MERGE command (#1304) * Added support for JSON.MSET command (#1307) * Fixed subcommand test bug (#1313) * Removed old implementation * Added types, removed redundant codespell configuration --------- Co-authored-by: Vladyslav Vildanov Co-authored-by: Till Krüss Co-authored-by: shacharPash <93581407+shacharPash@users.noreply.github.com> Co-authored-by: Till Krüss Co-authored-by: Stephan Co-authored-by: shacharPash Co-authored-by: Chayim Co-authored-by: Patrick Jahn <33724206+p-jahn@users.noreply.github.com> Co-authored-by: David Bomba Co-authored-by: Jess Archer --- src/Client.php | 18 +-- src/ClientContextInterface.php | 2 + src/ClientInterface.php | 2 + src/Command/{Redis => }/Container/ACL.php | 2 +- .../Container/AbstractContainer.php | 2 +- .../Container/ContainerFactory.php | 6 +- .../Container/ContainerInterface.php | 8 +- .../FUNCTIONS.php} | 4 +- .../{Redis => }/Container/Json/JSONDEBUG.php | 4 +- .../{Redis => }/Container/Search/FTCONFIG.php | 4 +- .../{Redis => }/Container/Search/FTCURSOR.php | 4 +- src/Command/Redis/Json/JSONMERGE.php | 29 +++++ src/Command/Redis/Json/JSONMSET.php | 28 +++++ src/Command/Redis/SORT.php | 6 +- src/Command/Traits/Keys.php | 4 +- src/Configuration/Options.php | 8 +- src/Connection/RelayMethods.php | 4 +- src/PubSub/AbstractConsumer.php | 2 +- tests/PHPUnit/OneOfConstraint.php | 2 +- tests/PHPUnit/PredisTestCase.php | 19 ++-- tests/PHPUnit/RedisCommandConstraint.php | 2 +- tests/Predis/Cluster/PredisStrategyTest.php | 2 +- tests/Predis/Cluster/RedisStrategyTest.php | 2 +- .../Container/AbstractContainerTest.php | 2 +- .../Container/ContainerFactoryTest.php | 6 +- .../Predis/Command/Redis/EVALSHA_RO_Test.php | 8 +- tests/Predis/Command/Redis/EVAL_RO_Test.php | 10 +- tests/Predis/Command/Redis/EXPIREAT_Test.php | 8 +- tests/Predis/Command/Redis/FCALL_RO_Test.php | 4 +- tests/Predis/Command/Redis/FCALL_Test.php | 6 +- .../Command/Redis/Json/JSONMERGE_Test.php | 103 ++++++++++++++++++ .../Command/Redis/Json/JSONMSET_Test.php | 85 +++++++++++++++ tests/Predis/Command/Redis/LCS_Test.php | 6 +- .../Command/Redis/Search/FTSEARCH_Test.php | 3 + .../Predis/Command/Redis/ZINTERCARD_Test.php | 4 +- .../Predis/Command/Redis/ZINTERSTORE_Test.php | 6 +- tests/Predis/Command/Redis/ZINTER_Test.php | 4 +- .../Predis/Command/Redis/ZRANGESTORE_Test.php | 16 +-- .../Predis/Command/Redis/ZUNIONSTORE_Test.php | 6 +- tests/Predis/Command/Redis/ZUNION_Test.php | 4 +- .../Replication/ReplicationStrategyTest.php | 2 +- 41 files changed, 349 insertions(+), 98 deletions(-) rename src/Command/{Redis => }/Container/ACL.php (93%) rename src/Command/{Redis => }/Container/AbstractContainer.php (95%) rename src/Command/{Redis => }/Container/ContainerFactory.php (93%) rename src/Command/{Redis => }/Container/ContainerInterface.php (78%) rename src/Command/{Redis/Container/FunctionContainer.php => Container/FUNCTIONS.php} (84%) rename src/Command/{Redis => }/Container/Json/JSONDEBUG.php (82%) rename src/Command/{Redis => }/Container/Search/FTCONFIG.php (84%) rename src/Command/{Redis => }/Container/Search/FTCURSOR.php (85%) create mode 100644 src/Command/Redis/Json/JSONMERGE.php create mode 100644 src/Command/Redis/Json/JSONMSET.php rename tests/Predis/Command/{Redis => }/Container/AbstractContainerTest.php (98%) rename tests/Predis/Command/{Redis => }/Container/ContainerFactoryTest.php (93%) create mode 100644 tests/Predis/Command/Redis/Json/JSONMERGE_Test.php create mode 100644 tests/Predis/Command/Redis/Json/JSONMSET_Test.php diff --git a/src/Client.php b/src/Client.php index 1636cc6f..32b9b708 100644 --- a/src/Client.php +++ b/src/Client.php @@ -16,9 +16,9 @@ use ArrayIterator; use InvalidArgumentException; use IteratorAggregate; use Predis\Command\CommandInterface; +use Predis\Command\Container\ContainerFactory; +use Predis\Command\Container\ContainerInterface; use Predis\Command\RawCommand; -use Predis\Command\Redis\Container\ContainerFactory; -use Predis\Command\Redis\Container\ContainerInterface; use Predis\Command\ScriptCommand; use Predis\Configuration\Options; use Predis\Configuration\OptionsInterface; @@ -346,29 +346,29 @@ class Client implements ClientInterface, IteratorAggregate } /** - * @param $name + * @param string $name * @return ContainerInterface */ - public function __get($name) + public function __get(string $name) { return ContainerFactory::create($this, $name); } /** - * @param $name - * @param $value + * @param string $name + * @param mixed $value * @return mixed */ - public function __set($name, $value) + public function __set(string $name, $value) { throw new RuntimeException('Not allowed'); } /** - * @param $name + * @param string $name * @return mixed */ - public function __isset($name) + public function __isset(string $name) { throw new RuntimeException('Not allowed'); } diff --git a/src/ClientContextInterface.php b/src/ClientContextInterface.php index 0de20a32..95f1590e 100644 --- a/src/ClientContextInterface.php +++ b/src/ClientContextInterface.php @@ -178,7 +178,9 @@ use Predis\Command\Redis\Container\Search\FTCURSOR; * @method $this jsonforget(string $key, string $path = '$') * @method $this jsonget(string $key, string $indent = '', string $newline = '', string $space = '', string ...$paths) * @method $this jsonnumincrby(string $key, string $path, int $value) + * @method $this jsonmerge(string $key, string $path, string $value) * @method $this jsonmget(array $keys, string $path) + * @method $this jsonmset(string ...$keyPathValue) * @method $this jsonobjkeys(string $key, string $path = '$') * @method $this jsonobjlen(string $key, string $path = '$') * @method $this jsonresp(string $key, string $path = '$') diff --git a/src/ClientInterface.php b/src/ClientInterface.php index e46209df..924db1ec 100644 --- a/src/ClientInterface.php +++ b/src/ClientInterface.php @@ -187,7 +187,9 @@ use Predis\Response\Status; * @method int jsonforget(string $key, string $path = '$') * @method string jsonget(string $key, string $indent = '', string $newline = '', string $space = '', string ...$paths) * @method string jsonnumincrby(string $key, string $path, int $value) + * @method Status jsonmerge(string $key, string $path, string $value) * @method array jsonmget(array $keys, string $path) + * @method Status jsonmset(string ...$keyPathValue) * @method array jsonobjkeys(string $key, string $path = '$') * @method array jsonobjlen(string $key, string $path = '$') * @method array jsonresp(string $key, string $path = '$') diff --git a/src/Command/Redis/Container/ACL.php b/src/Command/Container/ACL.php similarity index 93% rename from src/Command/Redis/Container/ACL.php rename to src/Command/Container/ACL.php index 2699d37e..25f86cc3 100644 --- a/src/Command/Redis/Container/ACL.php +++ b/src/Command/Container/ACL.php @@ -10,7 +10,7 @@ * file that was distributed with this source code. */ -namespace Predis\Command\Redis\Container; +namespace Predis\Command\Container; use Predis\Response\Status; diff --git a/src/Command/Redis/Container/AbstractContainer.php b/src/Command/Container/AbstractContainer.php similarity index 95% rename from src/Command/Redis/Container/AbstractContainer.php rename to src/Command/Container/AbstractContainer.php index 6ba86d0f..950346ba 100644 --- a/src/Command/Redis/Container/AbstractContainer.php +++ b/src/Command/Container/AbstractContainer.php @@ -10,7 +10,7 @@ * file that was distributed with this source code. */ -namespace Predis\Command\Redis\Container; +namespace Predis\Command\Container; use Predis\ClientInterface; diff --git a/src/Command/Redis/Container/ContainerFactory.php b/src/Command/Container/ContainerFactory.php similarity index 93% rename from src/Command/Redis/Container/ContainerFactory.php rename to src/Command/Container/ContainerFactory.php index 79d3de09..68f39a33 100644 --- a/src/Command/Redis/Container/ContainerFactory.php +++ b/src/Command/Container/ContainerFactory.php @@ -10,7 +10,7 @@ * file that was distributed with this source code. */ -namespace Predis\Command\Redis\Container; +namespace Predis\Command\Container; use Predis\ClientConfiguration; use Predis\ClientInterface; @@ -18,7 +18,7 @@ use UnexpectedValueException; class ContainerFactory { - private const CONTAINER_NAMESPACE = "Predis\Command\Redis\Container"; + private const CONTAINER_NAMESPACE = "Predis\Command\Container"; /** * Mappings for class names that corresponds to PHP reserved words. @@ -26,7 +26,7 @@ class ContainerFactory * @var array */ private static $specialMappings = [ - 'FUNCTION' => FunctionContainer::class, + 'FUNCTION' => FUNCTIONS::class, ]; /** diff --git a/src/Command/Redis/Container/ContainerInterface.php b/src/Command/Container/ContainerInterface.php similarity index 78% rename from src/Command/Redis/Container/ContainerInterface.php rename to src/Command/Container/ContainerInterface.php index ce3989b5..b4e1b0e6 100644 --- a/src/Command/Redis/Container/ContainerInterface.php +++ b/src/Command/Container/ContainerInterface.php @@ -10,7 +10,7 @@ * file that was distributed with this source code. */ -namespace Predis\Command\Redis\Container; +namespace Predis\Command\Container; interface ContainerInterface { @@ -18,11 +18,11 @@ interface ContainerInterface * Creates Redis container command with subcommand as virtual method name * and sends a request to the server. * - * @param $subcommandID - * @param $arguments + * @param string $subcommandID + * @param array $arguments * @return mixed */ - public function __call($subcommandID, $arguments); + public function __call(string $subcommandID, array $arguments); /** * Returns containerCommandId of specific container command. diff --git a/src/Command/Redis/Container/FunctionContainer.php b/src/Command/Container/FUNCTIONS.php similarity index 84% rename from src/Command/Redis/Container/FunctionContainer.php rename to src/Command/Container/FUNCTIONS.php index d757a44f..5b5c7860 100644 --- a/src/Command/Redis/Container/FunctionContainer.php +++ b/src/Command/Container/FUNCTIONS.php @@ -10,7 +10,7 @@ * file that was distributed with this source code. */ -namespace Predis\Command\Redis\Container; +namespace Predis\Command\Container; use Predis\Response\Status; @@ -18,7 +18,7 @@ use Predis\Response\Status; * @method string load(string $functionCode, bool $replace = 'false') * @method Status delete(string $libraryName) */ -class FunctionContainer extends AbstractContainer +class FUNCTIONS extends AbstractContainer { public function getContainerCommandId(): string { diff --git a/src/Command/Redis/Container/Json/JSONDEBUG.php b/src/Command/Container/Json/JSONDEBUG.php similarity index 82% rename from src/Command/Redis/Container/Json/JSONDEBUG.php rename to src/Command/Container/Json/JSONDEBUG.php index b20baca0..0bf4e862 100644 --- a/src/Command/Redis/Container/Json/JSONDEBUG.php +++ b/src/Command/Container/Json/JSONDEBUG.php @@ -10,9 +10,9 @@ * file that was distributed with this source code. */ -namespace Predis\Command\Redis\Container\Json; +namespace Predis\Command\Container\Json; -use Predis\Command\Redis\Container\AbstractContainer; +use Predis\Command\Container\AbstractContainer; /** * @method array memory(string $key, string $path) diff --git a/src/Command/Redis/Container/Search/FTCONFIG.php b/src/Command/Container/Search/FTCONFIG.php similarity index 84% rename from src/Command/Redis/Container/Search/FTCONFIG.php rename to src/Command/Container/Search/FTCONFIG.php index 9e80b8c5..5f718d3d 100644 --- a/src/Command/Redis/Container/Search/FTCONFIG.php +++ b/src/Command/Container/Search/FTCONFIG.php @@ -10,9 +10,9 @@ * file that was distributed with this source code. */ -namespace Predis\Command\Redis\Container\Search; +namespace Predis\Command\Container\Search; -use Predis\Command\Redis\Container\AbstractContainer; +use Predis\Command\Container\AbstractContainer; use Predis\Response\Status; /** diff --git a/src/Command/Redis/Container/Search/FTCURSOR.php b/src/Command/Container/Search/FTCURSOR.php similarity index 85% rename from src/Command/Redis/Container/Search/FTCURSOR.php rename to src/Command/Container/Search/FTCURSOR.php index 4d47c9c0..1cd4fa87 100644 --- a/src/Command/Redis/Container/Search/FTCURSOR.php +++ b/src/Command/Container/Search/FTCURSOR.php @@ -10,10 +10,10 @@ * file that was distributed with this source code. */ -namespace Predis\Command\Redis\Container\Search; +namespace Predis\Command\Container\Search; use Predis\Command\Argument\Search\CursorArguments; -use Predis\Command\Redis\Container\AbstractContainer; +use Predis\Command\Container\AbstractContainer; use Predis\Response\Status; /** diff --git a/src/Command/Redis/Json/JSONMERGE.php b/src/Command/Redis/Json/JSONMERGE.php new file mode 100644 index 00000000..a1322283 --- /dev/null +++ b/src/Command/Redis/Json/JSONMERGE.php @@ -0,0 +1,29 @@ + $argumentsLength || - !is_array($arguments[static::$keysArgumentPositionOffset]) + static::$keysArgumentPositionOffset > $argumentsLength + || !is_array($arguments[static::$keysArgumentPositionOffset]) ) { throw new UnexpectedValueException('Wrong keys argument type or position offset'); } diff --git a/src/Configuration/Options.php b/src/Configuration/Options.php index de6504f7..3fff0412 100644 --- a/src/Configuration/Options.php +++ b/src/Configuration/Options.php @@ -67,8 +67,8 @@ class Options implements OptionsInterface public function defined($option) { return - array_key_exists($option, $this->options) || - array_key_exists($option, $this->input) + array_key_exists($option, $this->options) + || array_key_exists($option, $this->input) ; } @@ -78,8 +78,8 @@ class Options implements OptionsInterface public function __isset($option) { return ( - array_key_exists($option, $this->options) || - array_key_exists($option, $this->input) + array_key_exists($option, $this->options) + || array_key_exists($option, $this->input) ) && $this->__get($option) !== null; } diff --git a/src/Connection/RelayMethods.php b/src/Connection/RelayMethods.php index 0e460a6e..a52c4a03 100644 --- a/src/Connection/RelayMethods.php +++ b/src/Connection/RelayMethods.php @@ -32,7 +32,7 @@ trait RelayMethods * @param string $pattern * @return bool */ - public function onInvalidated(?callable $callback, ?string $pattern = null) + public function onInvalidated(?callable $callback, string $pattern = null) { return $this->client->onInvalidated($callback, $pattern); } @@ -129,7 +129,7 @@ trait RelayMethods * @param ?int $db * @return bool */ - public function flushMemory(?string $endpointId = null, int $db = null) + public function flushMemory(string $endpointId = null, int $db = null) { return $this->client->flushMemory($endpointId, $db); } diff --git a/src/PubSub/AbstractConsumer.php b/src/PubSub/AbstractConsumer.php index 653517a0..c9ea2d65 100644 --- a/src/PubSub/AbstractConsumer.php +++ b/src/PubSub/AbstractConsumer.php @@ -32,7 +32,7 @@ abstract class AbstractConsumer implements Iterator public const STATUS_SUBSCRIBED = 2; // 0b0010 public const STATUS_PSUBSCRIBED = 4; // 0b0100 - protected $position = null; + protected $position; protected $statusFlags = self::STATUS_VALID; /** diff --git a/tests/PHPUnit/OneOfConstraint.php b/tests/PHPUnit/OneOfConstraint.php index 7c30cdbd..79529d38 100644 --- a/tests/PHPUnit/OneOfConstraint.php +++ b/tests/PHPUnit/OneOfConstraint.php @@ -44,7 +44,7 @@ class OneOfConstraint extends Constraint } /** - * @param $other + * @param mixed $other * @return string */ protected function failureDescription($other): string diff --git a/tests/PHPUnit/PredisTestCase.php b/tests/PHPUnit/PredisTestCase.php index d334f59a..d67829e8 100644 --- a/tests/PHPUnit/PredisTestCase.php +++ b/tests/PHPUnit/PredisTestCase.php @@ -22,7 +22,7 @@ use Predis\Connection; */ abstract class PredisTestCase extends \PHPUnit\Framework\TestCase { - protected $redisServerVersion = null; + protected $redisServerVersion; protected $redisJsonVersion; /** @@ -73,7 +73,7 @@ abstract class PredisTestCase extends \PHPUnit\Framework\TestCase * * @return RedisCommandConstraint */ - public function isRedisCommand($command = null, ?array $arguments = null): RedisCommandConstraint + public function isRedisCommand($command = null, array $arguments = null): RedisCommandConstraint { return new RedisCommandConstraint($command, $arguments); } @@ -224,7 +224,7 @@ abstract class PredisTestCase extends \PHPUnit\Framework\TestCase * * @return Client */ - protected function createClient(?array $parameters = null, ?array $options = null, ?bool $flushdb = true): Client + protected function createClient(array $parameters = null, array $options = null, ?bool $flushdb = true): Client { $parameters = array_merge( $this->getDefaultParametersArray(), @@ -300,7 +300,6 @@ abstract class PredisTestCase extends \PHPUnit\Framework\TestCase * the default connection parameters used by Predis or a set of connection * parameters specified in the optional second argument. * - * @param array|string|null $parameters Optional connection parameters * * @return MockObject|Connection\NodeConnectionInterface @@ -362,9 +361,9 @@ abstract class PredisTestCase extends \PHPUnit\Framework\TestCase $this->getName(false) ); - if (isset($annotations['method']['requiresRedisVersion'], $annotations['method']['group']) && - !empty($annotations['method']['requiresRedisVersion']) && - in_array('connected', $annotations['method']['group']) + if (isset($annotations['method']['requiresRedisVersion'], $annotations['method']['group']) + && !empty($annotations['method']['requiresRedisVersion']) + && in_array('connected', $annotations['method']['group']) ) { return $annotations['method']['requiresRedisVersion'][0]; } @@ -517,9 +516,9 @@ abstract class PredisTestCase extends \PHPUnit\Framework\TestCase $this->getName(false) ); - if (isset($annotations['method'][$moduleAnnotation], $annotations['method']['group']) && - !empty($annotations['method'][$moduleAnnotation]) && - in_array('connected', $annotations['method']['group'], true) + if (isset($annotations['method'][$moduleAnnotation], $annotations['method']['group']) + && !empty($annotations['method'][$moduleAnnotation]) + && in_array('connected', $annotations['method']['group'], true) ) { return $annotations['method'][$moduleAnnotation][0]; } diff --git a/tests/PHPUnit/RedisCommandConstraint.php b/tests/PHPUnit/RedisCommandConstraint.php index 8cb77e18..d4e0b4ec 100644 --- a/tests/PHPUnit/RedisCommandConstraint.php +++ b/tests/PHPUnit/RedisCommandConstraint.php @@ -25,7 +25,7 @@ class RedisCommandConstraint extends \PHPUnit\Framework\Constraint\Constraint * @param string|CommandInterface $command Expected command instance or command ID * @param ?array $arguments Expected command arguments */ - public function __construct($command, ?array $arguments = null) + public function __construct($command, array $arguments = null) { if ($command instanceof CommandInterface) { $this->commandID = strtoupper($command->getId()); diff --git a/tests/Predis/Cluster/PredisStrategyTest.php b/tests/Predis/Cluster/PredisStrategyTest.php index 594c4ed3..fbf7922c 100644 --- a/tests/Predis/Cluster/PredisStrategyTest.php +++ b/tests/Predis/Cluster/PredisStrategyTest.php @@ -310,7 +310,7 @@ class PredisStrategyTest extends PredisTestCase * * @return array */ - protected function getExpectedCommands(?string $type = null): array + protected function getExpectedCommands(string $type = null): array { $commands = [ /* commands operating on the key space */ diff --git a/tests/Predis/Cluster/RedisStrategyTest.php b/tests/Predis/Cluster/RedisStrategyTest.php index d19eec85..dd570d53 100644 --- a/tests/Predis/Cluster/RedisStrategyTest.php +++ b/tests/Predis/Cluster/RedisStrategyTest.php @@ -333,7 +333,7 @@ class RedisStrategyTest extends PredisTestCase * * @return array */ - protected function getExpectedCommands(?string $type = null): array + protected function getExpectedCommands(string $type = null): array { $commands = [ /* commands operating on the key space */ diff --git a/tests/Predis/Command/Redis/Container/AbstractContainerTest.php b/tests/Predis/Command/Container/AbstractContainerTest.php similarity index 98% rename from tests/Predis/Command/Redis/Container/AbstractContainerTest.php rename to tests/Predis/Command/Container/AbstractContainerTest.php index 7a91307e..857f7502 100644 --- a/tests/Predis/Command/Redis/Container/AbstractContainerTest.php +++ b/tests/Predis/Command/Container/AbstractContainerTest.php @@ -10,7 +10,7 @@ * file that was distributed with this source code. */ -namespace Predis\Command\Redis\Container; +namespace Predis\Command\Container; use PHPUnit\Framework\TestCase; use Predis\ClientInterface; diff --git a/tests/Predis/Command/Redis/Container/ContainerFactoryTest.php b/tests/Predis/Command/Container/ContainerFactoryTest.php similarity index 93% rename from tests/Predis/Command/Redis/Container/ContainerFactoryTest.php rename to tests/Predis/Command/Container/ContainerFactoryTest.php index f98901e1..2aa13044 100644 --- a/tests/Predis/Command/Redis/Container/ContainerFactoryTest.php +++ b/tests/Predis/Command/Container/ContainerFactoryTest.php @@ -10,12 +10,12 @@ * file that was distributed with this source code. */ -namespace Predis\Command\Redis\Container; +namespace Predis\Command\Container; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Predis\ClientInterface; -use Predis\Command\Redis\Container\Search\FTCONFIG; +use Predis\Command\Container\Search\FTCONFIG; use UnexpectedValueException; class ContainerFactoryTest extends TestCase @@ -73,7 +73,7 @@ class ContainerFactoryTest extends TestCase public function containerProvider(): array { return [ - 'core command' => ['function', FunctionContainer::class], + 'core command' => ['function', FUNCTIONS::class], 'module command' => ['ftconfig', FTCONFIG::class], ]; } diff --git a/tests/Predis/Command/Redis/EVALSHA_RO_Test.php b/tests/Predis/Command/Redis/EVALSHA_RO_Test.php index 596e4c38..74ad40ce 100644 --- a/tests/Predis/Command/Redis/EVALSHA_RO_Test.php +++ b/tests/Predis/Command/Redis/EVALSHA_RO_Test.php @@ -61,10 +61,10 @@ class EVALSHA_RO_Test extends PredisCommandTestCase /** * @group connected * @dataProvider scriptsProvider - * @param string $script - * @param array $keys - * @param array $arguments - * @param $expectedResponse + * @param string $script + * @param array $keys + * @param array $arguments + * @param mixed $expectedResponse * @return void * @requiresRedisVersion >= 7.0.0 */ diff --git a/tests/Predis/Command/Redis/EVAL_RO_Test.php b/tests/Predis/Command/Redis/EVAL_RO_Test.php index 89c93d40..cdeb5b70 100644 --- a/tests/Predis/Command/Redis/EVAL_RO_Test.php +++ b/tests/Predis/Command/Redis/EVAL_RO_Test.php @@ -61,11 +61,11 @@ class EVAL_RO_Test extends PredisCommandTestCase /** * @group connected * @dataProvider scriptsProvider - * @param array $dictionary - * @param string $script - * @param array $keys - * @param array $arguments - * @param $expectedResponse + * @param array $dictionary + * @param string $script + * @param array $keys + * @param array $arguments + * @param mixed $expectedResponse * @return void * @requiresRedisVersion >= 7.0.0 */ diff --git a/tests/Predis/Command/Redis/EXPIREAT_Test.php b/tests/Predis/Command/Redis/EXPIREAT_Test.php index 44829683..cee43824 100644 --- a/tests/Predis/Command/Redis/EXPIREAT_Test.php +++ b/tests/Predis/Command/Redis/EXPIREAT_Test.php @@ -166,14 +166,14 @@ class EXPIREAT_Test extends PredisCommandTestCase ['noExpiry', time() + 10, 'XX'], ], 'only if new expiry is greater then current one' => [ - ['newExpiryLower', 'value', 'EXAT', time() + 1000], - ['newExpiryGreater', 'value', 'EXAT', time() + 10], + ['newExpiryLower', 'value', 'EX', 1000], + ['newExpiryGreater', 'value', 'EX', 10], ['newExpiryGreater', time() + 20, 'GT'], ['newExpiryLower', time() + 20, 'GT'], ], 'only if new expiry is lower then current one' => [ - ['newExpiryLower', 'value', 'EXAT', time() + 1000], - ['newExpiryGreater', 'value', 'EXAT', time() + 10], + ['newExpiryLower', 'value', 'EX', 1000], + ['newExpiryGreater', 'value', 'EX', 10], ['newExpiryLower', time() + 20, 'LT'], ['newExpiryGreater', time() + 20, 'LT'], ], diff --git a/tests/Predis/Command/Redis/FCALL_RO_Test.php b/tests/Predis/Command/Redis/FCALL_RO_Test.php index a90695f3..87a3d334 100644 --- a/tests/Predis/Command/Redis/FCALL_RO_Test.php +++ b/tests/Predis/Command/Redis/FCALL_RO_Test.php @@ -113,8 +113,8 @@ class FCALL_RO_Test extends PredisCommandTestCase ); if ( - isset($annotations['method']['group']) && - in_array('connected', $annotations['method']['group'], true) + isset($annotations['method']['group']) + && in_array('connected', $annotations['method']['group'], true) ) { $redis = $this->getClient(); $redis->function->delete(self::LIB_NAME); diff --git a/tests/Predis/Command/Redis/FCALL_Test.php b/tests/Predis/Command/Redis/FCALL_Test.php index 8729e6f1..4e4ab055 100644 --- a/tests/Predis/Command/Redis/FCALL_Test.php +++ b/tests/Predis/Command/Redis/FCALL_Test.php @@ -78,9 +78,9 @@ class FCALL_Test extends PredisCommandTestCase /** * @group connected * @dataProvider functionsProvider - * @param string $function - * @param array $functionArguments - * @param $expectedResponse + * @param string $function + * @param array $functionArguments + * @param mixed $expectedResponse * @return void * @requiresRedisVersion >= 7.0.0 */ diff --git a/tests/Predis/Command/Redis/Json/JSONMERGE_Test.php b/tests/Predis/Command/Redis/Json/JSONMERGE_Test.php new file mode 100644 index 00000000..b9cb7a74 --- /dev/null +++ b/tests/Predis/Command/Redis/Json/JSONMERGE_Test.php @@ -0,0 +1,103 @@ +getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse(): void + { + $this->assertSame(1, $this->getCommand()->parseResponse(1)); + } + + /** + * @dataProvider jsonProvider + * @group connected + * @param array $setArguments + * @param array $mergeArguments + * @param string $expectedResponse + * @return void + * @requiresRedisJsonVersion >= 2.6.0 + */ + public function testMergeCorrectlyMergeJsonValues( + array $setArguments, + array $mergeArguments, + string $expectedResponse + ): void { + $redis = $this->getClient(); + + $this->assertEquals('OK', $redis->jsonset(...$setArguments)); + $this->assertEquals('OK', $redis->jsonmerge(...$mergeArguments)); + $this->assertEquals($expectedResponse, $redis->jsonget('key')); + } + + public function jsonProvider(): array + { + return [ + 'create non-existing value' => [ + ['key', '$', '{"a":2}'], + ['key', '$.b', '8'], + '{"a":2,"b":8}', + ], + 'replace existing value' => [ + ['key', '$', '{"a":2}'], + ['key', '$.a', '3'], + '{"a":3}', + ], + 'replace an array' => [ + ['key', '$', '{"a":[2,4,6,8]}'], + ['key', '$.a', '[10,12]'], + '{"a":[10,12]}', + ], + 'merge in multiple-paths' => [ + ['key', '$', '{"f1": {"a":1}, "f2":{"a":2}}'], + ['key', '$', '{"f2":{"a":3, "b":4}, "f3":[2,4,6]}'], + '{"f1":{"a":1},"f2":{"a":3,"b":4},"f3":[2,4,6]}', + ], + ]; + } +} diff --git a/tests/Predis/Command/Redis/Json/JSONMSET_Test.php b/tests/Predis/Command/Redis/Json/JSONMSET_Test.php new file mode 100644 index 00000000..2083d39c --- /dev/null +++ b/tests/Predis/Command/Redis/Json/JSONMSET_Test.php @@ -0,0 +1,85 @@ +getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse(): void + { + $this->assertSame(1, $this->getCommand()->parseResponse(1)); + } + + /** + * @group connected + * @return void + * @requiresRedisJsonVersion >= 2.6.0 + */ + public function testSetMultipleJsonDocuments(): void + { + $redis = $this->getClient(); + + $this->assertEquals('OK', $redis->jsonmset('doc1', '$', '{"a":2}', 'doc2', '$', '{"b":3}')); + $this->assertEquals(['[{"a":2}]', '[{"b":3}]'], $redis->jsonmget(['doc1', 'doc2'], '$')); + } + + /** + * @group connected + * @return void + * @requiresRedisJsonVersion >= 2.6.0 + */ + public function testThrowsExceptionOnNewValuesNotInTheRootPath(): void + { + $redis = $this->getClient(); + + $this->expectException(ServerException::class); + $this->expectExceptionMessage('ERR new objects must be created at the root'); + + $redis->jsonmset('doc1', '$', '{"a":2}', 'doc2', '$.f', '{"b":3}'); + } +} diff --git a/tests/Predis/Command/Redis/LCS_Test.php b/tests/Predis/Command/Redis/LCS_Test.php index 839084a3..72cb5c6c 100644 --- a/tests/Predis/Command/Redis/LCS_Test.php +++ b/tests/Predis/Command/Redis/LCS_Test.php @@ -58,9 +58,9 @@ class LCS_Test extends PredisCommandTestCase /** * @group connected * @dataProvider stringsProvider - * @param array $stringsArguments - * @param array $functionArguments - * @param $expectedResponse + * @param array $stringsArguments + * @param array $functionArguments + * @param mixed $expectedResponse * @return void * @requiresRedisVersion >= 7.0.0 */ diff --git a/tests/Predis/Command/Redis/Search/FTSEARCH_Test.php b/tests/Predis/Command/Redis/Search/FTSEARCH_Test.php index 58254af5..dfca91d5 100644 --- a/tests/Predis/Command/Redis/Search/FTSEARCH_Test.php +++ b/tests/Predis/Command/Redis/Search/FTSEARCH_Test.php @@ -113,6 +113,9 @@ class FTSEARCH_Test extends PredisCommandTestCase $ftCreateResponse = $redis->ftcreate('idx_hash', $schema, $ftCreateArguments); $this->assertEquals('OK', $ftCreateResponse); + // Timeout to make sure that index created before search performed. + usleep(2000); + $ftSearchArguments = new SearchArguments(); $ftSearchArguments->addReturn(1, 'should_return'); diff --git a/tests/Predis/Command/Redis/ZINTERCARD_Test.php b/tests/Predis/Command/Redis/ZINTERCARD_Test.php index d307eff1..7923b4d8 100644 --- a/tests/Predis/Command/Redis/ZINTERCARD_Test.php +++ b/tests/Predis/Command/Redis/ZINTERCARD_Test.php @@ -110,8 +110,8 @@ class ZINTERCARD_Test extends PredisCommandTestCase /** * @group connected * @dataProvider unexpectedValuesProvider - * @param $keys - * @param $limit + * @param mixed $keys + * @param mixed $limit * @param string $expectedExceptionMessage * @return void * @requiresRedisVersion >= 7.0.0 diff --git a/tests/Predis/Command/Redis/ZINTERSTORE_Test.php b/tests/Predis/Command/Redis/ZINTERSTORE_Test.php index 3c7229a9..bad586c1 100644 --- a/tests/Predis/Command/Redis/ZINTERSTORE_Test.php +++ b/tests/Predis/Command/Redis/ZINTERSTORE_Test.php @@ -133,9 +133,9 @@ class ZINTERSTORE_Test extends PredisCommandTestCase /** * @dataProvider unexpectedValueProvider - * @param string $destination - * @param $keys - * @param $weights + * @param string $destination + * @param mixed $keys + * @param mixed $weights * @param string $aggregate * @param string $expectedExceptionMessage * @return void diff --git a/tests/Predis/Command/Redis/ZINTER_Test.php b/tests/Predis/Command/Redis/ZINTER_Test.php index 9390cd5a..22eaef5b 100644 --- a/tests/Predis/Command/Redis/ZINTER_Test.php +++ b/tests/Predis/Command/Redis/ZINTER_Test.php @@ -127,8 +127,8 @@ class ZINTER_Test extends PredisCommandTestCase /** * @dataProvider unexpectedValueProvider - * @param $keys - * @param $weights + * @param mixed $keys + * @param mixed $weights * @param string $aggregate * @param bool $withScores * @param string $expectedExceptionMessage diff --git a/tests/Predis/Command/Redis/ZRANGESTORE_Test.php b/tests/Predis/Command/Redis/ZRANGESTORE_Test.php index d60e4ad6..2989a3ed 100644 --- a/tests/Predis/Command/Redis/ZRANGESTORE_Test.php +++ b/tests/Predis/Command/Redis/ZRANGESTORE_Test.php @@ -102,14 +102,14 @@ class ZRANGESTORE_Test extends PredisCommandTestCase /** * @group connected * @dataProvider unexpectedValuesProvider - * @param int|string $min - * @param int|string $max - * @param string|bool $by - * @param $rev - * @param $limit - * @param int $offset - * @param int $count - * @param string $expectedExceptionMessage + * @param int|string $min + * @param int|string $max + * @param string|bool $by + * @param $rev + * @param $limit + * @param int $offset + * @param int $count + * @param string $expectedExceptionMessage * @return void * @requiresRedisVersion >= 6.2.0 */ diff --git a/tests/Predis/Command/Redis/ZUNIONSTORE_Test.php b/tests/Predis/Command/Redis/ZUNIONSTORE_Test.php index 3bc036a4..2d9e8532 100644 --- a/tests/Predis/Command/Redis/ZUNIONSTORE_Test.php +++ b/tests/Predis/Command/Redis/ZUNIONSTORE_Test.php @@ -133,9 +133,9 @@ class ZUNIONSTORE_Test extends PredisCommandTestCase /** * @dataProvider unexpectedValueProvider - * @param string $destination - * @param $keys - * @param $weights + * @param string $destination + * @param $keys + * @param $weights * @param string $aggregate * @param string $expectedExceptionMessage * @return void diff --git a/tests/Predis/Command/Redis/ZUNION_Test.php b/tests/Predis/Command/Redis/ZUNION_Test.php index 2e1d3ed4..0cd033c9 100644 --- a/tests/Predis/Command/Redis/ZUNION_Test.php +++ b/tests/Predis/Command/Redis/ZUNION_Test.php @@ -101,8 +101,8 @@ class ZUNION_Test extends PredisCommandTestCase /** * @dataProvider unexpectedValueProvider - * @param $keys - * @param $weights + * @param $keys + * @param $weights * @param string $aggregate * @param bool $withScores * @param string $expectedExceptionMessage diff --git a/tests/Predis/Replication/ReplicationStrategyTest.php b/tests/Predis/Replication/ReplicationStrategyTest.php index ca9ae4bd..128bbce4 100644 --- a/tests/Predis/Replication/ReplicationStrategyTest.php +++ b/tests/Predis/Replication/ReplicationStrategyTest.php @@ -390,7 +390,7 @@ class ReplicationStrategyTest extends PredisTestCase * * @return array */ - protected function getExpectedCommands(?string $type = null): array + protected function getExpectedCommands(string $type = null): array { $commands = [ /* commands operating on the connection */