mirror of
https://github.com/predis/predis.git
synced 2026-08-18 09:12:53 +00:00
Compare commits
70 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b240daa106 | |||
| 8fee6ce8c3 | |||
| 35dd44b222 | |||
| 545177f09f | |||
| 2f9337cb9b | |||
| 437d80a7a3 | |||
| 3a14a39d92 | |||
| 5c9457cc2e | |||
| c551fc21f9 | |||
| 0d84606723 | |||
| c021e380d6 | |||
| 5f4b87080f | |||
| 5ae4ac6b49 | |||
| 521ac8f0eb | |||
| fbbef2a0a2 | |||
| 9930e933c6 | |||
| 16957f3b39 | |||
| 9e5371f5ce | |||
| 8ca99f91e4 | |||
| c778843b0d | |||
| dca201291c | |||
| 2e76410e65 | |||
| ca468b785c | |||
| 4a7fb55058 | |||
| fdf663ebba | |||
| 880ad09cad | |||
| 5eccc65d42 | |||
| f225c55a01 | |||
| 8be2418f01 | |||
| b9ebe8a376 | |||
| e2d26926d2 | |||
| 309248042f | |||
| 87452e62d0 | |||
| 31baa9b241 | |||
| 6f942400a1 | |||
| 5e220a0b57 | |||
| 0eb2633348 | |||
| cbbd6bba88 | |||
| 3702f24efc | |||
| 82fefe057b | |||
| 42336537dc | |||
| 802abac55e | |||
| 61e75816ce | |||
| 17f0c08cb6 | |||
| 2b8af1eef2 | |||
| c5f2b441b4 | |||
| 2440a61cba | |||
| 7100884201 | |||
| 2a932d7292 | |||
| 0a6306b73e | |||
| 4363345f7c | |||
| 2ce537d75e | |||
| 7489690306 | |||
| 7376902b20 | |||
| a6bd25412e | |||
| 60cc950a58 | |||
| db82dd9f23 | |||
| 1bc08d9bcc | |||
| 11e4bb44d0 | |||
| cddb849812 | |||
| f2298dd186 | |||
| bceda1d8e6 | |||
| 9f87c849c5 | |||
| 1382146b03 | |||
| cbc08aa5e7 | |||
| de9cd905bb | |||
| 6dd55d7f96 | |||
| 39ff616e86 | |||
| 738ec0c50f | |||
| 1828222e27 |
+5
-2
@@ -1,10 +1,13 @@
|
||||
* text=auto
|
||||
|
||||
/tests export-ignore
|
||||
/tests/PHPUnit export-ignore
|
||||
/tests/Predis export-ignore
|
||||
/tests/bootstrap.php export-ignore
|
||||
/.github export-ignore
|
||||
/.editorconfig export-ignore
|
||||
/.gitattributes export-ignore
|
||||
/.gitignore export-ignore
|
||||
/.php_cs export-ignore
|
||||
/.php_cs.dist export-ignore
|
||||
/.travis.yml export-ignore
|
||||
/phpunit.xml.dist export-ignore
|
||||
/phpunit.xml.travisci export-ignore
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Run command '...'
|
||||
2. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Versions (please complete the following information):**
|
||||
- Predis: [e.g. 1.1.2]
|
||||
- PHP [e.g. 8.0.0]
|
||||
- Redis Server [e.g. 6.0.0]
|
||||
- OS [e.g. Ubuntu 20.10]
|
||||
|
||||
**Code sample**
|
||||
If applicable, a small snippet of code that reproduces the issue.
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
@@ -0,0 +1,20 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: feature
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
@@ -2,6 +2,7 @@
|
||||
*.phar
|
||||
.php-version
|
||||
.php_cs.cache
|
||||
.phpunit.result.cache
|
||||
phpunit.xml
|
||||
package.xml
|
||||
composer.lock
|
||||
|
||||
@@ -9,6 +9,7 @@ branches:
|
||||
before_install:
|
||||
- docker run -d --rm -p 127.0.0.1:6379:6379 redis:3
|
||||
before_script:
|
||||
- phpenv config-rm xdebug.ini
|
||||
- composer self-update
|
||||
- composer install --no-interaction --prefer-source --dev
|
||||
script:
|
||||
@@ -30,3 +31,7 @@ matrix:
|
||||
- php: 7.2
|
||||
- php: 7.3
|
||||
- php: 7.4
|
||||
- php: 8.0
|
||||
- php: nightly
|
||||
allow_failures:
|
||||
- php: nightly
|
||||
|
||||
@@ -1,3 +1,97 @@
|
||||
v1.1.7 (2021-04-04)
|
||||
================================================================================
|
||||
|
||||
- __FIX__: with the phpiredis-based connection backends, failed pipelines led to
|
||||
spurious responses returned after reconnecting to Redis because the underlying
|
||||
reader was not properly reset by discarding buffered replies after disconnecting
|
||||
(ISSUE #363).
|
||||
- __FIX__: removed `cweagans/composer-patches` dev dependency and apply patches
|
||||
using `post-update-cmd` script.
|
||||
|
||||
|
||||
v1.1.6 (2020-09-11)
|
||||
================================================================================
|
||||
|
||||
- __FIX__: reverted support for sentinels authentication implemented in v1.1.5
|
||||
as it was bugged (see ISSUE #658), sorry for the trouble. This is now postponed
|
||||
as it requires a more thorough investigation.
|
||||
|
||||
|
||||
v1.1.5 (2020-09-10)
|
||||
================================================================================
|
||||
|
||||
- __FIX__:~~authentication for sentinels is now supported, previously it was not
|
||||
possible to specify a `password` for sentinels as its value was stripped during
|
||||
initialization because sentinels did not support authentication until Redis 5.
|
||||
**Please note** that with the current implementation each sentinel must have
|
||||
its own `password` parameter set in the parameters list despite this password is
|
||||
the same for all sentinels (read how `requirepass` works on the Redis docs). In
|
||||
this case you should avoid using the global `parameters` client option used to
|
||||
set default parameters for every connection created by Predis as this would end
|
||||
up using the same password even when connecting to actual Redis nodes.~~
|
||||
|
||||
- __FIX__: the username is now correctly retrieved from the userinfo fragment of
|
||||
the URI when using the "redis" scheme and a "username:password" pair is present.
|
||||
Values retrieved from the userinfo fragment always override the ones specified
|
||||
in `username` and `password` if those fields are present in the query string.
|
||||
|
||||
- __FIX__: `Predis\Connection\WebdisConnection` was unable to connect to Webdis
|
||||
when using an IPv4 address in the URL and this is probably due to some change in
|
||||
cURL internals since the last time we tested it.
|
||||
|
||||
- __FIX__: an exception is thrown whe passing `FALSE` or any value evaluating to
|
||||
`FALSE` to the `replication` client option. This was supposed to be unsupported,
|
||||
in fact it actually breaks client initialization and raises a PHP warning. Now
|
||||
the user is alerted with an `InvalidArgumentException` and a proper message.
|
||||
(PR #381).
|
||||
|
||||
|
||||
v1.1.4 (2020-08-31)
|
||||
================================================================================
|
||||
|
||||
- Improved @method annotations for methods responding to Redis commands defined
|
||||
by `Predis\ClientInterface` and `Predis\ClientContextInterface`. (PR #456 and
|
||||
PR #497, other fixes applied after further analysys).
|
||||
|
||||
- __FIX__: the client can now handle ACL authentication when connecting to Redis
|
||||
6.x simply by passing both `username` and `password` to connection parameters.
|
||||
See [the Redis docs](https://redis.io/topics/acl) for details on this topic.
|
||||
|
||||
- __FIX__: NULL or zero-length string values passed to `password` and `database`
|
||||
in the connection parameters list do not trigger spurious `AUTH` and `SELECT`
|
||||
commands anymore when connecting to Redis (ISSUE #436).
|
||||
|
||||
- __FIX__: initializing an iteration over a client instance when it is connected
|
||||
to a standalone Redis server will not throw an exception anymore, instead it
|
||||
will return an iterator that will run for just one loop returning a new client
|
||||
instance using the underlying single-node connection (ISSUE #552, PR #556).
|
||||
|
||||
- __FIX__: `Predis\Cluster\Distributor\HashRingaddNodeToRing()` was calculating
|
||||
the hash required for distribution by using `crc32()` directly instead of the
|
||||
method `Predis\Cluster\Hash\HashGeneratorInterface::hash()` implemented by the
|
||||
class itself. This bug fix does not have any impact on existing clusters that
|
||||
use client-side sharding based on this distributor simply because it does not
|
||||
take any external hash generators so distribution is not going to be affected.
|
||||
|
||||
- __FIX__: `SORT` now always trigger a switch to the master node in replication
|
||||
configurations instead of just when the `STORE` modifier is specified, this is
|
||||
because `SORT` is always considered to be a write operation and actually fails
|
||||
with a `-READONLY` error response when executed against a replica node. (ISSUE
|
||||
#554).
|
||||
|
||||
|
||||
v1.1.3 (2020-08-18)
|
||||
================================================================================
|
||||
|
||||
- Ensure compatibility with PHP 8.
|
||||
|
||||
- Moved repository from `github.com/nrk/predis` to `github.com/predis/predis`.
|
||||
|
||||
- __FIX__: Moved `cweagans/composer-patches` dependency to `require-dev`.
|
||||
|
||||
- __FIX__: Include PHPUnit `.patch` files in exports.
|
||||
|
||||
|
||||
v1.1.2 (2020-08-11)
|
||||
================================================================================
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
## Filing bug reports ##
|
||||
|
||||
Bugs or feature requests can be posted on the [GitHub issues](http://github.com/nrk/predis/issues)
|
||||
Bugs or feature requests can be posted on the [GitHub issues](http://github.com/predis/predis/issues)
|
||||
section of the project.
|
||||
|
||||
When reporting bugs, in addition to the obvious description of your issue you __must__ always provide
|
||||
|
||||
@@ -33,7 +33,7 @@ usually something that developers prefer to customize depending on their needs a
|
||||
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/nrk/predis/issues/29#issuecomment-1202624).
|
||||
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? ###
|
||||
|
||||
|
||||
@@ -5,14 +5,12 @@
|
||||
[![Latest development][ico-version-dev]][link-packagist]
|
||||
[![Monthly installs][ico-downloads-monthly]][link-downloads]
|
||||
[![Build status][ico-travis]][link-travis]
|
||||
[![Gitter room][ico-gitter]][link-gitter]
|
||||
|
||||
Flexible and feature-complete [Redis](http://redis.io) client for PHP >= 5.3 and HHVM >= 2.3.0.
|
||||
|
||||
Predis does not require any additional C extension by default, but it can be optionally paired with
|
||||
[phpiredis](https://github.com/nrk/phpiredis) to lower the overhead of the serialization and parsing
|
||||
of the [Redis RESP Protocol](http://redis.io/topics/protocol). For an __experimental__ asynchronous
|
||||
implementation of the client you can refer to [Predis\Async](https://github.com/nrk/predis-async).
|
||||
of the [Redis RESP Protocol](http://redis.io/topics/protocol).
|
||||
|
||||
More details about this project can be found on the [frequently asked questions](FAQ.md).
|
||||
|
||||
@@ -40,7 +38,7 @@ More details about this project can be found on the [frequently asked questions]
|
||||
This library can be found on [Packagist](http://packagist.org/packages/predis/predis) for an easier
|
||||
management of projects dependencies using [Composer](http://packagist.org/about-composer) or on our
|
||||
[own PEAR channel](http://pear.nrk.io) for a more traditional installation using PEAR. Ultimately,
|
||||
compressed archives of each release are [available on GitHub](https://github.com/nrk/predis/releases).
|
||||
compressed archives of each release are [available on GitHub](https://github.com/predis/predis/releases).
|
||||
|
||||
|
||||
### Loading the library ###
|
||||
@@ -89,6 +87,9 @@ $client = new Predis\Client([
|
||||
$client = new Predis\Client('tcp://10.0.0.1:6379');
|
||||
```
|
||||
|
||||
Password protected servers can be accessed by adding `password` to the parameters set. When ACLs are
|
||||
enabled on Redis >= 6.0, both `username` and `password` are required for user authentication.
|
||||
|
||||
It is also possible to connect to local instances of Redis using UNIX domain sockets, in this case
|
||||
the parameters must use the `unix` scheme and specify a path for the socket file:
|
||||
|
||||
@@ -453,7 +454,7 @@ the development server profile will be used. You can refer to [the tests README]
|
||||
for more detailed information about testing Predis.
|
||||
|
||||
Predis uses Travis CI for continuous integration and the history for past and current builds can be
|
||||
found [on its project page](http://travis-ci.org/nrk/predis).
|
||||
found [on its project page](http://travis-ci.org/predis/predis).
|
||||
|
||||
|
||||
## Other ##
|
||||
@@ -461,9 +462,9 @@ found [on its project page](http://travis-ci.org/nrk/predis).
|
||||
|
||||
### Project related links ###
|
||||
|
||||
- [Source code](https://github.com/nrk/predis)
|
||||
- [Wiki](https://github.com/nrk/predis/wiki)
|
||||
- [Issue tracker](https://github.com/nrk/predis/issues)
|
||||
- [Source code](https://github.com/predis/predis)
|
||||
- [Wiki](https://github.com/predis/predis/wiki)
|
||||
- [Issue tracker](https://github.com/predis/predis/issues)
|
||||
- [PEAR channel](http://pear.nrk.io)
|
||||
|
||||
|
||||
@@ -476,15 +477,13 @@ found [on its project page](http://travis-ci.org/nrk/predis).
|
||||
|
||||
The code for Predis is distributed under the terms of the MIT license (see [LICENSE](LICENSE)).
|
||||
|
||||
[ico-license]: https://img.shields.io/github/license/nrk/predis.svg?style=flat-square
|
||||
[ico-license]: https://img.shields.io/github/license/predis/predis.svg?style=flat-square
|
||||
[ico-version-stable]: https://img.shields.io/packagist/v/predis/predis.svg?style=flat-square
|
||||
[ico-version-dev]: https://img.shields.io/packagist/vpre/predis/predis.svg?style=flat-square
|
||||
[ico-downloads-monthly]: https://img.shields.io/packagist/dm/predis/predis.svg?style=flat-square
|
||||
[ico-travis]: https://img.shields.io/travis/nrk/predis.svg?style=flat-square
|
||||
[ico-travis]: https://img.shields.io/travis/predis/predis.svg?style=flat-square
|
||||
[ico-hhvm]: https://img.shields.io/hhvm/predis/predis.svg?style=flat-square
|
||||
[ico-gitter]: https://img.shields.io/gitter/room/nrk/predis.svg?style=flat-square
|
||||
|
||||
[link-packagist]: https://packagist.org/packages/predis/predis
|
||||
[link-travis]: https://travis-ci.org/nrk/predis
|
||||
[link-travis]: https://travis-ci.org/predis/predis
|
||||
[link-downloads]: https://packagist.org/packages/predis/predis/stats
|
||||
[link-gitter]: https://gitter.im/nrk/predis
|
||||
|
||||
+2
-2
@@ -115,7 +115,7 @@ function addPackageFile($pkg, $fileinfo, $role, $baseDir = '')
|
||||
function generatePackageXml($packageINI)
|
||||
{
|
||||
$XML = <<<XML
|
||||
<?xml version="1.0"?>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<package packagerversion="1.4.10" version="2.0"
|
||||
xmlns="http://pear.php.net/dtd/package-2.0"
|
||||
xmlns:tasks="http://pear.php.net/dtd/tasks-1.0"
|
||||
@@ -197,7 +197,7 @@ function rewritePackageInstallAs($pkg)
|
||||
|
||||
function savePackageXml($xml)
|
||||
{
|
||||
$dom = new DOMDocument("1.0");
|
||||
$dom = new DOMDocument("1.0", "UTF-8");
|
||||
$dom->preserveWhiteSpace = false;
|
||||
$dom->formatOutput = true;
|
||||
$dom->loadXML($xml->asXML());
|
||||
|
||||
+22
-18
@@ -3,21 +3,32 @@
|
||||
"type": "library",
|
||||
"description": "Flexible and feature-complete Redis client for PHP and HHVM",
|
||||
"keywords": ["nosql", "redis", "predis"],
|
||||
"homepage": "http://github.com/nrk/predis",
|
||||
"homepage": "http://github.com/predis/predis",
|
||||
"license": "MIT",
|
||||
"support": {
|
||||
"issues": "https://github.com/nrk/predis/issues"
|
||||
"issues": "https://github.com/predis/predis/issues"
|
||||
},
|
||||
"authors": [
|
||||
{
|
||||
"name": "Daniele Alessandri",
|
||||
"email": "suppakilla@gmail.com",
|
||||
"homepage": "http://clorophilla.net"
|
||||
"homepage": "http://clorophilla.net",
|
||||
"role": "Creator & Maintainer"
|
||||
},
|
||||
{
|
||||
"name": "Till Krüss",
|
||||
"homepage": "https://till.im",
|
||||
"role": "Maintainer"
|
||||
}
|
||||
],
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/tillkruss"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.3.9",
|
||||
"cweagans/composer-patches": "^1.6"
|
||||
"php": ">=5.3.9"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.8"
|
||||
@@ -27,18 +38,11 @@
|
||||
"ext-curl": "Allows access to Webdis when paired with phpiredis"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {"Predis\\": "src/"}
|
||||
"psr-4": {
|
||||
"Predis\\": "src/"
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"composer-exit-on-patch-failure": true,
|
||||
"patches": {
|
||||
"phpunit/phpunit-mock-objects": {
|
||||
"Fix PHP 7 and 8 compatibility": "./tests/phpunit_mock_objects.patch"
|
||||
},
|
||||
"phpunit/phpunit": {
|
||||
"Fix PHP 7 compatibility": "./tests/phpunit_php7.patch",
|
||||
"Fix PHP 8 compatibility": "./tests/phpunit_php8.patch"
|
||||
}
|
||||
}
|
||||
}
|
||||
"scripts": {
|
||||
"post-update-cmd": "@php -f tests/apply-patches.php"
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ name = "Predis"
|
||||
desc = "Flexible and feature-complete Redis client for PHP and HHVM"
|
||||
homepage = "http://github.com/nrk/predis"
|
||||
license = "MIT"
|
||||
version = "1.1.2"
|
||||
version = "1.1.7"
|
||||
stability = "stable"
|
||||
channel = "pear.nrk.io"
|
||||
|
||||
|
||||
@@ -36,10 +36,6 @@
|
||||
</whitelist>
|
||||
</filter>
|
||||
|
||||
<logging>
|
||||
<log type="coverage-text" target="php://stdout" />
|
||||
</logging>
|
||||
|
||||
<php>
|
||||
<!-- Redis -->
|
||||
<const name="REDIS_SERVER_VERSION" value="3.2" />
|
||||
|
||||
+5
-3
@@ -40,7 +40,7 @@ use Predis\Transaction\MultiExec as MultiExecTransaction;
|
||||
*/
|
||||
class Client implements ClientInterface, \IteratorAggregate
|
||||
{
|
||||
const VERSION = '1.1.2';
|
||||
const VERSION = '1.1.7';
|
||||
|
||||
protected $connection;
|
||||
protected $options;
|
||||
@@ -527,7 +527,7 @@ class Client implements ClientInterface, \IteratorAggregate
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @return \Traversable<string, static>
|
||||
*/
|
||||
public function getIterator()
|
||||
{
|
||||
@@ -535,7 +535,9 @@ class Client implements ClientInterface, \IteratorAggregate
|
||||
$connection = $this->getConnection();
|
||||
|
||||
if (!$connection instanceof \Traversable) {
|
||||
throw new ClientException('The underlying connection is not traversable');
|
||||
return new \ArrayIterator(array(
|
||||
(string) $connection => new static($connection, $this->getOptions())
|
||||
));
|
||||
}
|
||||
|
||||
foreach ($connection as $node) {
|
||||
|
||||
@@ -39,6 +39,7 @@ use Predis\Command\CommandInterface;
|
||||
* @method $this bitcount($key, $start = null, $end = null)
|
||||
* @method $this bitop($operation, $destkey, $key)
|
||||
* @method $this bitfield($key, $subcommand, ...$subcommandArg)
|
||||
* @method $this bitpos($key, $bit, $start = null, $end = null)
|
||||
* @method $this decr($key)
|
||||
* @method $this decrby($key, $decrement)
|
||||
* @method $this get($key)
|
||||
@@ -81,7 +82,7 @@ use Predis\Command\CommandInterface;
|
||||
* @method $this llen($key)
|
||||
* @method $this lpop($key)
|
||||
* @method $this lpush($key, array $values)
|
||||
* @method $this lpushx($key, $value)
|
||||
* @method $this lpushx($key, array $values)
|
||||
* @method $this lrange($key, $start, $stop)
|
||||
* @method $this lrem($key, $count, $value)
|
||||
* @method $this lset($key, $index, $value)
|
||||
@@ -89,7 +90,7 @@ use Predis\Command\CommandInterface;
|
||||
* @method $this rpop($key)
|
||||
* @method $this rpoplpush($source, $destination)
|
||||
* @method $this rpush($key, array $values)
|
||||
* @method $this rpushx($key, $value)
|
||||
* @method $this rpushx($key, array $values)
|
||||
* @method $this sadd($key, array $members)
|
||||
* @method $this scard($key)
|
||||
* @method $this sdiff(array|string $keys)
|
||||
@@ -117,7 +118,7 @@ use Predis\Command\CommandInterface;
|
||||
* @method $this zremrangebyrank($key, $start, $stop)
|
||||
* @method $this zremrangebyscore($key, $min, $max)
|
||||
* @method $this zrevrange($key, $start, $stop, array $options = null)
|
||||
* @method $this zrevrangebyscore($key, $min, $max, array $options = null)
|
||||
* @method $this zrevrangebyscore($key, $max, $min, array $options = null)
|
||||
* @method $this zrevrank($key, $member)
|
||||
* @method $this zunionstore($destination, array|string $keys, array $options = null)
|
||||
* @method $this zscore($key, $member)
|
||||
|
||||
+148
-147
@@ -24,153 +24,154 @@ use Predis\Profile\ProfileInterface;
|
||||
* and more friendly interface to ease programming which is described in the
|
||||
* following list of methods:
|
||||
*
|
||||
* @method int del(array|string $keys)
|
||||
* @method string dump($key)
|
||||
* @method int exists($key)
|
||||
* @method int expire($key, $seconds)
|
||||
* @method int expireat($key, $timestamp)
|
||||
* @method array keys($pattern)
|
||||
* @method int move($key, $db)
|
||||
* @method mixed object($subcommand, $key)
|
||||
* @method int persist($key)
|
||||
* @method int pexpire($key, $milliseconds)
|
||||
* @method int pexpireat($key, $timestamp)
|
||||
* @method int pttl($key)
|
||||
* @method string randomkey()
|
||||
* @method mixed rename($key, $target)
|
||||
* @method int renamenx($key, $target)
|
||||
* @method array scan($cursor, array $options = null)
|
||||
* @method array sort($key, array $options = null)
|
||||
* @method int ttl($key)
|
||||
* @method mixed type($key)
|
||||
* @method int append($key, $value)
|
||||
* @method int bitcount($key, $start = null, $end = null)
|
||||
* @method int bitop($operation, $destkey, $key)
|
||||
* @method array bitfield($key, $subcommand, ...$subcommandArg)
|
||||
* @method int decr($key)
|
||||
* @method int decrby($key, $decrement)
|
||||
* @method string get($key)
|
||||
* @method int getbit($key, $offset)
|
||||
* @method string getrange($key, $start, $end)
|
||||
* @method string getset($key, $value)
|
||||
* @method int incr($key)
|
||||
* @method int incrby($key, $increment)
|
||||
* @method string incrbyfloat($key, $increment)
|
||||
* @method array mget(array $keys)
|
||||
* @method mixed mset(array $dictionary)
|
||||
* @method int msetnx(array $dictionary)
|
||||
* @method mixed psetex($key, $milliseconds, $value)
|
||||
* @method mixed set($key, $value, $expireResolution = null, $expireTTL = null, $flag = null)
|
||||
* @method int setbit($key, $offset, $value)
|
||||
* @method int setex($key, $seconds, $value)
|
||||
* @method int setnx($key, $value)
|
||||
* @method int setrange($key, $offset, $value)
|
||||
* @method int strlen($key)
|
||||
* @method int hdel($key, array $fields)
|
||||
* @method int hexists($key, $field)
|
||||
* @method string hget($key, $field)
|
||||
* @method array hgetall($key)
|
||||
* @method int hincrby($key, $field, $increment)
|
||||
* @method string hincrbyfloat($key, $field, $increment)
|
||||
* @method array hkeys($key)
|
||||
* @method int hlen($key)
|
||||
* @method array hmget($key, array $fields)
|
||||
* @method mixed hmset($key, array $dictionary)
|
||||
* @method array hscan($key, $cursor, array $options = null)
|
||||
* @method int hset($key, $field, $value)
|
||||
* @method int hsetnx($key, $field, $value)
|
||||
* @method array hvals($key)
|
||||
* @method int hstrlen($key, $field)
|
||||
* @method array blpop(array|string $keys, $timeout)
|
||||
* @method array brpop(array|string $keys, $timeout)
|
||||
* @method array brpoplpush($source, $destination, $timeout)
|
||||
* @method string lindex($key, $index)
|
||||
* @method int linsert($key, $whence, $pivot, $value)
|
||||
* @method int llen($key)
|
||||
* @method string lpop($key)
|
||||
* @method int lpush($key, array $values)
|
||||
* @method int lpushx($key, $value)
|
||||
* @method array lrange($key, $start, $stop)
|
||||
* @method int lrem($key, $count, $value)
|
||||
* @method mixed lset($key, $index, $value)
|
||||
* @method mixed ltrim($key, $start, $stop)
|
||||
* @method string rpop($key)
|
||||
* @method string rpoplpush($source, $destination)
|
||||
* @method int rpush($key, array $values)
|
||||
* @method int rpushx($key, $value)
|
||||
* @method int sadd($key, array $members)
|
||||
* @method int scard($key)
|
||||
* @method array sdiff(array|string $keys)
|
||||
* @method int sdiffstore($destination, array|string $keys)
|
||||
* @method array sinter(array|string $keys)
|
||||
* @method int sinterstore($destination, array|string $keys)
|
||||
* @method int sismember($key, $member)
|
||||
* @method array smembers($key)
|
||||
* @method int smove($source, $destination, $member)
|
||||
* @method array spop($key, $count = null)
|
||||
* @method string srandmember($key, $count = null)
|
||||
* @method int srem($key, $member)
|
||||
* @method array sscan($key, $cursor, array $options = null)
|
||||
* @method array sunion(array|string $keys)
|
||||
* @method int sunionstore($destination, array|string $keys)
|
||||
* @method int zadd($key, array $membersAndScoresDictionary)
|
||||
* @method int zcard($key)
|
||||
* @method string zcount($key, $min, $max)
|
||||
* @method string zincrby($key, $increment, $member)
|
||||
* @method int zinterstore($destination, array|string $keys, array $options = null)
|
||||
* @method array zrange($key, $start, $stop, array $options = null)
|
||||
* @method array zrangebyscore($key, $min, $max, array $options = null)
|
||||
* @method int zrank($key, $member)
|
||||
* @method int zrem($key, $member)
|
||||
* @method int zremrangebyrank($key, $start, $stop)
|
||||
* @method int zremrangebyscore($key, $min, $max)
|
||||
* @method array zrevrange($key, $start, $stop, array $options = null)
|
||||
* @method array zrevrangebyscore($key, $max, $min, array $options = null)
|
||||
* @method int zrevrank($key, $member)
|
||||
* @method int zunionstore($destination, array|string $keys, array $options = null)
|
||||
* @method string zscore($key, $member)
|
||||
* @method array zscan($key, $cursor, array $options = null)
|
||||
* @method array zrangebylex($key, $start, $stop, array $options = null)
|
||||
* @method array zrevrangebylex($key, $start, $stop, array $options = null)
|
||||
* @method int zremrangebylex($key, $min, $max)
|
||||
* @method int zlexcount($key, $min, $max)
|
||||
* @method int pfadd($key, array $elements)
|
||||
* @method mixed pfmerge($destinationKey, array|string $sourceKeys)
|
||||
* @method int pfcount(array|string $keys)
|
||||
* @method mixed pubsub($subcommand, $argument)
|
||||
* @method int publish($channel, $message)
|
||||
* @method mixed discard()
|
||||
* @method array exec()
|
||||
* @method mixed multi()
|
||||
* @method mixed unwatch()
|
||||
* @method mixed watch($key)
|
||||
* @method mixed eval($script, $numkeys, $keyOrArg1 = null, $keyOrArgN = null)
|
||||
* @method mixed evalsha($script, $numkeys, $keyOrArg1 = null, $keyOrArgN = null)
|
||||
* @method mixed script($subcommand, $argument = null)
|
||||
* @method mixed auth($password)
|
||||
* @method string echo($message)
|
||||
* @method mixed ping($message = null)
|
||||
* @method mixed select($database)
|
||||
* @method mixed bgrewriteaof()
|
||||
* @method mixed bgsave()
|
||||
* @method mixed client($subcommand, $argument = null)
|
||||
* @method mixed config($subcommand, $argument = null)
|
||||
* @method int dbsize()
|
||||
* @method mixed flushall()
|
||||
* @method mixed flushdb()
|
||||
* @method array info($section = null)
|
||||
* @method int lastsave()
|
||||
* @method mixed save()
|
||||
* @method mixed slaveof($host, $port)
|
||||
* @method mixed slowlog($subcommand, $argument = null)
|
||||
* @method array time()
|
||||
* @method array command()
|
||||
* @method int geoadd($key, $longitude, $latitude, $member)
|
||||
* @method array geohash($key, array $members)
|
||||
* @method array geopos($key, array $members)
|
||||
* @method string geodist($key, $member1, $member2, $unit = null)
|
||||
* @method array georadius($key, $longitude, $latitude, $radius, $unit, array $options = null)
|
||||
* @method array georadiusbymember($key, $member, $radius, $unit, array $options = null)
|
||||
* @method int del(array|string $keys)
|
||||
* @method string|null dump($key)
|
||||
* @method int exists($key)
|
||||
* @method int expire($key, $seconds)
|
||||
* @method int expireat($key, $timestamp)
|
||||
* @method array keys($pattern)
|
||||
* @method int move($key, $db)
|
||||
* @method mixed object($subcommand, $key)
|
||||
* @method int persist($key)
|
||||
* @method int pexpire($key, $milliseconds)
|
||||
* @method int pexpireat($key, $timestamp)
|
||||
* @method int pttl($key)
|
||||
* @method string|null randomkey()
|
||||
* @method mixed rename($key, $target)
|
||||
* @method int renamenx($key, $target)
|
||||
* @method array scan($cursor, array $options = null)
|
||||
* @method array sort($key, array $options = null)
|
||||
* @method int ttl($key)
|
||||
* @method mixed type($key)
|
||||
* @method int append($key, $value)
|
||||
* @method int bitcount($key, $start = null, $end = null)
|
||||
* @method int bitop($operation, $destkey, $key)
|
||||
* @method array|null bitfield($key, $subcommand, ...$subcommandArg)
|
||||
* @method int bitpos($key, $bit, $start = null, $end = null)
|
||||
* @method int decr($key)
|
||||
* @method int decrby($key, $decrement)
|
||||
* @method string|null get($key)
|
||||
* @method int getbit($key, $offset)
|
||||
* @method string getrange($key, $start, $end)
|
||||
* @method string|null getset($key, $value)
|
||||
* @method int incr($key)
|
||||
* @method int incrby($key, $increment)
|
||||
* @method string incrbyfloat($key, $increment)
|
||||
* @method array mget(array $keys)
|
||||
* @method mixed mset(array $dictionary)
|
||||
* @method int msetnx(array $dictionary)
|
||||
* @method mixed psetex($key, $milliseconds, $value)
|
||||
* @method mixed set($key, $value, $expireResolution = null, $expireTTL = null, $flag = null)
|
||||
* @method int setbit($key, $offset, $value)
|
||||
* @method int setex($key, $seconds, $value)
|
||||
* @method int setnx($key, $value)
|
||||
* @method int setrange($key, $offset, $value)
|
||||
* @method int strlen($key)
|
||||
* @method int hdel($key, array $fields)
|
||||
* @method int hexists($key, $field)
|
||||
* @method string|null hget($key, $field)
|
||||
* @method array hgetall($key)
|
||||
* @method int hincrby($key, $field, $increment)
|
||||
* @method string hincrbyfloat($key, $field, $increment)
|
||||
* @method array hkeys($key)
|
||||
* @method int hlen($key)
|
||||
* @method array hmget($key, array $fields)
|
||||
* @method mixed hmset($key, array $dictionary)
|
||||
* @method array hscan($key, $cursor, array $options = null)
|
||||
* @method int hset($key, $field, $value)
|
||||
* @method int hsetnx($key, $field, $value)
|
||||
* @method array hvals($key)
|
||||
* @method int hstrlen($key, $field)
|
||||
* @method array|null blpop(array|string $keys, $timeout)
|
||||
* @method array|null brpop(array|string $keys, $timeout)
|
||||
* @method string|null brpoplpush($source, $destination, $timeout)
|
||||
* @method string|null lindex($key, $index)
|
||||
* @method int linsert($key, $whence, $pivot, $value)
|
||||
* @method int llen($key)
|
||||
* @method string|null lpop($key)
|
||||
* @method int lpush($key, array $values)
|
||||
* @method int lpushx($key, array $values)
|
||||
* @method array lrange($key, $start, $stop)
|
||||
* @method int lrem($key, $count, $value)
|
||||
* @method mixed lset($key, $index, $value)
|
||||
* @method mixed ltrim($key, $start, $stop)
|
||||
* @method string|null rpop($key)
|
||||
* @method string|null rpoplpush($source, $destination)
|
||||
* @method int rpush($key, array $values)
|
||||
* @method int rpushx($key, array $values)
|
||||
* @method int sadd($key, array $members)
|
||||
* @method int scard($key)
|
||||
* @method array sdiff(array|string $keys)
|
||||
* @method int sdiffstore($destination, array|string $keys)
|
||||
* @method array sinter(array|string $keys)
|
||||
* @method int sinterstore($destination, array|string $keys)
|
||||
* @method int sismember($key, $member)
|
||||
* @method array smembers($key)
|
||||
* @method int smove($source, $destination, $member)
|
||||
* @method string|null spop($key, $count = null)
|
||||
* @method string|null srandmember($key, $count = null)
|
||||
* @method int srem($key, $member)
|
||||
* @method array sscan($key, $cursor, array $options = null)
|
||||
* @method array sunion(array|string $keys)
|
||||
* @method int sunionstore($destination, array|string $keys)
|
||||
* @method int zadd($key, array $membersAndScoresDictionary)
|
||||
* @method int zcard($key)
|
||||
* @method string zcount($key, $min, $max)
|
||||
* @method string zincrby($key, $increment, $member)
|
||||
* @method int zinterstore($destination, array|string $keys, array $options = null)
|
||||
* @method array zrange($key, $start, $stop, array $options = null)
|
||||
* @method array zrangebyscore($key, $min, $max, array $options = null)
|
||||
* @method int|null zrank($key, $member)
|
||||
* @method int zrem($key, $member)
|
||||
* @method int zremrangebyrank($key, $start, $stop)
|
||||
* @method int zremrangebyscore($key, $min, $max)
|
||||
* @method array zrevrange($key, $start, $stop, array $options = null)
|
||||
* @method array zrevrangebyscore($key, $max, $min, array $options = null)
|
||||
* @method int|null zrevrank($key, $member)
|
||||
* @method int zunionstore($destination, array|string $keys, array $options = null)
|
||||
* @method string|null zscore($key, $member)
|
||||
* @method array zscan($key, $cursor, array $options = null)
|
||||
* @method array zrangebylex($key, $start, $stop, array $options = null)
|
||||
* @method array zrevrangebylex($key, $start, $stop, array $options = null)
|
||||
* @method int zremrangebylex($key, $min, $max)
|
||||
* @method int zlexcount($key, $min, $max)
|
||||
* @method int pfadd($key, array $elements)
|
||||
* @method mixed pfmerge($destinationKey, array|string $sourceKeys)
|
||||
* @method int pfcount(array|string $keys)
|
||||
* @method mixed pubsub($subcommand, $argument)
|
||||
* @method int publish($channel, $message)
|
||||
* @method mixed discard()
|
||||
* @method array|null exec()
|
||||
* @method mixed multi()
|
||||
* @method mixed unwatch()
|
||||
* @method mixed watch($key)
|
||||
* @method mixed eval($script, $numkeys, $keyOrArg1 = null, $keyOrArgN = null)
|
||||
* @method mixed evalsha($script, $numkeys, $keyOrArg1 = null, $keyOrArgN = null)
|
||||
* @method mixed script($subcommand, $argument = null)
|
||||
* @method mixed auth($password)
|
||||
* @method string echo($message)
|
||||
* @method mixed ping($message = null)
|
||||
* @method mixed select($database)
|
||||
* @method mixed bgrewriteaof()
|
||||
* @method mixed bgsave()
|
||||
* @method mixed client($subcommand, $argument = null)
|
||||
* @method mixed config($subcommand, $argument = null)
|
||||
* @method int dbsize()
|
||||
* @method mixed flushall()
|
||||
* @method mixed flushdb()
|
||||
* @method array info($section = null)
|
||||
* @method int lastsave()
|
||||
* @method mixed save()
|
||||
* @method mixed slaveof($host, $port)
|
||||
* @method mixed slowlog($subcommand, $argument = null)
|
||||
* @method array time()
|
||||
* @method array command()
|
||||
* @method int geoadd($key, $longitude, $latitude, $member)
|
||||
* @method array geohash($key, array $members)
|
||||
* @method array geopos($key, array $members)
|
||||
* @method string|null geodist($key, $member1, $member2, $unit = null)
|
||||
* @method array georadius($key, $longitude, $latitude, $radius, $unit, array $options = null)
|
||||
* @method array georadiusbymember($key, $member, $radius, $unit, array $options = null)
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
|
||||
@@ -161,7 +161,7 @@ class HashRing implements DistributorInterface, HashGeneratorInterface
|
||||
$replicas = (int) round($weightRatio * $totalNodes * $replicas);
|
||||
|
||||
for ($i = 0; $i < $replicas; ++$i) {
|
||||
$key = crc32("$nodeHash:$i");
|
||||
$key = $this->hash("$nodeHash:$i");
|
||||
$ring[$key] = $nodeObject;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ class ProcessorChain implements \ArrayAccess, ProcessorInterface
|
||||
/**
|
||||
* Returns an iterator over the list of command processor in the chain.
|
||||
*
|
||||
* @return \ArrayIterator
|
||||
* @return \Traversable<int, ProcessorInterface>
|
||||
*/
|
||||
public function getIterator()
|
||||
{
|
||||
@@ -89,7 +89,7 @@ class ProcessorChain implements \ArrayAccess, ProcessorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @return bool
|
||||
*/
|
||||
public function offsetExists($index)
|
||||
{
|
||||
|
||||
@@ -36,10 +36,6 @@ class ReplicationOption implements OptionInterface
|
||||
return $value;
|
||||
}
|
||||
|
||||
if (is_bool($value) || $value === null) {
|
||||
return $value ? $this->getDefault($options) : null;
|
||||
}
|
||||
|
||||
if ($value === 'sentinel') {
|
||||
return function ($sentinels, $options) {
|
||||
return new SentinelReplication($options->service, $sentinels, $options->connections);
|
||||
@@ -50,7 +46,13 @@ class ReplicationOption implements OptionInterface
|
||||
!is_object($value) &&
|
||||
null !== $asbool = filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE)
|
||||
) {
|
||||
return $asbool ? $this->getDefault($options) : null;
|
||||
if (true === $asbool) {
|
||||
return $this->getDefault($options);
|
||||
} else {
|
||||
throw new \InvalidArgumentException(
|
||||
"Values evaluating to FALSE are not accepted for `replication`"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException(
|
||||
|
||||
@@ -176,7 +176,7 @@ class PredisCluster implements ClusterInterface, \IteratorAggregate, \Countable
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @return int
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
@@ -184,7 +184,7 @@ class PredisCluster implements ClusterInterface, \IteratorAggregate, \Countable
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @return \Traversable<string|int, NodeConnectionInterface>
|
||||
*/
|
||||
public function getIterator()
|
||||
{
|
||||
|
||||
@@ -600,7 +600,7 @@ class RedisCluster implements ClusterInterface, \IteratorAggregate, \Countable
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @return int
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
@@ -608,7 +608,7 @@ class RedisCluster implements ClusterInterface, \IteratorAggregate, \Countable
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @return \Traversable<int, NodeConnectionInterface>
|
||||
*/
|
||||
public function getIterator()
|
||||
{
|
||||
|
||||
@@ -146,14 +146,14 @@ class SentinelReplication implements ReplicationInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the time to wait (in seconds) before fetching a new configuration
|
||||
* Sets the time to wait (in milliseconds) before fetching a new configuration
|
||||
* from one of the sentinels.
|
||||
*
|
||||
* @param float $seconds Time to wait before the next attempt.
|
||||
* @param float $milliseconds Time to wait before the next attempt.
|
||||
*/
|
||||
public function setRetryWait($seconds)
|
||||
public function setRetryWait($milliseconds)
|
||||
{
|
||||
$this->retryWait = (float) $seconds;
|
||||
$this->retryWait = (float) $milliseconds;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -239,9 +239,14 @@ class SentinelReplication implements ReplicationInterface
|
||||
}
|
||||
|
||||
if (is_array($parameters)) {
|
||||
// We explicitly set "database" and "password" to null,
|
||||
// so that no AUTH and SELECT command is send to the sentinels.
|
||||
// NOTE: sentinels do not accept AUTH and SELECT commands so we must
|
||||
// explicitly set them to NULL to avoid problems when using default
|
||||
// parameters set via client options. Actually AUTH is supported for
|
||||
// sentinels starting with Redis 5 but we have to differentiate from
|
||||
// sentinels passwords and nodes passwords, this will be implemented
|
||||
// in a later release.
|
||||
$parameters['database'] = null;
|
||||
$parameters['username'] = null;
|
||||
$parameters['password'] = null;
|
||||
|
||||
if (!isset($parameters['timeout'])) {
|
||||
|
||||
@@ -173,13 +173,17 @@ class Factory implements FactoryInterface
|
||||
{
|
||||
$parameters = $connection->getParameters();
|
||||
|
||||
if (isset($parameters->password)) {
|
||||
if (isset($parameters->password) && strlen($parameters->password)) {
|
||||
$cmdAuthArgs = isset($parameters->username) && strlen($parameters->username)
|
||||
? array('AUTH', $parameters->username, $parameters->password)
|
||||
: array('AUTH', $parameters->password);
|
||||
|
||||
$connection->addConnectCommand(
|
||||
new RawCommand(array('AUTH', $parameters->password))
|
||||
new RawCommand($cmdAuthArgs)
|
||||
);
|
||||
}
|
||||
|
||||
if (isset($parameters->database)) {
|
||||
if (isset($parameters->database) && strlen($parameters->database)) {
|
||||
$connection->addConnectCommand(
|
||||
new RawCommand(array('SELECT', $parameters->database))
|
||||
);
|
||||
|
||||
@@ -109,8 +109,17 @@ class Parameters implements ParametersInterface
|
||||
}
|
||||
|
||||
if (stripos($uri, 'redis') === 0) {
|
||||
if (isset($parsed['user'])) {
|
||||
if (strlen($parsed['user'])) {
|
||||
$parsed['username'] = $parsed['user'];
|
||||
}
|
||||
unset($parsed['user']);
|
||||
}
|
||||
|
||||
if (isset($parsed['pass'])) {
|
||||
$parsed['password'] = $parsed['pass'];
|
||||
if (strlen($parsed['pass'])) {
|
||||
$parsed['password'] = $parsed['pass'];
|
||||
}
|
||||
unset($parsed['pass']);
|
||||
}
|
||||
|
||||
|
||||
@@ -66,9 +66,9 @@ class PhpiredisSocketConnection extends AbstractConnection
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
phpiredis_reader_destroy($this->reader);
|
||||
|
||||
parent::__destruct();
|
||||
|
||||
phpiredis_reader_destroy($this->reader);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -227,9 +227,7 @@ class PhpiredisSocketConnection extends AbstractConnection
|
||||
$protocol = SOL_TCP;
|
||||
}
|
||||
|
||||
$socket = @socket_create($domain, SOCK_STREAM, $protocol);
|
||||
|
||||
if (!is_resource($socket)) {
|
||||
if (false === $socket = @socket_create($domain, SOCK_STREAM, $protocol)) {
|
||||
$this->emitSocketError();
|
||||
}
|
||||
|
||||
@@ -344,7 +342,9 @@ class PhpiredisSocketConnection extends AbstractConnection
|
||||
public function disconnect()
|
||||
{
|
||||
if ($this->isConnected()) {
|
||||
phpiredis_reader_reset($this->reader);
|
||||
socket_close($this->getResource());
|
||||
|
||||
parent::disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,9 +67,19 @@ class PhpiredisStreamConnection extends StreamConnection
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
phpiredis_reader_destroy($this->reader);
|
||||
|
||||
parent::__destruct();
|
||||
|
||||
phpiredis_reader_destroy($this->reader);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function disconnect()
|
||||
{
|
||||
phpiredis_reader_reset($this->reader);
|
||||
|
||||
parent::disconnect();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -87,9 +97,23 @@ class PhpiredisStreamConnection extends StreamConnection
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function assertSslSupport(ParametersInterface $parameters)
|
||||
protected function assertParameters(ParametersInterface $parameters)
|
||||
{
|
||||
throw new \InvalidArgumentException('SSL encryption is not supported by this connection backend.');
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -119,7 +119,7 @@ class WebdisConnection implements NodeConnectionInterface
|
||||
$parameters = $this->getParameters();
|
||||
$timeout = (isset($parameters->timeout) ? (float) $parameters->timeout : 5.0) * 1000;
|
||||
|
||||
if (filter_var($host = $parameters->host, FILTER_VALIDATE_IP)) {
|
||||
if (filter_var($host = $parameters->host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
|
||||
$host = "[$host]";
|
||||
}
|
||||
|
||||
|
||||
@@ -89,31 +89,6 @@ class ReplicationStrategy
|
||||
return isset($this->disallowed[$command->getId()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a SORT command is a readable operation by parsing the arguments
|
||||
* array of the specified commad instance.
|
||||
*
|
||||
* @param CommandInterface $command Command instance.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function isSortReadOnly(CommandInterface $command)
|
||||
{
|
||||
$arguments = $command->getArguments();
|
||||
$argc = count($arguments);
|
||||
|
||||
if ($argc > 1) {
|
||||
for ($i = 1; $i < $argc; ++$i) {
|
||||
$argument = strtoupper($arguments[$i]);
|
||||
if ($argument === 'STORE') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if BITFIELD performs a read-only operation by looking for certain
|
||||
* SET and INCRYBY modifiers in the arguments array of the command.
|
||||
@@ -292,7 +267,6 @@ class ReplicationStrategy
|
||||
'BITPOS' => true,
|
||||
'TIME' => true,
|
||||
'PFCOUNT' => true,
|
||||
'SORT' => array($this, 'isSortReadOnly'),
|
||||
'BITFIELD' => array($this, 'isBitfieldReadOnly'),
|
||||
'GEOHASH' => true,
|
||||
'GEOPOS' => true,
|
||||
|
||||
@@ -337,4 +337,16 @@ abstract class PredisTestCase extends \PHPUnit_Framework_TestCase
|
||||
|
||||
$this->checkRequiredRedisServerVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks current test skipped when test suite is running on CI environments.
|
||||
*
|
||||
* @param string $message
|
||||
*/
|
||||
protected function markTestSkippedOnCIEnvironment($message = 'Test skipped on CI environment')
|
||||
{
|
||||
if (getenv('GITHUB_ACTIONS') || getenv('TRAVIS')) {
|
||||
$this->markTestSkipped($message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -853,15 +853,17 @@ class ClientTest extends PredisTestCase
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
* @expectedException \Predis\ClientException
|
||||
* @expectedExceptionMessage The underlying connection is not traversable
|
||||
*/
|
||||
public function testGetIteratorWithNonTraversableConnectionThrowsException()
|
||||
public function testGetIteratorWithNonTraversableConnectionNoException()
|
||||
{
|
||||
$connection = $this->getMock('Predis\Connection\NodeConnectionInterface');
|
||||
$connection = $this->getMockConnection('tcp://127.0.0.1:6381');
|
||||
$client = new Client($connection);
|
||||
|
||||
$client->getIterator();
|
||||
$iterator = $client->getIterator();
|
||||
|
||||
$this->assertInstanceOf('\Predis\Client', $nodeClient = $iterator->current());
|
||||
$this->assertSame($connection, $nodeClient->getConnection());
|
||||
$this->assertSame('127.0.0.1:6381', $iterator->key());
|
||||
}
|
||||
|
||||
// ******************************************************************** //
|
||||
|
||||
@@ -57,8 +57,8 @@ class HashKeyTest extends PredisTestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @link https://github.com/nrk/predis/pull/330
|
||||
* @link https://github.com/nrk/predis/issues/331
|
||||
* @see https://github.com/predis/predis/pull/330
|
||||
* @see https://github.com/predis/predis/issues/331
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testIterationWithIntegerFields()
|
||||
|
||||
@@ -57,7 +57,7 @@ class SortedSetKeyTest extends PredisTestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @link https://github.com/nrk/predis/issues/216
|
||||
* @see https://github.com/predis/predis/issues/216
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testIterationWithIntegerMembers()
|
||||
|
||||
@@ -83,7 +83,7 @@ class ConnectionSelectTest extends PredisCommandTestCase
|
||||
/**
|
||||
* @group connected
|
||||
* @expectedException \Predis\Response\ServerException
|
||||
* @expectedExceptionMessage ERR invalid DB index
|
||||
* @expectedExceptionMessageRegExp /ERR (invalid DB index|value is not)/
|
||||
*/
|
||||
public function testThrowsExceptionOnUnexpectedDatabaseName()
|
||||
{
|
||||
|
||||
@@ -82,7 +82,7 @@ class KeyMoveTest extends PredisCommandTestCase
|
||||
/**
|
||||
* @group connected
|
||||
* @expectedException \Predis\Response\ServerException
|
||||
* @expectedExceptionMessage ERR index out of range
|
||||
* @expectedExceptionMessageRegEx /ERR.*out of range/
|
||||
*/
|
||||
public function testThrowsExceptionOnInvalidDatabases()
|
||||
{
|
||||
|
||||
@@ -102,13 +102,24 @@ class ServerCommandTest extends PredisCommandTestCase
|
||||
{
|
||||
$redis = $this->getClient();
|
||||
|
||||
$expected = array(array('get', 2, array('readonly', 'fast'), 1, 1, 1));
|
||||
|
||||
// NOTE: starting with Redis 6.0 and the introduction of Access Control
|
||||
// Lists, COMMAND INFO returns an additional array for each specified
|
||||
// command in yhe request with a list of the ACL categories associated
|
||||
// to a command. We simply append this additional array in the expected
|
||||
// response if the test suite is executed against Redis >= 6.0.
|
||||
if ($this->isRedisServerVersion('>=', '6.0')) {
|
||||
$expected[0][] = array('@read', '@string', '@fast');
|
||||
}
|
||||
|
||||
$this->assertCount(1, $response = $redis->command('INFO', 'GET'));
|
||||
|
||||
// NOTE: we use assertEquals instead of assertSame because Redis returns
|
||||
// flags as +STATUS responses, represented by Predis with instances of
|
||||
// Predis\Response\Status instead of plain strings. This class responds
|
||||
// to __toString() so the string conversion is implicit, but assertSame
|
||||
// checks for strict equality while assertEquals is loose.
|
||||
$expected = array(array('get', 2, array('readonly', 'fast'), 1, 1, 1));
|
||||
$this->assertCount(1, $response = $redis->command('INFO', 'GET'));
|
||||
$this->assertEquals($expected, $response);
|
||||
}
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ class StringIncrementByFloatTest extends PredisCommandTestCase
|
||||
$redis->set('foo', 2);
|
||||
|
||||
// We use round() to avoid errors on some platforms, see the following
|
||||
// issue https://github.com/nrk/predis/issues/220 for reference.
|
||||
// issue https://github.com/predis/predis/issues/220 for reference.
|
||||
$this->assertEquals(22.123, $redis->incrbyfloat('foo', 20.123));
|
||||
$this->assertEquals(10, round($redis->incrbyfloat('foo', -12.123), 5));
|
||||
$this->assertEquals(-100.01, round($redis->incrbyfloat('foo', -110.01), 5));
|
||||
|
||||
@@ -31,26 +31,49 @@ class ReplicationOptionTest extends PredisTestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
* @return array
|
||||
*/
|
||||
public function testAcceptsValuesThatCanBeInterpretedAsBooleans()
|
||||
public function provideValuesEvaluatingTrue()
|
||||
{
|
||||
return array(array(true), array(1), array('true'), array('on'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
* @dataProvider provideValuesEvaluatingTrue
|
||||
*/
|
||||
public function testAcceptsValuesThatCanBeInterpretedAsBooleanTrue($value)
|
||||
{
|
||||
$option = new ReplicationOption();
|
||||
$options = $this->getMock('Predis\Configuration\OptionsInterface');
|
||||
|
||||
$this->assertNull($option->filter($options, null));
|
||||
$this->assertInstanceOf('Predis\Connection\Aggregate\MasterSlaveReplication', $option->filter($options, $value));
|
||||
}
|
||||
|
||||
$this->assertInstanceOf('Predis\Connection\Aggregate\ReplicationInterface', $option->filter($options, true));
|
||||
$this->assertNull($option->filter($options, false));
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function provideValuesEvaluatingFalse()
|
||||
{
|
||||
return array(array(false), array(0), array('false'), array('off'));
|
||||
}
|
||||
|
||||
$this->assertInstanceOf('Predis\Connection\Aggregate\ReplicationInterface', $option->filter($options, 1));
|
||||
$this->assertNull($option->filter($options, 0));
|
||||
/**
|
||||
* @group disconnected
|
||||
* @dataProvider provideValuesEvaluatingFalse
|
||||
* @expectedException \InvalidArgumentException
|
||||
* @expectedExceptionMessage Values evaluating to FALSE are not accepted for `replication`
|
||||
*/
|
||||
public function testDoesNotAcceptValuesThatCanBeInterpretedAsBooleanFalse($value)
|
||||
{
|
||||
if (version_compare(PHP_VERSION, '5.4', '<')) {
|
||||
$this->markTestSkipped('Skip test, because.');
|
||||
}
|
||||
|
||||
$this->assertInstanceOf('Predis\Connection\Aggregate\ReplicationInterface', $option->filter($options, 'true'));
|
||||
$this->assertNull($option->filter($options, 'false'));
|
||||
$option = new ReplicationOption();
|
||||
$options = $this->getMock('Predis\Configuration\OptionsInterface');
|
||||
|
||||
$this->assertInstanceOf('Predis\Connection\Aggregate\ReplicationInterface', $option->filter($options, 'on'));
|
||||
$this->assertNull($option->filter($options, 'off'));
|
||||
$option->filter($options, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -541,29 +541,6 @@ class MasterSlaveReplicationTest extends PredisTestCase
|
||||
$replication->executeCommand($cmdEval);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testSortTriggersSwitchToMasterConnectionOnStoreModifier()
|
||||
{
|
||||
$profile = Profile\Factory::get('dev');
|
||||
$cmdSortNormal = $profile->createCommand('sort', array('key'));
|
||||
$cmdSortStore = $profile->createCommand('sort', array('key', array('store' => 'key:store')));
|
||||
|
||||
$master = $this->getMockConnection('tcp://host1?alias=master');
|
||||
$master->expects($this->once())->method('executeCommand')->with($cmdSortStore);
|
||||
|
||||
$slave1 = $this->getMockConnection('tcp://host2?alias=slave1');
|
||||
$slave1->expects($this->once())->method('executeCommand')->with($cmdSortNormal);
|
||||
|
||||
$replication = new MasterSlaveReplication();
|
||||
$replication->add($master);
|
||||
$replication->add($slave1);
|
||||
|
||||
$replication->executeCommand($cmdSortNormal);
|
||||
$replication->executeCommand($cmdSortStore);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
|
||||
@@ -36,15 +36,19 @@ class SentinelReplicationTest extends PredisTestCase
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testParametersForSentinelConnectionShouldNotUseDatabaseAndPassword()
|
||||
public function testParametersForSentinelConnectionShouldNotUseDatabaseAndUsernameAndPassword()
|
||||
{
|
||||
$replication = $this->getReplicationConnection('svc', array(
|
||||
'tcp://127.0.0.1:5381?alias=sentinel1&database=1&password=secret',
|
||||
'tcp://127.0.0.1:5381?alias=sentinel1&database=1&username=myusername&password=secret',
|
||||
));
|
||||
|
||||
$parameters = $replication->getSentinelConnection()->getParameters()->toArray();
|
||||
|
||||
$this->assertArraySubset(array('database' => null, 'password' => null), $parameters);
|
||||
$this->assertArraySubset(array(
|
||||
'database' => null,
|
||||
'username' => null,
|
||||
'password' => null
|
||||
), $parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -280,8 +280,6 @@ class FactoryTest extends PredisTestCase
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*
|
||||
* @todo This test smells but there's no other way around it right now.
|
||||
*/
|
||||
public function testCreateConnectionWithInitializationCommands()
|
||||
{
|
||||
@@ -303,6 +301,111 @@ class FactoryTest extends PredisTestCase
|
||||
|
||||
$factory = new Factory();
|
||||
|
||||
// TODO: using reflection to make a protected method accessible :facepalm:
|
||||
$reflection = new \ReflectionObject($factory);
|
||||
$prepareConnection = $reflection->getMethod('prepareConnection');
|
||||
$prepareConnection->setAccessible(true);
|
||||
$prepareConnection->invoke($factory, $connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testCreateConnectionWithPasswordAndNoUsernameAddsInitializationCommandAuthWithOneArgument()
|
||||
{
|
||||
$parameters = new Parameters(array(
|
||||
'password' => 'foobar',
|
||||
));
|
||||
|
||||
$connection = $this->getMock('Predis\Connection\NodeConnectionInterface');
|
||||
$connection->expects($this->once())
|
||||
->method('getParameters')
|
||||
->will($this->returnValue($parameters));
|
||||
$connection->expects($this->once(1))
|
||||
->method('addConnectCommand')
|
||||
->with($this->isRedisCommand('AUTH', array('foobar')));
|
||||
|
||||
$factory = new Factory();
|
||||
|
||||
// TODO: using reflection to make a protected method accessible :facepalm:
|
||||
$reflection = new \ReflectionObject($factory);
|
||||
$prepareConnection = $reflection->getMethod('prepareConnection');
|
||||
$prepareConnection->setAccessible(true);
|
||||
$prepareConnection->invoke($factory, $connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testCreateConnectionWithPasswordAndUsernameAddsInitializationCommandAuthWithTwoArguments()
|
||||
{
|
||||
$parameters = new Parameters(array(
|
||||
'username' => 'myusername',
|
||||
'password' => 'foobar',
|
||||
));
|
||||
|
||||
$connection = $this->getMock('Predis\Connection\NodeConnectionInterface');
|
||||
$connection->expects($this->once())
|
||||
->method('getParameters')
|
||||
->will($this->returnValue($parameters));
|
||||
$connection->expects($this->once(1))
|
||||
->method('addConnectCommand')
|
||||
->with($this->isRedisCommand('AUTH', array('myusername', 'foobar')));
|
||||
|
||||
$factory = new Factory();
|
||||
|
||||
// TODO: using reflection to make a protected method accessible :facepalm:
|
||||
$reflection = new \ReflectionObject($factory);
|
||||
$prepareConnection = $reflection->getMethod('prepareConnection');
|
||||
$prepareConnection->setAccessible(true);
|
||||
$prepareConnection->invoke($factory, $connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testCreateConnectionWithUsernameAndNoPasswordDoesNotAddInitializationCommands()
|
||||
{
|
||||
$parameters = new Parameters(array(
|
||||
'username' => 'myusername',
|
||||
));
|
||||
|
||||
$connection = $this->getMock('Predis\Connection\NodeConnectionInterface');
|
||||
$connection->expects($this->once())
|
||||
->method('getParameters')
|
||||
->will($this->returnValue($parameters));
|
||||
$connection->expects($this->never())
|
||||
->method('addConnectCommand');
|
||||
|
||||
$factory = new Factory();
|
||||
|
||||
// TODO: using reflection to make a protected method accessible :facepalm:
|
||||
$reflection = new \ReflectionObject($factory);
|
||||
$prepareConnection = $reflection->getMethod('prepareConnection');
|
||||
$prepareConnection->setAccessible(true);
|
||||
$prepareConnection->invoke($factory, $connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
* @dataProvider provideEmptyParametersForInitializationCommands
|
||||
*/
|
||||
public function testCreateConnectionWithEmptyParametersDoesNotAddInitializationCommands($parameter, $value)
|
||||
{
|
||||
$parameters = new Parameters(array(
|
||||
$parameter => $value,
|
||||
));
|
||||
|
||||
$connection = $this->getMock('Predis\Connection\NodeConnectionInterface');
|
||||
$connection->expects($this->once())
|
||||
->method('getParameters')
|
||||
->will($this->returnValue($parameters));
|
||||
$connection->expects($this->never())
|
||||
->method('addConnectCommand');
|
||||
|
||||
$factory = new Factory();
|
||||
|
||||
// TODO: using reflection to make a protected method accessible :facepalm:
|
||||
$reflection = new \ReflectionObject($factory);
|
||||
$prepareConnection = $reflection->getMethod('prepareConnection');
|
||||
$prepareConnection->setAccessible(true);
|
||||
@@ -487,4 +590,28 @@ class FactoryTest extends PredisTestCase
|
||||
|
||||
return array($connection, get_class($connection));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides empty values for specific parameters.
|
||||
*
|
||||
* These parameters usually trigger the addition of initializatin commands
|
||||
* to connection instances like `password` => AUTH and `database` => SELECT,
|
||||
* but they should not be added when their values are NULL or empty strings.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function provideEmptyParametersForInitializationCommands()
|
||||
{
|
||||
return array(
|
||||
// AUTH
|
||||
array('username', ''),
|
||||
array('username', null),
|
||||
array('password', ''),
|
||||
array('password', null),
|
||||
|
||||
// SELECT
|
||||
array('database', ''),
|
||||
array('database', null),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,7 +156,7 @@ class ParametersTest extends PredisTestCase
|
||||
*/
|
||||
public function testParsingURIWithRedisScheme()
|
||||
{
|
||||
$uri = 'redis://:secret@10.10.10.10:6400/5?timeout=0.5&persistent=1';
|
||||
$uri = 'redis://predis:secret@10.10.10.10:6400/5?timeout=0.5&persistent=1';
|
||||
|
||||
$expected = array(
|
||||
'scheme' => 'redis',
|
||||
@@ -164,20 +164,48 @@ class ParametersTest extends PredisTestCase
|
||||
'port' => 6400,
|
||||
'timeout' => '0.5',
|
||||
'persistent' => '1',
|
||||
'username' => 'predis',
|
||||
'password' => 'secret',
|
||||
'database' => '5',
|
||||
);
|
||||
|
||||
$parameters = Parameters::parse($uri);
|
||||
|
||||
// TODO: parse_url() in PHP >= 5.6 returns an empty "user" entry in the
|
||||
// dictionary when no username has been provided in the URI string. This
|
||||
// actually makes sense, but let's keep the test ugly & simple for now.
|
||||
unset($parameters['user']);
|
||||
|
||||
$this->assertSame($expected, $parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testRedisSchemeOverridesUsernameAndPasswordInQueryString()
|
||||
{
|
||||
$parameters = Parameters::parse('redis://predis:secret@10.10.10.10/5?username=ignored&password=ignored');
|
||||
|
||||
$this->assertSame('predis', $parameters['username']);
|
||||
$this->assertSame('secret', $parameters['password']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testRedisSchemeDoesNotOverridesUsernameAndPasswordInQueryStringOnEmptyAuthFragment()
|
||||
{
|
||||
$parameters = Parameters::parse('redis://:@10.10.10.10/5?username=predis&password=secret');
|
||||
|
||||
$this->assertSame('predis', $parameters['username']);
|
||||
$this->assertSame('secret', $parameters['password']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testRedisSchemeOverridesDatabaseInQueryString()
|
||||
{
|
||||
$parameters = Parameters::parse('redis://10.10.10.10/5?database=10');
|
||||
|
||||
$this->assertSame('5', $parameters['database']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
@@ -197,17 +225,6 @@ class ParametersTest extends PredisTestCase
|
||||
$this->assertSame($expected, $parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testRedisSchemeOverridesPasswordAndDatabaseInQueryString()
|
||||
{
|
||||
$parameters = Parameters::parse('redis://:secret@10.10.10.10/5?password=ignored&database=4');
|
||||
|
||||
$this->assertSame('secret', $parameters['password']);
|
||||
$this->assertSame('5', $parameters['database']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
|
||||
@@ -76,6 +76,28 @@ class PhpiredisSocketConnectionTest extends PredisConnectionTestCase
|
||||
// ---- INTEGRATION TESTS --------------------------------------------- //
|
||||
// ******************************************************************** //
|
||||
|
||||
/**
|
||||
* @group connected
|
||||
*/
|
||||
public function testClearsPendingResponsesInReaderBufferOnDisconnect()
|
||||
{
|
||||
$profile = $this->getCurrentProfile();
|
||||
$connection = $this->createConnection();
|
||||
|
||||
$cmdECHOBefore = $profile->createCommand('echo', array('BEFORE DISCONNECT'));
|
||||
$cmdECHOAfter = $profile->createCommand('echo', array('AFTER DISCONNECT'));
|
||||
|
||||
$connection->writeRequest($cmdECHOBefore);
|
||||
$connection->writeRequest($cmdECHOBefore);
|
||||
$connection->writeRequest($cmdECHOBefore);
|
||||
$connection->readResponse($cmdECHOBefore);
|
||||
$connection->disconnect();
|
||||
|
||||
$response = $connection->executeCommand($cmdECHOAfter);
|
||||
|
||||
$this->assertSame('AFTER DISCONNECT', $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group connected
|
||||
* @expectedException \Predis\Connection\ConnectionException
|
||||
|
||||
@@ -76,6 +76,28 @@ class PhpiredisStreamConnectionTest extends PredisConnectionTestCase
|
||||
// ---- INTEGRATION TESTS --------------------------------------------- //
|
||||
// ******************************************************************** //
|
||||
|
||||
/**
|
||||
* @group connected
|
||||
*/
|
||||
public function testClearsPendingResponsesInReaderBufferOnDisconnect()
|
||||
{
|
||||
$profile = $this->getCurrentProfile();
|
||||
$connection = $this->createConnection();
|
||||
|
||||
$cmdECHOBefore = $profile->createCommand('echo', array('BEFORE DISCONNECT'));
|
||||
$cmdECHOAfter = $profile->createCommand('echo', array('AFTER DISCONNECT'));
|
||||
|
||||
$connection->writeRequest($cmdECHOBefore);
|
||||
$connection->writeRequest($cmdECHOBefore);
|
||||
$connection->writeRequest($cmdECHOBefore);
|
||||
$connection->readResponse($cmdECHOBefore);
|
||||
$connection->disconnect();
|
||||
|
||||
$response = $connection->executeCommand($cmdECHOAfter);
|
||||
|
||||
$this->assertSame('AFTER DISCONNECT', $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group connected
|
||||
* @group slow
|
||||
|
||||
@@ -297,11 +297,25 @@ class ConsumerTest extends PredisTestCase
|
||||
// ---- INTEGRATION TESTS --------------------------------------------- //
|
||||
// ******************************************************************** //
|
||||
|
||||
// NOTE: the following 2 tests fail at random without any apparent reason
|
||||
// when executed on our CI environments and these failures are not tied
|
||||
// to a particular version of PHP or Redis. It is most likely some weird
|
||||
// timing issue on busy systems as it is really rare to get it triggered
|
||||
// locally. The chances it is a bug in the library are pretty low so for
|
||||
// now we just mark this test skipped on our CI environments (but still
|
||||
// enabled for local test runs) and "debug" this issue using a separate
|
||||
// branch to avoid having spurious failures on main development branches
|
||||
// which is utterly annoying.
|
||||
|
||||
/**
|
||||
* @group connected
|
||||
*/
|
||||
public function testPubSubAgainstRedisServer()
|
||||
{
|
||||
$this->markTestSkippedOnCIEnvironment(
|
||||
'Test temporarily skipped on CI environments, see note in the body of the test' // TODO
|
||||
);
|
||||
|
||||
$parameters = array(
|
||||
'host' => REDIS_SERVER_HOST,
|
||||
'port' => REDIS_SERVER_PORT,
|
||||
@@ -347,6 +361,10 @@ class ConsumerTest extends PredisTestCase
|
||||
*/
|
||||
public function testPubSubAgainstRedisServerBlocking()
|
||||
{
|
||||
$this->markTestSkippedOnCIEnvironment(
|
||||
'Test temporarily skipped on CI environments, see note in the body of the test' // TODO
|
||||
);
|
||||
|
||||
$parameters = array(
|
||||
'host' => REDIS_SERVER_HOST,
|
||||
'port' => REDIS_SERVER_PORT,
|
||||
|
||||
@@ -23,11 +23,25 @@ class DispatcherLoopTest extends PredisTestCase
|
||||
// ---- INTEGRATION TESTS --------------------------------------------- //
|
||||
// ******************************************************************** //
|
||||
|
||||
// NOTE: the following 2 tests fail at random without any apparent reason
|
||||
// when executed on our CI environments and these failures are not tied
|
||||
// to a particular version of PHP or Redis. It is most likely some weird
|
||||
// timing issue on busy systems as it is really rare to get it triggered
|
||||
// locally. The chances it is a bug in the library are pretty low so for
|
||||
// now we just mark this test skipped on our CI environments (but still
|
||||
// enabled for local test runs) and "debug" this issue using a separate
|
||||
// branch to avoid having spurious failures on main development branches
|
||||
// which is utterly annoying.
|
||||
|
||||
/**
|
||||
* @group connected
|
||||
*/
|
||||
public function testDispatcherLoopAgainstRedisServer()
|
||||
{
|
||||
$this->markTestSkippedOnCIEnvironment(
|
||||
'Test temporarily skipped on CI environments, see note in the body of the test' // TODO
|
||||
);
|
||||
|
||||
$parameters = array(
|
||||
'host' => REDIS_SERVER_HOST,
|
||||
'port' => REDIS_SERVER_PORT,
|
||||
@@ -87,6 +101,10 @@ class DispatcherLoopTest extends PredisTestCase
|
||||
*/
|
||||
public function testDispatcherLoopAgainstRedisServerWithPrefix()
|
||||
{
|
||||
$this->markTestSkippedOnCIEnvironment(
|
||||
'Test temporarily skipped on CI environments, see note in the body of the test' // TODO
|
||||
);
|
||||
|
||||
$parameters = array(
|
||||
'host' => REDIS_SERVER_HOST,
|
||||
'port' => REDIS_SERVER_PORT,
|
||||
|
||||
@@ -81,15 +81,15 @@ class ReplicationStrategyTest extends PredisTestCase
|
||||
$profile = Profile\Factory::getDevelopment();
|
||||
$strategy = new ReplicationStrategy();
|
||||
|
||||
$cmdReadSort = $profile->createCommand('SORT', array('key:list'));
|
||||
$this->assertTrue(
|
||||
$strategy->isReadOperation($cmdReadSort),
|
||||
'SORT is expected to be a read operation.'
|
||||
$cmdReturnSort = $profile->createCommand('SORT', array('key:list'));
|
||||
$this->assertFalse(
|
||||
$strategy->isReadOperation($cmdReturnSort),
|
||||
'SORT is expected to be a write operation.'
|
||||
);
|
||||
|
||||
$cmdWriteSort = $profile->createCommand('SORT', array('key:list', array('store' => 'key:stored')));
|
||||
$cmdStoreSort = $profile->createCommand('SORT', array('key:list', array('store' => 'key:stored')));
|
||||
$this->assertFalse(
|
||||
$strategy->isReadOperation($cmdWriteSort),
|
||||
$strategy->isReadOperation($cmdStoreSort),
|
||||
'SORT with STORE is expected to be a write operation.'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
/**
|
||||
* Apply patches to support newer PHP versions.
|
||||
*/
|
||||
|
||||
$patches = array(
|
||||
'phpunit_mock_objects.patch' => 'phpunit/phpunit-mock-objects',
|
||||
'phpunit_php7.patch' => 'phpunit/phpunit',
|
||||
'phpunit_php8.patch' => 'phpunit/phpunit',
|
||||
);
|
||||
|
||||
foreach ($patches as $patch => $package) {
|
||||
chdir(__DIR__.'/../vendor/'.$package);
|
||||
passthru(sprintf('patch -p1 -f < ../../../tests/%s', $patch));
|
||||
}
|
||||
Reference in New Issue
Block a user