diff --git a/.gitattributes b/.gitattributes
index e20c2b8a..226cb6ab 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
@@ -12,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..fd468fff 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,18 +2,25 @@
## Unreleased
+### Changed
+- Added `PrefixableCommandInterface` (#1262)
+
+### Removed
+- Removed Webdis and Phpiredis support (#1291)
+
+## v2.2.0-RC1 (2023-05-09)
+
### Added
-- Added support for `ACL SETUSER, GETUSER, DRYRUN` commands
-- 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 [Relay](https://github.com/predis/predis/wiki/Using-Relay) (#1263)
+- 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/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/VERSION b/VERSION
index eca07e4c..2468aa9e 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.1.2
+3.0.0-dev
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/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
new file mode 100644
index 00000000..bfe4f52a
--- /dev/null
+++ b/phpunit.relay.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+ tests/Predis/
+
+
+
+
+
+ relay-incompatible
+ realm-stack
+ ext-curl
+
+
+
+
+
+ src/
+
+
+
+
+
+
+
+
+
+
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index dff6900b..662e1fd4 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -28,9 +28,9 @@
- ext-phpiredis
+ realm-stack
+ ext-relay
ext-curl
- realm-webdis
@@ -45,13 +45,9 @@
-
-
-
-
-
+
diff --git a/src/Client.php b/src/Client.php
index 66dfdc42..f2d45628 100644
--- a/src/Client.php
+++ b/src/Client.php
@@ -16,18 +16,24 @@ 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;
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;
@@ -47,7 +53,7 @@ use Traversable;
*/
class Client implements ClientInterface, IteratorAggregate
{
- public const VERSION = '2.1.2';
+ public const VERSION = '3.0.0-dev';
/** @var OptionsInterface */
private $options;
@@ -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
@@ -314,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');
}
@@ -440,19 +472,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;
+ }
}
/*
@@ -522,7 +564,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/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/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 @@
-
*/
#[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/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/Processor/ProcessorChain.php b/src/Command/Processor/ProcessorChain.php
index 8ecfc4d9..1ce915e2 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/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 3cf9dc74..2f5daad5 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/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 @@
+ $data[1], $data[2] => $data[3]];
}
diff --git a/src/Command/Redis/SORT.php b/src/Command/Redis/SORT.php
index 428745f6..bb62d068 100644
--- a/src/Command/Redis/SORT.php
+++ b/src/Command/Redis/SORT.php
@@ -60,9 +60,9 @@ class SORT extends RedisCommand
}
}
- if (isset($sortParams['LIMIT']) &&
- is_array($sortParams['LIMIT']) &&
- count($sortParams['LIMIT']) == 2) {
+ if (isset($sortParams['LIMIT'])
+ && is_array($sortParams['LIMIT'])
+ && count($sortParams['LIMIT']) == 2) {
$query[] = 'LIMIT';
$query[] = $sortParams['LIMIT'][0];
$query[] = $sortParams['LIMIT'][1];
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 30467894..68fb7877 100644
--- a/src/Command/Redis/TYPE.php
+++ b/src/Command/Redis/TYPE.php
@@ -27,6 +27,31 @@ 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;
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
public function prefixKeys($prefix)
{
$this->applyPrefixForFirstArgument($prefix);
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 b0efcee9..b2801c90 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/Keys.php b/src/Command/Traits/Keys.php
index a623e9ca..5dc86ad7 100644
--- a/src/Command/Traits/Keys.php
+++ b/src/Command/Traits/Keys.php
@@ -25,8 +25,8 @@ trait Keys
$argumentsLength = count($arguments);
if (
- static::$keysArgumentPositionOffset > $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/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/CRC16.php b/src/Configuration/Option/CRC16.php
index b1714492..809a9059 100644
--- a/src/Configuration/Option/CRC16.php
+++ b/src/Configuration/Option/CRC16.php
@@ -26,7 +26,7 @@ class CRC16 implements OptionInterface
* Returns an hash generator instance from a descriptive name.
*
* @param OptionsInterface $options Client options.
- * @param string $description Identifier of a hash generator (`predis`, `phpiredis`)
+ * @param string $description Identifier of a hash generator (`predis`)
*
* @return callable
*/
@@ -34,11 +34,9 @@ class CRC16 implements OptionInterface
{
if ($description === 'predis') {
return new Hash\CRC16();
- } elseif ($description === 'phpiredis') {
- return new Hash\PhpiredisCRC16();
} else {
throw new InvalidArgumentException(
- 'String value for the crc16 option must be either `predis` or `phpiredis`'
+ 'String value for the crc16 option must be either `predis`'
);
}
}
@@ -67,8 +65,6 @@ class CRC16 implements OptionInterface
*/
public function getDefault(OptionsInterface $options)
{
- return function_exists('phpiredis_utils_crc16')
- ? new Hash\PhpiredisCRC16()
- : new Hash\CRC16();
+ return new Hash\CRC16();
}
}
diff --git a/src/Configuration/Option/Connections.php b/src/Configuration/Option/Connections.php
index 89bfb8f0..a3e14668 100644
--- a/src/Configuration/Option/Connections.php
+++ b/src/Configuration/Option/Connections.php
@@ -17,8 +17,7 @@ use Predis\Configuration\OptionInterface;
use Predis\Configuration\OptionsInterface;
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.
@@ -86,9 +85,7 @@ class Connections implements OptionInterface
* string that identifies specific configurations of schemes and connection
* classes. Supported configuration values are:
*
- * - "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
@@ -103,17 +100,10 @@ class Connections implements OptionInterface
$factory = $this->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);
+ case 'relay':
+ $factory->define('tcp', RelayConnection::class);
+ $factory->define('redis', RelayConnection::class);
+ $factory->define('unix', RelayConnection::class);
break;
case 'default':
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/Cluster/PredisCluster.php b/src/Connection/Cluster/PredisCluster.php
index f1039dbb..cacf0553 100644
--- a/src/Connection/Cluster/PredisCluster.php
+++ b/src/Connection/Cluster/PredisCluster.php
@@ -22,6 +22,7 @@ use Predis\Connection\NodeConnectionInterface;
use Predis\Connection\ParametersInterface;
use Predis\NotSupportedException;
use ReturnTypeWillChange;
+use Traversable;
/**
* Abstraction for a cluster of aggregate connections to various Redis servers
@@ -214,7 +215,7 @@ class PredisCluster implements ClusterInterface, IteratorAggregate, Countable
}
/**
- * {@inheritdoc}
+ * @return int
*/
#[ReturnTypeWillChange]
public function count()
@@ -223,7 +224,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 186ec883..078e1d91 100644
--- a/src/Connection/Cluster/RedisCluster.php
+++ b/src/Connection/Cluster/RedisCluster.php
@@ -32,6 +32,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).
@@ -603,7 +604,7 @@ class RedisCluster implements ClusterInterface, IteratorAggregate, Countable
}
/**
- * {@inheritdoc}
+ * @return int
*/
#[ReturnTypeWillChange]
public function count()
@@ -612,7 +613,7 @@ class RedisCluster implements ClusterInterface, IteratorAggregate, Countable
}
/**
- * {@inheritdoc}
+ * @return Traversable
*/
#[ReturnTypeWillChange]
public function getIterator()
diff --git a/src/Connection/Factory.php b/src/Connection/Factory.php
index 2fa446a3..411a0d7b 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/ParametersInterface.php b/src/Connection/ParametersInterface.php
index d33197c6..464ef145 100644
--- a/src/Connection/ParametersInterface.php
+++ b/src/Connection/ParametersInterface.php
@@ -27,11 +27,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/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/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..a52c4a03
--- /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/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/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/Pipeline/Pipeline.php b/src/Pipeline/Pipeline.php
index 09b7c287..d50f058a 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 f764693d..c9ea2d65 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;
+ protected $statusFlags = self::STATUS_VALID;
/**
* Automatically stops the consumer when the garbage collector kicks in.
@@ -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/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/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..68c87378 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)
diff --git a/src/Transaction/MultiExec.php b/src/Transaction/MultiExec.php
index 2793bad1..3edc1a0b 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.'
@@ -402,10 +426,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;
+ }
+
if ($protocolVersion === 2) {
$response[$i] = $commands->dequeue()->parseResponse($cmdResponse);
} else {
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/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..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(),
@@ -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);
@@ -301,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
@@ -363,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];
}
@@ -518,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/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/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/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/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/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 85e5250e..cee43824 100644
--- a/tests/Predis/Command/Redis/EXPIREAT_Test.php
+++ b/tests/Predis/Command/Redis/EXPIREAT_Test.php
@@ -112,8 +112,8 @@ class EXPIREAT_Test extends PredisCommandTestCase
/**
* @medium
* @group connected
- * @dataProvider keysProvider
* @group slow
+ * @dataProvider keysProvider
* @param array $firstKeyArguments
* @param array $secondKeyArguments
* @param array $positivePathArguments
@@ -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/EXPIRE_Test.php b/tests/Predis/Command/Redis/EXPIRE_Test.php
index d3a0a5f6..d753e421 100644
--- a/tests/Predis/Command/Redis/EXPIRE_Test.php
+++ b/tests/Predis/Command/Redis/EXPIRE_Test.php
@@ -109,8 +109,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_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 78eba93a..4e4ab055 100644
--- a/tests/Predis/Command/Redis/FCALL_Test.php
+++ b/tests/Predis/Command/Redis/FCALL_Test.php
@@ -18,6 +18,7 @@ use Predis\Response\ServerException;
/**
* @group commands
* @group realm-scripting
+ * @requiresRedisVersion >= 7.0.0
*/
class FCALL_Test extends PredisCommandTestCase
{
@@ -77,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
*/
@@ -89,6 +90,7 @@ class FCALL_Test extends PredisCommandTestCase
$expectedResponse
): void {
$redis = $this->getClient();
+ $redis->executeRaw(['FUNCTION', 'FLUSH']);
$this->assertSame('mylib', $redis->function->load($function));
@@ -105,6 +107,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 c0dfcad3..cb71a6f3 100644
--- a/tests/Predis/Command/Redis/GEOADD_Test.php
+++ b/tests/Predis/Command/Redis/GEOADD_Test.php
@@ -107,7 +107,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 f13dd654..e5d68a3f 100644
--- a/tests/Predis/Command/Redis/GETBIT_Test.php
+++ b/tests/Predis/Command/Redis/GETBIT_Test.php
@@ -99,8 +99,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();
@@ -114,8 +113,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 b92fa4ae..54a9d015 100644
--- a/tests/Predis/Command/Redis/HMGET_Test.php
+++ b/tests/Predis/Command/Redis/HMGET_Test.php
@@ -105,7 +105,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/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/MIGRATE_Test.php b/tests/Predis/Command/Redis/MIGRATE_Test.php
index 96bb361c..fafe87b6 100644
--- a/tests/Predis/Command/Redis/MIGRATE_Test.php
+++ b/tests/Predis/Command/Redis/MIGRATE_Test.php
@@ -107,6 +107,7 @@ class MIGRATE_Test extends PredisCommandTestCase
/**
* @group connected
+ * @group relay-incompatible
* @requiresRedisVersion >= 2.6.0
*/
public function testReturnsStatusNOKEYOnNonExistingKey(): void
@@ -117,6 +118,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 cce45ee6..a61b40ed 100644
--- a/tests/Predis/Command/Redis/MOVE_Test.php
+++ b/tests/Predis/Command/Redis/MOVE_Test.php
@@ -80,7 +80,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 4af67eee..5ff1db4b 100644
--- a/tests/Predis/Command/Redis/PSUBSCRIBE_Test.php
+++ b/tests/Predis/Command/Redis/PSUBSCRIBE_Test.php
@@ -17,6 +17,7 @@ use Predis\Command\PrefixableCommand;
/**
* @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 4162e2be..52b63370 100644
--- a/tests/Predis/Command/Redis/PUBLISH_Test.php
+++ b/tests/Predis/Command/Redis/PUBLISH_Test.php
@@ -77,6 +77,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 a9b3bb4c..343a1d08 100644
--- a/tests/Predis/Command/Redis/PUNSUBSCRIBE_Test.php
+++ b/tests/Predis/Command/Redis/PUNSUBSCRIBE_Test.php
@@ -17,6 +17,7 @@ use Predis\Command\PrefixableCommand;
/**
* @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 b9b58ad7..19fa688e 100644
--- a/tests/Predis/Command/Redis/SUBSCRIBE_Test.php
+++ b/tests/Predis/Command/Redis/SUBSCRIBE_Test.php
@@ -17,6 +17,7 @@ use Predis\Command\PrefixableCommand;
/**
* @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 e3c02d53..3e5c3b7f 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/FTSEARCH_Test.php b/tests/Predis/Command/Redis/Search/FTSEARCH_Test.php
index ecbf593f..dfca91d5 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');
@@ -110,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/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 d7be5538..422ba42d 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 b44aa213..26273e82 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 4f258795..6f1a6ac5 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 4b0bfbec..20fbc6ab 100644
--- a/tests/Predis/Command/Redis/UNSUBSCRIBE_Test.php
+++ b/tests/Predis/Command/Redis/UNSUBSCRIBE_Test.php
@@ -17,6 +17,7 @@ use Predis\Command\PrefixableCommand;
/**
* @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 b75c1e27..5fece04e 100644
--- a/tests/Predis/Command/Redis/WATCH_Test.php
+++ b/tests/Predis/Command/Redis/WATCH_Test.php
@@ -17,6 +17,7 @@ use Predis\Command\PrefixableCommand;
/**
* @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 11cb65af..4f46cdc9 100644
--- a/tests/Predis/Command/Redis/ZADD_Test.php
+++ b/tests/Predis/Command/Redis/ZADD_Test.php
@@ -173,10 +173,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 c26c4f94..d2884343 100644
--- a/tests/Predis/Command/Redis/ZINCRBY_Test.php
+++ b/tests/Predis/Command/Redis/ZINCRBY_Test.php
@@ -82,10 +82,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/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 cfcbbe3e..bad586c1 100644
--- a/tests/Predis/Command/Redis/ZINTERSTORE_Test.php
+++ b/tests/Predis/Command/Redis/ZINTERSTORE_Test.php
@@ -110,7 +110,7 @@ class ZINTERSTORE_Test extends PredisCommandTestCase
);
$this->assertSame($expectedResponse, $actualResponse);
- $this->assertSame(
+ $this->assertEquals(
$expectedResultSortedSet,
$redis->zrange($destination, 0, -1, ['withscores' => true])
);
@@ -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 297d4387..22eaef5b 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);
}
/**
@@ -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/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 1d830725..bc7d11b9 100644
--- a/tests/Predis/Command/Redis/ZRANGEBYSCORE_Test.php
+++ b/tests/Predis/Command/Redis/ZRANGEBYSCORE_Test.php
@@ -199,8 +199,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]));
}
/**
@@ -229,7 +229,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/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/ZRANGE_Test.php b/tests/Predis/Command/Redis/ZRANGE_Test.php
index eaffbc55..6e8b6fea 100644
--- a/tests/Predis/Command/Redis/ZRANGE_Test.php
+++ b/tests/Predis/Command/Redis/ZRANGE_Test.php
@@ -156,8 +156,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 fc2d51aa..7b9e03a2 100644
--- a/tests/Predis/Command/Redis/ZREVRANGEBYSCORE_Test.php
+++ b/tests/Predis/Command/Redis/ZREVRANGEBYSCORE_Test.php
@@ -203,8 +203,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]));
}
/**
@@ -235,7 +235,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 f2ac45b6..ab52a7a7 100644
--- a/tests/Predis/Command/Redis/ZREVRANGE_Test.php
+++ b/tests/Predis/Command/Redis/ZREVRANGE_Test.php
@@ -156,8 +156,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 7b2955ec..1d0fcf03 100644
--- a/tests/Predis/Command/Redis/ZSCORE_Test.php
+++ b/tests/Predis/Command/Redis/ZSCORE_Test.php
@@ -84,9 +84,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 a432da35..2d9e8532 100644
--- a/tests/Predis/Command/Redis/ZUNIONSTORE_Test.php
+++ b/tests/Predis/Command/Redis/ZUNIONSTORE_Test.php
@@ -110,7 +110,7 @@ class ZUNIONSTORE_Test extends PredisCommandTestCase
);
$this->assertSame($expectedResponse, $actualResponse);
- $this->assertSame(
+ $this->assertEquals(
$expectedResultSortedSet,
$redis->zrange($destination, 0, -1, ['withscores' => true])
);
@@ -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 eef3941a..0cd033c9 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);
}
/**
@@ -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/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 fc46308b..1fb0a391 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();
@@ -229,9 +229,7 @@ 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/Cluster/RedisClusterTest.php b/tests/Predis/Connection/Cluster/RedisClusterTest.php
index 47a6342c..5c58c5f1 100644
--- a/tests/Predis/Connection/Cluster/RedisClusterTest.php
+++ b/tests/Predis/Connection/Cluster/RedisClusterTest.php
@@ -758,6 +758,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 ab4bf802..ef71275c 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/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/RelayConnectionTest.php
similarity index 86%
rename from tests/Predis/Connection/PhpiredisStreamConnectionTest.php
rename to tests/Predis/Connection/RelayConnectionTest.php
index 83c5d2a5..11bc72e3 100644
--- a/tests/Predis/Connection/PhpiredisStreamConnectionTest.php
+++ b/tests/Predis/Connection/RelayConnectionTest.php
@@ -17,43 +17,17 @@ use Predis\Command\RawCommand;
use Predis\Response\Error as ErrorResponse;
/**
- * @group ext-phpiredis
- * @requires extension phpiredis
+ * @group ext-relay
+ * @requires extension relay
*/
-class PhpiredisStreamConnectionTest extends PredisConnectionTestCase
+class RelayConnectionTest extends PredisConnectionTestCase
{
/**
* {@inheritDoc}
*/
public function getConnectionClass(): string
{
- return 'Predis\Connection\PhpiredisStreamConnection';
- }
-
- /**
- * @group disconnected
- */
- public function testSupportsSchemeTls(): void
- {
- $this->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);
+ return RelayConnection::class;
}
/**
@@ -89,6 +63,18 @@ class PhpiredisStreamConnectionTest extends PredisConnectionTestCase
// ---- 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
@@ -110,6 +96,7 @@ class PhpiredisStreamConnectionTest extends PredisConnectionTestCase
/**
* @medium
* @group connected
+ * @group relay-incompatible
*/
public function testThrowsExceptionOnProtocolDesynchronizationErrors(): void
{
@@ -126,6 +113,7 @@ class PhpiredisStreamConnectionTest extends PredisConnectionTestCase
/**
* @group connected
+ * @group relay-incompatible
* @requires PHP 5.4
*/
public function testPersistentParameterWithFalseLikeValues(): void
@@ -145,6 +133,7 @@ class PhpiredisStreamConnectionTest extends PredisConnectionTestCase
/**
* @group connected
+ * @group relay-incompatible
* @requires PHP 5.4
*/
public function testPersistentParameterWithTrueLikeValues(): void
@@ -166,6 +155,7 @@ class PhpiredisStreamConnectionTest extends PredisConnectionTestCase
/**
* @group connected
+ * @group relay-incompatible
* @requires PHP 5.4
*/
public function testPersistentConnectionsToSameNodeShareResource(): void
@@ -183,6 +173,7 @@ class PhpiredisStreamConnectionTest extends PredisConnectionTestCase
/**
* @group connected
+ * @group relay-incompatible
* @requires PHP 5.4
*/
public function testPersistentConnectionsToSameNodeDoNotShareResourceUsingDifferentPersistentID(): void
@@ -198,6 +189,7 @@ class PhpiredisStreamConnectionTest extends PredisConnectionTestCase
/**
* @group connected
+ * @group relay-incompatible
*/
public function testTcpNodelayParameterSetsContextFlagWhenTrue()
{
@@ -212,6 +204,7 @@ class PhpiredisStreamConnectionTest extends PredisConnectionTestCase
/**
* @group connected
+ * @group relay-incompatible
*/
public function testTcpNodelayParameterDoesNotSetContextFlagWhenFalse()
{
@@ -226,6 +219,7 @@ class PhpiredisStreamConnectionTest extends PredisConnectionTestCase
/**
* @group connected
+ * @group relay-incompatible
*/
public function testTcpDelayContextFlagIsNotSetByDefault()
{
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;
- }
-}
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 */
diff --git a/tests/Predis/Transaction/MultiExecTest.php b/tests/Predis/Transaction/MultiExecTest.php
index 6fa316a2..13430791 100644
--- a/tests/Predis/Transaction/MultiExecTest.php
+++ b/tests/Predis/Transaction/MultiExecTest.php
@@ -724,6 +724,7 @@ class MultiExecTest extends PredisTestCase
/**
* @group connected
+ * @group relay-incompatible
*/
public function testIntegrationReturnsErrorObjectOnRedisErrorInBlock(): void
{
@@ -740,6 +741,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`.