Compare commits

..

30 Commits

Author SHA1 Message Date
Till Krüss 4cc119a03c tag 2.0.0-beta.1 2022-05-26 11:48:12 -07:00
Till Krüss 619890f715 fix test 2022-05-26 11:45:35 -07:00
Till Krüss b060d43157 port changes from v1.1 branch 2022-05-26 11:29:45 -07:00
Till Krüss a5ab2bce6b truncate changelog 2022-05-26 11:12:41 -07:00
Hubert Lenoir 89f20dc968 add TOUCH command (#767) 2022-05-23 08:46:48 -07:00
Michal Lulco 6af5394a89 Added ZPOPMIN and ZPOPMAX (#758)
* Added ZPOPMIN and ZPOPMAX

* Added ZPOPMIN and ZPOPMAX

* Applied patch
2022-05-16 08:00:06 -07:00
Zaher Ghaibeh c508086b0e remove redundant variables (#765) 2022-05-15 09:51:28 -07:00
Zaher Ghaibeh 3c01ccc94c Testing code against Redis 7 (#764)
* redis 7 init

fix typo

add the new returns

* having a full sentence for the exception message
2022-05-12 12:23:51 -07:00
Jordi Boggiano e382bedb27 Update method tags (#762) 2022-05-12 09:13:06 -07:00
Zaher Ghaibeh a2449da7c8 PHP 8.1 tests (#760)
* - init 8.1 tests
- adding `#[\ReturnTypeWillChange]`
- Fix deprecation message: strlen(): Passing null to parameter #1 ($string) of type string is deprecated
- null is not allowed
- cleanup
- default values should be same type

* Mirror `v1.1` fixes for these files

* add null as type too since we also accept null as default value

Signed-off-by: Zaher Ghaibeh <zaher@zaher.dev>

* revert back to assertNull

* Update CHANGELOG

* Update CHANGELOG.md

Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2022-05-07 08:03:53 -07:00
♚ PH⑦ de Soria™♛ b3a5bdf940 Remove invalid input for actions/cache (#737)
https://github.com/actions/cache/blob/main/examples.md#php---composer
2022-01-14 08:22:59 -08:00
Georges.L 4c1aada5ae Updated set, setex, setexp type hint (#710) 2021-09-08 09:05:55 -07:00
Mehdi Baaboura 54775a0295 Update LICENSE (#704) 2021-07-19 09:27:37 -07:00
Ruslan Bekenev 367bd72a0b Test optional count argument for LPOP (#700)
First added in Redis 6.2
2021-06-09 09:46:24 -07:00
Till Krüss 1d7ccb64ab Merge pull request #670 from charescape/patch-1
Update README.md
2021-04-04 10:33:08 -07:00
Till Krüss e29ae9065f some spacing 2021-04-04 10:31:53 -07:00
Till Krüss 64fc7774c6 stick to PHPUnit 9.4.* for now
`getAnnotations()` was removed in 9.5:

https://github.com/sebastianbergmann/phpunit/commit/68582043e149039cfa3596b42ed35753dcf54fb2
2021-04-04 10:31:45 -07:00
Till Krüss 554c36b329 Merge pull request #688 from open-source-contributions/improve_assertions
Improve PHPUnit assertions
2021-04-04 10:20:39 -07:00
Till Krüss be9d477564 fix for Redis 6 error message 2021-04-04 10:16:44 -07:00
Till Krüss 0e4e8f41cc fix 2021-04-04 10:14:13 -07:00
Till Krüss aa0c30809b fix test when using Redis 6 2021-04-04 10:11:29 -07:00
Peter 20f8faee6f Improve PHPUnit assertions 2021-04-04 23:30:14 +08:00
Till Krüss aa436263f8 Merge pull request #684 from andrew-demb/patch-2
CommandInterface::parseResponse() can accept array and null argument
2021-03-09 08:43:59 -08:00
Till Krüss 3c8856b05a Merge pull request #683 from andrew-demb/patch-1
Status::get() always return self
2021-03-09 08:43:39 -08:00
Andrii Dembitskyi d935f6e5c2 CommandInterface::parseResponse() can accept array and null argument 2021-03-09 07:15:08 -05:00
Andrii Dembitskyi 87fcc69e7a Status::get() always return self 2021-03-09 07:09:15 -05:00
charescape 407ddeca92 Update README.md 2020-11-12 11:39:48 +08:00
Till Krüss 338ba6d73d Merge pull request #665 from danwall/patch-1
Fix typo
2020-09-26 19:08:13 -07:00
Dan Wall 25db9bfec5 Fix typo 2020-09-26 11:52:44 +10:00
Daniele Alessandri 0e9aeee90f Fix PhpiredisSocketConnection for PHP 8.
Removed is_resource() check as socket_create() now returns an object.
2020-09-20 15:29:16 +02:00
58 changed files with 819 additions and 1762 deletions
+16 -4
View File
@@ -1,40 +1,52 @@
name: Tests
on: [push, pull_request]
on:
- push
- pull_request
jobs:
predis:
name: PHP ${{ matrix.php-versions }} (Redis ${{ matrix.redis-versions }})
runs-on: ubuntu-latest
services:
redis:
image: redis:${{ matrix.redis-versions }}
ports:
- 6379:6379
options: --health-cmd="redis-cli ping" --health-interval=10s --health-timeout=5s --health-retries=3
strategy:
fail-fast: false
matrix:
php-versions: ['7.2', '7.3', '7.4', '8.0']
redis-versions: ['3', '4', '5', '6']
php-versions: ['7.2', '7.3', '7.4', '8.0', '8.1']
redis-versions: ['3', '4', '5', '6', '7']
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup PHP with Composer and extensions
with:
php-version: ${{ matrix.php-versions }}
uses: shivammathur/setup-php@v2
- name: Get Composer cache directory
id: composercache
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
- name: Cache Composer dependencies
uses: actions/cache@v2
with:
php-version: ${{ matrix.php-versions }}
path: ${{ steps.composercache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-
- name: Install Composer dependencies
env:
PHP_VERSION: ${{ matrix.php-versions }}
run: composer install --no-progress --prefer-dist --optimize-autoloader $(if [ "$PHP_VERSION" == "8.0" ]; then echo "--ignore-platform-reqs"; fi;)
- name: Test with PHPUnit
run: vendor/bin/phpunit
+19 -1074
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright (c) 2009-2020 Daniele Alessandri
Copyright (c) 2009-2021 Daniele Alessandri
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
+8 -58
View File
@@ -22,7 +22,7 @@ More details about this project can be found on the [frequently asked questions]
## Main features ##
- Support for Redis from __2.0__ to __3.2__.
- Support for Redis from __2.0__ to __6.0__.
- Support for clustering using client-side sharding and pluggable keyspace distributors.
- Support for [redis-cluster](http://redis.io/topics/cluster-tutorial) (Redis >= 3.0).
- Support for master-slave replication setups and [redis-sentinel](http://redis.io/topics/sentinel).
@@ -169,40 +169,6 @@ Users can also provide custom options with values or callable objects (for lazy
are stored in the options container for later use through the library.
### Global and role-specific default connection parameters ###
While the `parameters` client option is useful to apply a set of default parameters and their values
to connections created by the underlying connection factory, sometimes it is useful to set different
values depending on the actual role of the target node (just to make an example, for sentinel nodes
it is common to use a lower connect() timeout compared to the default value for normal Redis nodes).
To make this possible `parameters` allows passing role-specific default values as named arrays using
three special keys: `role.sentinel`, `role.master` and `role.slave`. These role-specific parameters
take precedence over global default parameters passed at the root level of `parameters` but they do
not override parameters explicitly set by the user for each single node just like global defaults.
```php
$options = [
'parameters' => [
// Root level is for global default parameters.
'database' => 10,
'password' => $redisSecretPassword,
// ...
'role.master' => [
// Sub-key for default parameters targeting master Redis nodes.
],
'role.slave' => [
// Sub-key for default parameters targeting replica Redis nodes.
],
'role.sentinel' => [
// Sub-key for default parameters targeting Redis Sentinel nodes.
],
],
];
```
### Aggregate connections ###
Aggregate connections are the foundation upon which Predis implements clustering and replication and
@@ -268,38 +234,22 @@ the `service` option set to the name of the service:
```php
$sentinels = ['tcp://10.0.0.1', 'tcp://10.0.0.2', 'tcp://10.0.0.3'];
$options = ['replication' => 'sentinel', 'service' => 'myservice'];
$options = ['replication' => 'sentinel', 'service' => 'mymaster'];
$client = new Predis\Client($sentinels, $options);
```
When master and replica nodes are configured to require authentication from clients, users must pass
`password` (password-based authentication) or `username` and `password` (ACL-based authentication on
Redis >= 6.0) via the global `parameters` client option.
If the master and slave nodes are configured to require an authentication from clients, a password
must be provided via the global `parameters` client option. This option can also be used to specify
a different database index. The client options array would then look like this:
```php
$options = [
'replication' => 'sentinel',
'service' => 'myservice',
'service' => 'mymaster',
'parameters' => [
'password' => $secretRedisPassword,
],
];
```
For sentinels protected by a password (supported since Redis >= 5.0) its value is not inherited from
the global `parameters` client option so a `password` must be set using the `role.sentinel` sub-key:
```php
$options = [
'replication' => 'sentinel',
'service' => 'myservice',
'parameters' => [
'password' => $secretRedisPassword,
'role.sentinel' => [
'password' => $secretSentinelPassword
]
'password' => $secretpassword,
'database' => 10,
],
];
```
+1 -1
View File
@@ -1 +1 @@
2.0.0-dev
2.0.0-beta.1
+1 -1
View File
@@ -31,7 +31,7 @@
"php": "^7.2 || ^8.0"
},
"require-dev": {
"phpunit/phpunit": "^8.0 || ^9.0"
"phpunit/phpunit": "^8.0 || ~9.4.4"
},
"suggest": {
"ext-phpiredis": "Allows faster serialization and deserialization of the Redis protocol",
+3 -4
View File
@@ -40,7 +40,7 @@ use Predis\Transaction\MultiExec as MultiExecTransaction;
*/
class Client implements ClientInterface, \IteratorAggregate
{
const VERSION = '2.0.0-dev';
const VERSION = '2.0.0-beta.1';
/** @var OptionsInterface */
private $options;
@@ -209,9 +209,7 @@ class Client implements ClientInterface, \IteratorAggregate
throw new \InvalidArgumentException("Cannot find a connection by $selector matching `$value`");
}
$client = new static($connection, $this->getOptions());
return $client;
return new static($connection, $this->getOptions());
}
/**
@@ -515,6 +513,7 @@ class Client implements ClientInterface, \IteratorAggregate
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function getIterator()
{
$clients = array();
+127 -123
View File
@@ -15,6 +15,7 @@ use Predis\Command\CommandInterface;
use Predis\Command\FactoryInterface;
use Predis\Configuration\OptionsInterface;
use Predis\Connection\ConnectionInterface;
use Predis\Response\Status;
/**
* Interface defining a client able to execute commands against Redis.
@@ -24,134 +25,137 @@ use Predis\Connection\ConnectionInterface;
* and more friendly interface to ease programming which is described in the
* following list of methods:
*
* @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 int del(string[]|string $keyOrKeys, string ...$keys = null)
* @method string|null dump(string $key)
* @method int exists(string $key)
* @method int expire(string $key, int $seconds)
* @method int expireat(string $key, int $timestamp)
* @method array keys(string $pattern)
* @method int move(string $key, int $db)
* @method mixed object($subcommand, string $key)
* @method int persist(string $key)
* @method int pexpire(string $key, int $milliseconds)
* @method int pexpireat(string $key, int $timestamp)
* @method int pttl(string $key)
* @method string|null randomkey()
* @method mixed rename($key, $target)
* @method int renamenx($key, $target)
* @method mixed rename(string $key, string $target)
* @method int renamenx(string $key, string $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 array sort(string $key, array $options = null)
* @method int ttl(string $key)
* @method mixed type(string $key)
* @method int append(string $key, $value)
* @method int bitcount(string $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 array|null bitfield(string $key, $subcommand, ...$subcommandArg)
* @method int bitpos(string $key, $bit, $start = null, $end = null)
* @method int decr(string $key)
* @method int decrby(string $key, int $decrement)
* @method string|null get(string $key)
* @method int getbit(string $key, $offset)
* @method string getrange(string $key, $start, $end)
* @method string|null getset(string $key, $value)
* @method int incr(string $key)
* @method int incrby(string $key, int $increment)
* @method string incrbyfloat(string $key, int|float $increment)
* @method array mget(string[]|string $keyOrKeys, string ...$keys = null)
* @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 Status psetex(string $key, $milliseconds, $value)
* @method Status set(string $key, $value, $expireResolution = null, $expireTTL = null, $flag = null)
* @method int setbit(string $key, $offset, $value)
* @method Status setex(string $key, $seconds, $value)
* @method int setnx(string $key, $value)
* @method int setrange(string $key, $offset, $value)
* @method int strlen(string $key)
* @method int hdel(string $key, array $fields)
* @method int hexists(string $key, string $field)
* @method string|null hget(string $key, string $field)
* @method array hgetall(string $key)
* @method int hincrby(string $key, string $field, int $increment)
* @method string hincrbyfloat(string $key, string $field, int|float $increment)
* @method array hkeys(string $key)
* @method int hlen(string $key)
* @method array hmget(string $key, array $fields)
* @method mixed hmset(string $key, array $dictionary)
* @method array hscan(string $key, $cursor, array $options = null)
* @method int hset(string $key, string $field, string $value)
* @method int hsetnx(string $key, string $field, string $value)
* @method array hvals(string $key)
* @method int hstrlen(string $key, string $field)
* @method array|null blpop(array|string $keys, int|float $timeout)
* @method array|null brpop(array|string $keys, int|float $timeout)
* @method string|null brpoplpush(string $source, string $destination, int|float $timeout)
* @method string|null lindex(string $key, int $index)
* @method int linsert(string $key, $whence, $pivot, $value)
* @method int llen(string $key)
* @method string|null lpop(string $key)
* @method int lpush(string $key, array $values)
* @method int lpushx(string $key, array $values)
* @method string[] lrange(string $key, int $start, int $stop)
* @method int lrem(string $key, int $count, string $value)
* @method mixed lset(string $key, int $index, string $value)
* @method mixed ltrim(string $key, int $start, int $stop)
* @method string|null rpop(string $key)
* @method string|null rpoplpush(string $source, string $destination)
* @method int rpush(string $key, array $values)
* @method int rpushx(string $key, array $values)
* @method int sadd(string $key, array $members)
* @method int scard(string $key)
* @method string[] sdiff(array|string $keys)
* @method int sdiffstore(string $destination, array|string $keys)
* @method string[] sinter(array|string $keys)
* @method int sinterstore(string $destination, array|string $keys)
* @method int sismember(string $key, string $member)
* @method string[] smembers(string $key)
* @method int smove(string $source, string $destination, string $member)
* @method string|null spop(string $key, int $count = null)
* @method string|null srandmember(string $key, int $count = null)
* @method int srem(string $key, string $member)
* @method array sscan(string $key, int $cursor, array $options = null)
* @method string[] sunion(array|string $keys)
* @method int sunionstore(string $destination, array|string $keys)
* @method int touch(string[]|string $keyOrKeys, string ...$keys = null)
* @method int zadd(string $key, array $membersAndScoresDictionary)
* @method int zcard(string $key)
* @method string zcount(string $key, int|string $min, int|string $max)
* @method string zincrby(string $key, int $increment, string $member)
* @method int zinterstore(string $destination, array|string $keys, array $options = null)
* @method array zpopmin(string $key, int $count = 1)
* @method array zpopmax(string $key, int $count = 1)
* @method array zrange(string $key, int|string $start, int|string $stop, array $options = null)
* @method array zrangebyscore(string $key, int|string $min, int|string $max, array $options = null)
* @method int|null zrank(string $key, string $member)
* @method int zrem(string $key, string ...$member)
* @method int zremrangebyrank(string $key, int|string $start, int|string $stop)
* @method int zremrangebyscore(string $key, int|string $min, int|string $max)
* @method array zrevrange(string $key, int|string $start, int|string $stop, array $options = null)
* @method array zrevrangebyscore(string $key, int|string $max, int|string $min, array $options = null)
* @method int|null zrevrank(string $key, string $member)
* @method int zunionstore(string $destination, array|string $keys, array $options = null)
* @method string|null zscore(string $key, string $member)
* @method array zscan(string $key, int $cursor, array $options = null)
* @method array zrangebylex(string $key, string $start, string $stop, array $options = null)
* @method array zrevrangebylex(string $key, string $start, string $stop, array $options = null)
* @method int zremrangebylex(string $key, string $min, string $max)
* @method int zlexcount(string $key, string $min, string $max)
* @method int pfadd(string $key, array $elements)
* @method mixed pfmerge(string $destinationKey, array|string $sourceKeys)
* @method int pfcount(string[]|string $keyOrKeys, string ...$keys = null)
* @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 watch(string $key)
* @method mixed eval(string $script, int $numkeys, string ...$keyOrArg = null)
* @method mixed evalsha(string $script, int $numkeys, string ...$keyOrArg = 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 auth(string $password)
* @method string echo(string $message)
* @method mixed ping(string $message = null)
* @method mixed select(int $database)
* @method mixed bgrewriteaof()
* @method mixed bgsave()
* @method mixed client($subcommand, $argument = null)
@@ -162,16 +166,16 @@ use Predis\Connection\ConnectionInterface;
* @method array info($section = null)
* @method int lastsave()
* @method mixed save()
* @method mixed slaveof($host, $port)
* @method mixed slaveof(string $host, int $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)
* @method int geoadd(string $key, $longitude, $latitude, $member)
* @method array geohash(string $key, array $members)
* @method array geopos(string $key, array $members)
* @method string|null geodist(string $key, $member1, $member2, $unit = null)
* @method array georadius(string $key, $longitude, $latitude, $radius, $unit, array $options = null)
* @method array georadiusbymember(string $key, $member, $radius, $unit, array $options = null)
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
+1 -2
View File
@@ -239,9 +239,8 @@ class HashRing implements DistributorInterface, HashGeneratorInterface
public function get($value)
{
$hash = $this->hash($value);
$node = $this->getByHash($hash);
return $node;
return $this->getByHash($hash);
}
/**
+1 -2
View File
@@ -40,9 +40,8 @@ class PredisStrategy extends ClusterStrategy
{
$key = $this->extractKeyTag($key);
$hash = $this->distributor->hash($key);
$slot = $this->distributor->getSlot($hash);
return $slot;
return $this->distributor->getSlot($hash);
}
/**
+1 -2
View File
@@ -41,9 +41,8 @@ class RedisStrategy extends ClusterStrategy
public function getSlotByKey($key)
{
$key = $this->extractKeyTag($key);
$slot = $this->hashGenerator->hash($key) & 0x3FFF;
return $slot;
return $this->hashGenerator->hash($key) & 0x3FFF;
}
/**
+6
View File
@@ -125,6 +125,7 @@ class SlotMap implements \ArrayAccess, \IteratorAggregate, \Countable
*
* @return bool
*/
#[\ReturnTypeWillChange]
public function offsetExists($slot)
{
return isset($this->slots[$slot]);
@@ -137,6 +138,7 @@ class SlotMap implements \ArrayAccess, \IteratorAggregate, \Countable
*
* @return string
*/
#[\ReturnTypeWillChange]
public function offsetGet($slot)
{
if (isset($this->slots[$slot])) {
@@ -152,6 +154,7 @@ class SlotMap implements \ArrayAccess, \IteratorAggregate, \Countable
*
* @return string
*/
#[\ReturnTypeWillChange]
public function offsetSet($slot, $connection)
{
if (!static::isValid($slot)) {
@@ -168,6 +171,7 @@ class SlotMap implements \ArrayAccess, \IteratorAggregate, \Countable
*
* @return string
*/
#[\ReturnTypeWillChange]
public function offsetUnset($slot)
{
unset($this->slots[$slot]);
@@ -178,6 +182,7 @@ class SlotMap implements \ArrayAccess, \IteratorAggregate, \Countable
*
* @return int
*/
#[\ReturnTypeWillChange]
public function count()
{
return count($this->slots);
@@ -188,6 +193,7 @@ class SlotMap implements \ArrayAccess, \IteratorAggregate, \Countable
*
* @return \ArrayIterator
*/
#[\ReturnTypeWillChange]
public function getIterator()
{
return new \ArrayIterator($this->slots);
@@ -92,7 +92,7 @@ abstract class CursorBasedIterator implements \Iterator
{
$options = array();
if (strlen($this->match) > 0) {
if (strlen(strval($this->match)) > 0) {
$options['MATCH'] = $this->match;
}
@@ -139,6 +139,7 @@ abstract class CursorBasedIterator implements \Iterator
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function rewind()
{
$this->reset();
@@ -148,6 +149,7 @@ abstract class CursorBasedIterator implements \Iterator
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function current()
{
return $this->current;
@@ -156,6 +158,7 @@ abstract class CursorBasedIterator implements \Iterator
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function key()
{
return $this->position;
@@ -164,6 +167,7 @@ abstract class CursorBasedIterator implements \Iterator
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function next()
{
tryFetch: {
@@ -184,6 +188,7 @@ abstract class CursorBasedIterator implements \Iterator
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function valid()
{
return $this->valid;
+5
View File
@@ -128,6 +128,7 @@ class ListKey implements \Iterator
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function rewind()
{
$this->reset();
@@ -137,6 +138,7 @@ class ListKey implements \Iterator
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function current()
{
return $this->current;
@@ -145,6 +147,7 @@ class ListKey implements \Iterator
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function key()
{
return $this->position;
@@ -153,6 +156,7 @@ class ListKey implements \Iterator
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function next()
{
if (!$this->elements && $this->fetchmore) {
@@ -169,6 +173,7 @@ class ListKey implements \Iterator
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function valid()
{
return $this->valid;
+1 -1
View File
@@ -92,7 +92,7 @@ abstract class Command implements CommandInterface
*/
public static function normalizeArguments(array $arguments)
{
if (count($arguments) === 1 && is_array($arguments[0])) {
if (count($arguments) === 1 && isset($arguments[0]) && is_array($arguments[0])) {
return $arguments[0];
}
+1 -1
View File
@@ -73,7 +73,7 @@ interface CommandInterface
/**
* Parses a raw response and returns a PHP object.
*
* @param string $data Binary string containing the whole response.
* @param string|array|null $data Binary string containing the whole response.
*
* @return mixed
*/
+5 -1
View File
@@ -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()
{
@@ -91,6 +91,7 @@ class ProcessorChain implements \ArrayAccess, ProcessorInterface
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function offsetExists($index)
{
return isset($this->processors[$index]);
@@ -99,6 +100,7 @@ class ProcessorChain implements \ArrayAccess, ProcessorInterface
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function offsetGet($index)
{
return $this->processors[$index];
@@ -107,6 +109,7 @@ class ProcessorChain implements \ArrayAccess, ProcessorInterface
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function offsetSet($index, $processor)
{
if (!$processor instanceof ProcessorInterface) {
@@ -121,6 +124,7 @@ class ProcessorChain implements \ArrayAccess, ProcessorInterface
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function offsetUnset($index)
{
unset($this->processors[$index]);
+1 -2
View File
@@ -51,9 +51,8 @@ final class RawCommand implements CommandInterface
public static function create($commandID /* [ $arg, ... */)
{
$arguments = func_get_args();
$command = new static(array_shift($arguments), $arguments);
return $command;
return new static(array_shift($arguments), $arguments);
}
/**
+4 -1
View File
@@ -33,7 +33,10 @@ class SENTINEL extends RedisCommand
*/
public function parseResponse($data)
{
switch (strtolower($this->getArgument(0))) {
$argument = $this->getArgument(0);
$argument = is_null($argument) ? null : strtolower($argument);
switch ($argument) {
case 'masters':
case 'slaves':
return self::processMastersOrSlaves($data);
+40
View File
@@ -0,0 +1,40 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command\Redis;
use Predis\Command\Command as RedisCommand;
/**
* @link http://redis.io/commands/touch
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class TOUCH extends RedisCommand
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'TOUCH';
}
/**
* {@inheritdoc}
*/
public function setArguments(array $arguments)
{
$arguments = self::normalizeArguments($arguments);
parent::setArguments($arguments);
}
}
+44
View File
@@ -0,0 +1,44 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command\Redis;
use Predis\Command\Command as RedisCommand;
/**
* @link http://redis.io/commands/zpopmax
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ZPOPMAX extends RedisCommand
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'ZPOPMAX';
}
/**
* {@inheritdoc}
*/
public function parseResponse($data)
{
$result = array();
for ($i = 0; $i < count($data); ++$i) {
$result[$data[$i]] = $data[++$i];
}
return $result;
}
}
+44
View File
@@ -0,0 +1,44 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command\Redis;
use Predis\Command\Command as RedisCommand;
/**
* @link http://redis.io/commands/zpopmin
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ZPOPMIN extends RedisCommand
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'ZPOPMIN';
}
/**
* {@inheritdoc}
*/
public function parseResponse($data)
{
$result = array();
for ($i = 0; $i < count($data); ++$i) {
$result[$data[$i]] = $data[++$i];
}
return $result;
}
}
+9 -5
View File
@@ -26,17 +26,21 @@ abstract class CommunicationException extends PredisException
* @param NodeConnectionInterface $connection Connection that generated the exception.
* @param string $message Error message.
* @param int $code Error code.
* @param \Exception $innerException Inner exception for wrapping the original error.
* @param \Exception|null $innerException Inner exception for wrapping the original error.
*/
public function __construct(
NodeConnectionInterface $connection,
$message = null,
$code = null,
$message = "",
$code = 0,
\Exception $innerException = null
) {
$this->connection = $connection;
parent::__construct(
is_null($message) ? '' : $message,
is_null($code) ? 0 : $code,
$innerException
);
parent::__construct($message, $code, $innerException);
$this->connection = $connection;
}
/**
+1 -1
View File
@@ -126,7 +126,7 @@ abstract class AbstractConnection implements NodeConnectionInterface
* @param string $message Error message.
* @param int $code Error code.
*/
protected function onConnectionError($message, $code = null)
protected function onConnectionError($message, $code = 0)
{
CommunicationException::handle(
new ConnectionException($this, "$message [{$this->getParameters()}]", $code)
+4 -6
View File
@@ -138,9 +138,7 @@ class PredisCluster implements ClusterInterface, \IteratorAggregate, \Countable
);
}
$node = $this->distributor->getBySlot($slot);
return $node;
return $this->distributor->getBySlot($slot);
}
/**
@@ -189,9 +187,7 @@ class PredisCluster implements ClusterInterface, \IteratorAggregate, \Countable
public function getConnectionByKey($key)
{
$hash = $this->strategy->getSlotByKey($key);
$node = $this->distributor->getBySlot($hash);
return $node;
return $this->distributor->getBySlot($hash);
}
/**
@@ -208,6 +204,7 @@ class PredisCluster implements ClusterInterface, \IteratorAggregate, \Countable
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function count()
{
return count($this->pool);
@@ -216,6 +213,7 @@ class PredisCluster implements ClusterInterface, \IteratorAggregate, \Countable
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function getIterator()
{
return new \ArrayIterator($this->pool);
+4 -6
View File
@@ -442,9 +442,7 @@ class RedisCluster implements ClusterInterface, \IteratorAggregate, \Countable
}
$this->move($connection, $slot);
$response = $this->executeCommand($command);
return $response;
return $this->executeCommand($command);
}
/**
@@ -465,9 +463,7 @@ class RedisCluster implements ClusterInterface, \IteratorAggregate, \Countable
}
$connection->executeCommand(RawCommand::create('ASKING'));
$response = $connection->executeCommand($command);
return $response;
return $connection->executeCommand($command);
}
/**
@@ -545,6 +541,7 @@ class RedisCluster implements ClusterInterface, \IteratorAggregate, \Countable
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function count()
{
return count($this->pool);
@@ -553,6 +550,7 @@ class RedisCluster implements ClusterInterface, \IteratorAggregate, \Countable
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function getIterator()
{
if ($this->slotmap->isEmpty()) {
+2 -64
View File
@@ -11,7 +11,6 @@
namespace Predis\Connection;
use InvalidArgumentException;
use Predis\Command\RawCommand;
/**
@@ -120,28 +119,6 @@ class Factory implements FactoryInterface
*/
public function setDefaultParameters(array $parameters)
{
if (isset($parameters['role.master']) && !is_array($parameters['role.master'])) {
throw new InvalidArgumentException('Default parameters for `role.master` must be passed as a named array');
}
if (isset($parameters['role.slave']) && !is_array($parameters['role.slave'])) {
throw new InvalidArgumentException('Default parameters for `role.slave` must be passed as a named array');
}
if (isset($parameters['role.sentinel'])) {
if (!is_array($parameters['role.sentinel'])) {
throw new InvalidArgumentException('Default parameters for `role.sentinel` must be passed as a named array');
}
// NOTE: sentinels do not support "SELECT" and ACL "AUTH" commands
// so we must strip "database" and "username" from "role.sentinel"
// to prevent spurious commands from being sent to sentinel nodes.
unset(
$parameters['role.sentinel']['username'],
$parameters['role.sentinel']['database']
);
}
$this->defaults = $parameters;
}
@@ -155,37 +132,6 @@ class Factory implements FactoryInterface
return $this->defaults;
}
/**
* Applies default connection parameters to the user supplied parameters.
*
* @param array $parameters Input connection parameters
*
* @return array
*/
protected function applyDefaultParameters(array $parameters)
{
static $stripInternal = ['role.sentinel' => null, 'role.master' => null, 'role.slave' => null];
$stripAdditional = [];
if (isset($parameters['role'])) {
switch ($role = $parameters['role']) {
case 'sentinel':
// NOTE: we strip these from global defaults when dealing with sentinel nodes.
$stripAdditional = ['username' => null, 'password' => null, 'database' => null];
case 'master':
case 'slave':
if (isset($this->defaults["role.$role"])) {
$parameters += $this->defaults["role.$role"];
}
}
}
$parameters += array_diff_key($this->defaults, $stripInternal, $stripAdditional);
return $parameters;
}
/**
* Creates a connection parameters instance from the supplied argument.
*
@@ -198,19 +144,11 @@ class Factory implements FactoryInterface
if (is_string($parameters)) {
$parameters = Parameters::parse($parameters);
} else {
$parameters = $parameters ?? [];
}
if (isset($parameters['role']) && $parameters['role'] === 'sentinel') {
// NOTE: sentinels do not support "SELECT" and ACL "AUTH" commands so we must strip
// "database" and "username" from input parameters to prevent spurious commands from
// being sent to sentinel nodes but they can still accept "password" when explicitly
// set (password-based authentication for sentinels is supported on Redis >= 5.0).
unset($parameters['username'], $parameters['database']);
$parameters = $parameters ?: array();
}
if ($this->defaults) {
$parameters = $this->applyDefaultParameters($parameters);
$parameters += $this->defaults;
}
return new Parameters($parameters);
+5 -5
View File
@@ -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();
}
}
+12 -2
View File
@@ -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();
}
/**
@@ -20,6 +20,7 @@ use Predis\Connection\NodeConnectionInterface;
use Predis\Connection\Parameters;
use Predis\Replication\ReplicationStrategy;
use Predis\Replication\RoleException;
use Predis\Response\Error;
use Predis\Response\ErrorInterface as ErrorResponseInterface;
use Predis\Response\ServerException;
@@ -151,14 +152,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;
}
/**
@@ -241,8 +242,6 @@ class SentinelReplication implements ReplicationInterface
/**
* Creates a new connection to a sentinel server.
*
* @param mixed $parameters Connection parameters or connection instance
*
* @return NodeConnectionInterface
*/
protected function createSentinelConnection($parameters)
@@ -256,19 +255,21 @@ class SentinelReplication implements ReplicationInterface
}
if (is_array($parameters)) {
// NOTE: we enforce the "sentinel" role so that appropriate default
// parameters are applied when creating the new connection instance
// and blacklisted ones are stripped off from input parameters.
$parameters['role'] = 'sentinel';
// 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;
if (!isset($parameters['timeout'])) {
$parameters['timeout'] = $this->sentinelTimeout;
}
}
$connection = $this->connectionFactory->create($parameters);
return $connection;
return $this->connectionFactory->create($parameters);
}
/**
@@ -536,13 +537,17 @@ class SentinelReplication implements ReplicationInterface
* @param NodeConnectionInterface $connection Connection to a redis server.
* @param string $role Expected role of the server ("master", "slave" or "sentinel").
*
* @throws RoleException
* @throws RoleException|ConnectionException
*/
protected function assertConnectionRole(NodeConnectionInterface $connection, $role)
{
$role = strtolower($role);
$actualRole = $connection->executeCommand(RawCommand::create('ROLE'));
if ($actualRole instanceof Error) {
throw new ConnectionException($connection, $actualRole->getMessage());
}
if ($role !== $actualRole[0]) {
throw new RoleException($connection, "Expected $role but got $actualRole[0] [$connection]");
}
+3 -7
View File
@@ -151,9 +151,7 @@ class StreamConnection extends AbstractConnection
}
}
$resource = $this->createStreamSocket($parameters, $address, $flags);
return $resource;
return $this->createStreamSocket($parameters, $address, $flags);
}
/**
@@ -183,9 +181,7 @@ class StreamConnection extends AbstractConnection
}
}
$resource = $this->createStreamSocket($parameters, "unix://{$parameters->path}", $flags);
return $resource;
return $this->createStreamSocket($parameters, "unix://{$parameters->path}", $flags);
}
/**
@@ -364,7 +360,7 @@ class StreamConnection extends AbstractConnection
$buffer = "*{$reqlen}\r\n\${$cmdlen}\r\n{$commandID}\r\n";
foreach ($arguments as $argument) {
$arglen = strlen($argument);
$arglen = strlen(strval($argument));
$buffer .= "\${$arglen}\r\n{$argument}\r\n";
}
+5
View File
@@ -91,6 +91,7 @@ class Consumer implements \Iterator
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function rewind()
{
// NOOP
@@ -101,6 +102,7 @@ class Consumer implements \Iterator
*
* @return object
*/
#[\ReturnTypeWillChange]
public function current()
{
return $this->getValue();
@@ -109,6 +111,7 @@ class Consumer implements \Iterator
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function key()
{
return $this->position;
@@ -117,6 +120,7 @@ class Consumer implements \Iterator
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function next()
{
++$this->position;
@@ -127,6 +131,7 @@ class Consumer implements \Iterator
*
* @return bool
*/
#[\ReturnTypeWillChange]
public function valid()
{
return $this->valid;
+1 -1
View File
@@ -14,7 +14,7 @@ namespace Predis\Protocol;
use Predis\CommunicationException;
/**
* Exception used to indentify errors encountered while parsing the Redis wire
* Exception used to identify errors encountered while parsing the Redis wire
* protocol.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
+1 -3
View File
@@ -95,9 +95,7 @@ class ResponseReader implements ResponseReaderInterface
$this->onProtocolError($connection, "Unknown response prefix: '$prefix'");
}
$payload = $this->handlers[$prefix]->handle($connection, substr($header, 1));
return $payload;
return $this->handlers[$prefix]->handle($connection, substr($header, 1));
}
/**
+5
View File
@@ -151,6 +151,7 @@ abstract class AbstractConsumer implements \Iterator
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function rewind()
{
// NOOP
@@ -162,6 +163,7 @@ abstract class AbstractConsumer implements \Iterator
*
* @return array
*/
#[\ReturnTypeWillChange]
public function current()
{
return $this->getValue();
@@ -170,6 +172,7 @@ abstract class AbstractConsumer implements \Iterator
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function key()
{
return $this->position;
@@ -178,6 +181,7 @@ abstract class AbstractConsumer implements \Iterator
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function next()
{
if ($this->valid()) {
@@ -192,6 +196,7 @@ abstract class AbstractConsumer implements \Iterator
*
* @return bool
*/
#[\ReturnTypeWillChange]
public function valid()
{
$isValid = $this->isFlagSet(self::STATUS_VALID);
+2 -1
View File
@@ -62,7 +62,8 @@ class ReplicationStrategy
}
if (($eval = $id === 'EVAL') || $id === 'EVALSHA') {
$sha1 = $eval ? sha1($command->getArgument(0)) : $command->getArgument(0);
$argument = $command->getArgument(0);
$sha1 = $eval ? sha1(strval($argument)) : $argument;
if (isset($this->readonlySHA1[$sha1])) {
if (true === $readonly = $this->readonlySHA1[$sha1]) {
@@ -34,6 +34,7 @@ abstract class MultiBulkIterator implements \Iterator, \Countable, ResponseInter
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function rewind()
{
// NOOP
@@ -42,6 +43,7 @@ abstract class MultiBulkIterator implements \Iterator, \Countable, ResponseInter
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function current()
{
return $this->current;
@@ -50,6 +52,7 @@ abstract class MultiBulkIterator implements \Iterator, \Countable, ResponseInter
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function key()
{
return $this->position;
@@ -58,6 +61,7 @@ abstract class MultiBulkIterator implements \Iterator, \Countable, ResponseInter
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function next()
{
if (++$this->position < $this->size) {
@@ -68,6 +72,7 @@ abstract class MultiBulkIterator implements \Iterator, \Countable, ResponseInter
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function valid()
{
return $this->position < $this->size;
@@ -82,6 +87,7 @@ abstract class MultiBulkIterator implements \Iterator, \Countable, ResponseInter
*
* @return int
*/
#[\ReturnTypeWillChange]
public function count()
{
return $this->size;
+1
View File
@@ -61,6 +61,7 @@ class MultiBulkTuple extends MultiBulk implements \OuterIterator
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function getInnerIterator()
{
return $this->iterator;
+1 -1
View File
@@ -59,7 +59,7 @@ class Status implements ResponseInterface
*
* @param string $payload Status response payload.
*
* @return string
* @return self
*/
public static function get($payload)
{
+6
View File
@@ -54,6 +54,7 @@ class Handler implements \SessionHandlerInterface
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function open($save_path, $session_id)
{
// NOOP
@@ -63,6 +64,7 @@ class Handler implements \SessionHandlerInterface
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function close()
{
// NOOP
@@ -72,6 +74,7 @@ class Handler implements \SessionHandlerInterface
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function gc($maxlifetime)
{
// NOOP
@@ -81,6 +84,7 @@ class Handler implements \SessionHandlerInterface
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function read($session_id)
{
if ($data = $this->client->get($session_id)) {
@@ -92,6 +96,7 @@ class Handler implements \SessionHandlerInterface
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function write($session_id, $session_data)
{
$this->client->setex($session_id, $this->ttl, $session_data);
@@ -102,6 +107,7 @@ class Handler implements \SessionHandlerInterface
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function destroy($session_id)
{
$this->client->del($session_id);
@@ -27,9 +27,10 @@ class AbortedMultiExecException extends PredisException
* @param string $message Error message.
* @param int $code Error code.
*/
public function __construct(MultiExec $transaction, $message, $code = null)
public function __construct(MultiExec $transaction, $message, $code = 0)
{
parent::__construct($message, $code);
parent::__construct($message, is_null($code) ? 0 : $code);
$this->transaction = $transaction;
}
+4 -4
View File
@@ -236,7 +236,7 @@ class SlotMapTest extends PredisTestCase
{
$slotmap = new SlotMap();
$this->assertSame(0, count($slotmap));
$this->assertCount(0, $slotmap);
}
/**
@@ -247,13 +247,13 @@ class SlotMapTest extends PredisTestCase
$slotmap = new SlotMap();
$slotmap->setSlots(0, 5460, '127.0.0.1:6379');
$this->assertSame(5461, count($slotmap));
$this->assertCount(5461, $slotmap);
$slotmap->setSlots(5461, 10922, '127.0.0.1:6380');
$this->assertSame(10923, count($slotmap));
$this->assertCount(10923, $slotmap);
$slotmap->setSlots(10923, 16383, '127.0.0.1:6381');
$this->assertSame(16384, count($slotmap));
$this->assertCount(16384, $slotmap);
}
/**
+22 -1
View File
@@ -106,13 +106,34 @@ class COMMAND_Test extends PredisCommandTestCase
// 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
// command in the 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');
}
// NOTE: starting with Redis 7.0 COMMAND INFO returns an additional arrays:
// - Command tips: https://redis.io/topics/command-tips.
// - Key specifications: https://redis.io/topics/key-specs.
// - Subcommands: https://redis.io/commands/command/#subcommands.
// We simply append this additional array in the expected response if the
// test suite is executed against Redis >= 7.0.
if ($this->isRedisServerVersion('>=', '7.0')) {
$expected[0][] = array();
$expected[0][] = array(
array(
'flags',
array('RO','access'),
'begin_search',
array('type','index','spec', array('index',1)),
'find_keys',
array('type','range','spec', array('lastkey',0,'keystep',1,'limit',0))
)
);
$expected[0][] = array();
}
$this->assertCount(1, $response = $redis->command('INFO', 'GET'));
// NOTE: we use assertEquals instead of assertSame because Redis returns
+8 -2
View File
@@ -104,7 +104,7 @@ class CONFIG_Test extends PredisCommandTestCase
$redis = $this->getClient();
$this->assertIsArray($configs = $redis->config('GET', 'dbfilename'));
$this->assertEquals(1, count($configs));
$this->assertCount(1, $configs);
$this->assertArrayHasKey('dbfilename', $configs);
}
@@ -143,7 +143,13 @@ class CONFIG_Test extends PredisCommandTestCase
public function testThrowsExceptionWhenSettingUnknownConfiguration(): void
{
$this->expectException('Predis\Response\ServerException');
$this->expectExceptionMessage('ERR Unsupported CONFIG parameter: foo');
if ($this->isRedisServerVersion('<=', '6.0')) {
$this->expectExceptionMessage('ERR Unsupported CONFIG parameter: foo');
}
if ($this->isRedisServerVersion('>=', '7.0')) {
$this->expectExceptionMessage("ERR Unknown option or number of arguments for CONFIG SET - 'foo'");
}
$redis = $this->getClient();
+1 -1
View File
@@ -320,7 +320,7 @@ BUFFER;
$redis = $this->getClient();
$command = $this->getCommand();
$this->assertInternalType('array', $info = $redis->executeCommand($command));
$this->assertIsArray($info = $redis->executeCommand($command));
$this->assertArrayHasKey('redis_version', $info);
}
}
+15
View File
@@ -92,4 +92,19 @@ class LPOP_Test extends PredisCommandTestCase
$redis->set('foo', 'bar');
$redis->lpop('foo');
}
/**
* @group connected
* @requiresRedisVersion >= 6.2
*/
public function testPopsSpecifiedNumberOfElements(): void
{
$redis = $this->getClient();
$redis->rpush('letters', 'a', 'b', 'c', 'd', 'e', 'f');
$this->assertSame(array('a', 'b'), $redis->lpop('letters', 2));
$this->assertSame(array('c', 'd'), $redis->lpop('letters', 2));
$this->assertSame(array('e', 'f'), $redis->lrange('letters', 0, -1));
}
}
+1 -1
View File
@@ -85,7 +85,7 @@ class MOVE_Test extends PredisCommandTestCase
public function testThrowsExceptionOnInvalidDatabases(): void
{
$this->expectException('Predis\Response\ServerException');
$this->expectExceptionMessage('ERR index out of range');
$this->expectExceptionMessageMatches('/ERR.*out of range/');
$redis = $this->getClient();
+1 -1
View File
@@ -87,7 +87,7 @@ class SELECT_Test extends PredisCommandTestCase
public function testThrowsExceptionOnUnexpectedDatabaseName(): void
{
$this->expectException('Predis\Response\ServerException');
$this->expectExceptionMessage('ERR invalid DB index');
$this->expectExceptionMessageMatches('/ERR.*(invalid DB index|value is not an integer or out of range)/');
$redis = $this->getClient();
+3 -3
View File
@@ -185,11 +185,11 @@ class SORT_Test extends PredisCommandTestCase
$redis = $this->getClient();
$redis->lpush('list:unordered', $unordered = array(2, 100, 3, 1, 30, 10));
$this->assertEquals(
count($unordered),
$this->assertCount(
$redis->sort('list:unordered', array(
'store' => 'list:ordered',
))
)),
$unordered
);
$this->assertEquals(array(1, 2, 3, 10, 30, 100), $redis->lrange('list:ordered', 0, -1));
+98
View File
@@ -0,0 +1,98 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command\Redis;
/**
* @group commands
* @group realm-server
*/
class TOUCH_Test extends PredisCommandTestCase
{
/**
* {@inheritdoc}
*/
protected function getExpectedCommand(): string
{
return 'Predis\Command\Redis\TOUCH';
}
/**
* {@inheritdoc}
*/
protected function getExpectedId(): string
{
return 'TOUCH';
}
/**
* @requiresRedisVersion >= 3.2.1
*
* @group disconnected
*/
public function testFilterArguments(): void
{
$arguments = ['key1', 'key2', 'key3'];
$expected = ['key1', 'key2', 'key3'];
$command = $this->getCommand();
$command->setArguments($arguments);
$this->assertSame($expected, $command->getArguments());
}
/**
* @requiresRedisVersion >= 3.2.1
*
* @group disconnected
*/
public function testFilterArgumentsAsSingleArray(): void
{
$arguments = [['key1', 'key2', 'key3']];
$expected = ['key1', 'key2', 'key3'];
$command = $this->getCommand();
$command->setArguments($arguments);
$this->assertSame($expected, $command->getArguments());
}
/**
* @requiresRedisVersion >= 3.2.1
*
* @group disconnected
*/
public function testParseResponse(): void
{
$command = $this->getCommand();
$this->assertSame(10, $command->parseResponse(10));
}
/**
* @requiresRedisVersion >= 3.2.1
*
* @group connected
*/
public function testReturnsNumberOfDeletedKeys(): void
{
$redis = $this->getClient();
$this->assertSame(0, $redis->touch('foo'));
$redis->set('foo', 'bar');
$this->assertSame(1, $redis->touch('foo'));
$this->assertSame(1, $redis->touch('foo', 'hoge'));
$redis->set('hoge', 'piyo');
$this->assertSame(1, $redis->touch('foo'));
$this->assertSame(2, $redis->touch('foo', 'hoge'));
}
}
+102
View File
@@ -0,0 +1,102 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command\Redis;
/**
* @group commands
* @group realm-zset
*/
class ZPOPMAX_Test extends PredisCommandTestCase
{
/**
* {@inheritdoc}
*/
protected function getExpectedCommand(): string
{
return 'Predis\Command\Redis\ZPOPMAX';
}
/**
* {@inheritdoc}
*/
protected function getExpectedId(): string
{
return 'ZPOPMAX';
}
/**
* @requiresRedisVersion >= 5.0.0
*
* @group disconnected
*/
public function testFilterArguments(): void
{
$arguments = array('zset', 2);
$expected = array('zset', 2);
$command = $this->getCommand();
$command->setArguments($arguments);
$this->assertSame($expected, $command->getArguments());
}
/**
* @requiresRedisVersion >= 5.0.0
*
* @group disconnected
*/
public function testParseResponse(): void
{
$raw = array('element1', '1', 'element2', '2', 'element3', '3');
$expected = array('element1' => '1', 'element2' => '2', 'element3' => '3');
$command = $this->getCommand();
$this->assertSame($expected, $command->parseResponse($raw));
}
/**
* @requiresRedisVersion >= 5.0.0
*
* @group connected
*/
public function testReturnsElements(): void
{
$redis = $this->getClient();
$this->assertSame(array(), $redis->zpopmax('letters'));
$this->assertSame(array(), $redis->zpopmax('letters', 3));
$redis->zadd('letters', -10, 'a', 0, 'b', 10, 'c', 20, 'd', 20, 'e', 30, 'f');
$this->assertSame(array('f' => '30'), $redis->zpopmax('letters'));
$this->assertSame(array('e' => '20', 'd' => '20', 'c' => '10'), $redis->zpopmax('letters', 3));
$this->assertSame(array('b' => '0', 'a' => '-10'), $redis->zpopmax('letters', 3));
}
/**
* @requiresRedisVersion >= 5.0.0
*
* @group connected
*/
public function testThrowsExceptionOnWrongType(): void
{
$this->expectException('Predis\Response\ServerException');
$this->expectExceptionMessage('Operation against a key holding the wrong kind of value');
$redis = $this->getClient();
$redis->set('foo', 'bar');
$redis->zpopmax('foo');
}
}
+101
View File
@@ -0,0 +1,101 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command\Redis;
/**
* @group commands
* @group realm-zset
*/
class ZPOPMIN_Test extends PredisCommandTestCase
{
/**
* {@inheritdoc}
*/
protected function getExpectedCommand(): string
{
return 'Predis\Command\Redis\ZPOPMIN';
}
/**
* {@inheritdoc}
*/
protected function getExpectedId(): string
{
return 'ZPOPMIN';
}
/**
* @requiresRedisVersion >= 5.0.0
*
* @group disconnected
*/
public function testFilterArguments(): void
{
$arguments = array('zset', 2);
$expected = array('zset', 2);
$command = $this->getCommand();
$command->setArguments($arguments);
$this->assertSame($expected, $command->getArguments());
}
/**
* @requiresRedisVersion >= 5.0.0
*
* @group disconnected
*/
public function testParseResponse(): void
{
$raw = array('element1', '1', 'element2', '2', 'element3', '3');
$expected = array('element1' => '1', 'element2' => '2', 'element3' => '3');
$command = $this->getCommand();
$this->assertSame($expected, $command->parseResponse($raw));
}
/**
* @requiresRedisVersion >= 5.0.0
*
* @group connected
*/
public function testReturnsElements(): void
{
$redis = $this->getClient();
$this->assertSame(array(), $redis->zpopmin('letters'));
$this->assertSame(array(), $redis->zpopmin('letters', 3));
$redis->zadd('letters', -10, 'a', 0, 'b', 10, 'c', 20, 'd', 20, 'e', 30, 'f');
$this->assertSame(array('a' => '-10'), $redis->zpopmin('letters'));
$this->assertSame(array('b' => '0', 'c' => '10', 'd' => '20'), $redis->zpopmin('letters', 3));
$this->assertSame(array('e' => '20', 'f' => '30'), $redis->zpopmin('letters', 3));
}
/**
* @requiresRedisVersion >= 5.0.0
*
* @group connected
*/
public function testThrowsExceptionOnWrongType(): void
{
$this->expectException('Predis\Response\ServerException');
$this->expectExceptionMessage('Operation against a key holding the wrong kind of value');
$redis = $this->getClient();
$redis->set('foo', 'bar');
$redis->zpopmin('foo');
}
}
+1 -1
View File
@@ -90,7 +90,7 @@ class RedisFactoryTest extends PredisTestCase
$this->assertTrue($factory->supports('mock'));
$this->assertTrue($factory->supports('MOCK'));
$this->assertSame(get_class($command), $factory->getCommandClass('mock'));
$this->assertInstanceOf($factory->getCommandClass('mock'), $command);
}
/**
@@ -40,7 +40,7 @@ class PredisClusterTest extends PredisTestCase
$cluster->add($connection1);
$cluster->add($connection2);
$this->assertSame(2, count($cluster));
$this->assertCount(2, $cluster);
$this->assertSame($connection1, $cluster->getConnectionById('127.0.0.1:7001'));
$this->assertSame($connection2, $cluster->getConnectionById('127.0.0.1:7002'));
}
@@ -58,7 +58,7 @@ class PredisClusterTest extends PredisTestCase
$cluster->add($connection1);
$cluster->add($connection2);
$this->assertSame(2, count($cluster));
$this->assertCount(2, $cluster);
$this->assertSame($connection1, $cluster->getConnectionByAlias('node01'));
$this->assertSame($connection2, $cluster->getConnectionByAlias('node02'));
}
@@ -71,7 +71,7 @@ class RedisClusterTest extends PredisTestCase
$cluster->add($connection1);
$cluster->add($connection2);
$this->assertSame(2, count($cluster));
$this->assertCount(2, $cluster);
$this->assertSame($connection1, $cluster->getConnectionById('127.0.0.1:6379'));
$this->assertSame($connection2, $cluster->getConnectionById('127.0.0.1:6380'));
}
@@ -92,7 +92,7 @@ class RedisClusterTest extends PredisTestCase
$this->assertTrue($cluster->remove($connection1));
$this->assertFalse($cluster->remove($connection3));
$this->assertSame(1, count($cluster));
$this->assertCount(1, $cluster);
}
/**
@@ -110,7 +110,7 @@ class RedisClusterTest extends PredisTestCase
$this->assertTrue($cluster->removeById('127.0.0.1:6380'));
$this->assertFalse($cluster->removeById('127.0.0.1:6390'));
$this->assertSame(1, count($cluster));
$this->assertCount(1, $cluster);
}
/**
@@ -128,11 +128,11 @@ class RedisClusterTest extends PredisTestCase
$cluster->add($connection2);
$cluster->add($connection3);
$this->assertSame(3, count($cluster));
$this->assertCount(3, $cluster);
$cluster->remove($connection3);
$this->assertSame(2, count($cluster));
$this->assertCount(2, $cluster);
}
/**
@@ -977,7 +977,7 @@ class RedisClusterTest extends PredisTestCase
$this->assertSame('foobar', $cluster->executeCommand($command));
$this->assertSame('foobar', $cluster->executeCommand($command));
$this->assertSame(2, count($cluster));
$this->assertCount(2, $cluster);
}
/**
@@ -1033,7 +1033,7 @@ class RedisClusterTest extends PredisTestCase
$this->assertSame('foobar', $cluster->executeCommand($command));
$this->assertSame('foobar', $cluster->executeCommand($command));
$this->assertSame(2, count($cluster));
$this->assertCount(2, $cluster);
}
/**
@@ -1071,7 +1071,7 @@ class RedisClusterTest extends PredisTestCase
$this->assertSame('foobar', $cluster->executeCommand($command));
$this->assertSame('foobar', $cluster->executeCommand($command));
$this->assertSame(2, count($cluster));
$this->assertCount(2, $cluster);
}
/**
@@ -1121,7 +1121,7 @@ class RedisClusterTest extends PredisTestCase
$this->assertSame('foobar', $cluster->executeCommand($command));
$this->assertSame('foobar', $cluster->executeCommand($command));
$this->assertSame(3, count($cluster));
$this->assertCount(3, $cluster);
}
/**
@@ -1259,7 +1259,7 @@ class RedisClusterTest extends PredisTestCase
$cluster->add($connection1);
$this->assertSame('foobar', $cluster->executeCommand($cmdGET));
$this->assertSame(2, count($cluster));
$this->assertCount(2, $cluster);
}
/**
+2 -314
View File
@@ -44,108 +44,8 @@ class FactoryTest extends PredisTestCase
));
$this->assertSame($defaults, $factory->getDefaultParameters());
}
/**
* @group disconnected
*/
public function testSettingDefaultParametersForMasterRole(): void
{
$factory = new Factory();
$factory->setDefaultParameters($expected = array(
'role.master' => [
'username' => 'myusername',
'password' => 'secret',
'database' => 10,
]
));
$this->assertSame($expected, $factory->getDefaultParameters());
}
/**
* @group disconnected
*/
public function testSettingDefaultParametersForMasterRoleAcceptsArrayOnly(): void
{
$this->expectException('InvalidArgumentException');
$this->expectExceptionMessage('Default parameters for `role.master` must be passed as a named array');
$factory = new Factory();
$factory->setDefaultParameters(array(
'role.master' => 'invalid value',
));
}
/**
* @group disconnected
*/
public function testSettingDefaultParametersForSlaveRole(): void
{
$factory = new Factory();
$factory->setDefaultParameters($expected = array(
'role.slave' => [
'username' => 'myusername',
'password' => 'secret',
'database' => 10,
]
));
$this->assertSame($expected, $factory->getDefaultParameters());
}
/**
* @group disconnected
*/
public function testSettingDefaultParametersForSlaveRoleAcceptsArrayOnly(): void
{
$this->expectException('InvalidArgumentException');
$this->expectExceptionMessage('Default parameters for `role.slave` must be passed as a named array');
$factory = new Factory();
$factory->setDefaultParameters(array(
'role.slave' => 'invalid value',
));
}
/**
* @group disconnected
*/
public function testSettingDefaultParametersForSentinelRoleIgnoresUsernameAndPassword(): void
{
$factory = new Factory();
$factory->setDefaultParameters(array(
'role.sentinel' => [
'username' => 'myusername',
'password' => 'secret',
'database' => 10,
]
));
$expected = array(
'role.sentinel' => [
'password' => 'secret',
]
);
$this->assertSame($expected, $factory->getDefaultParameters());
}
/**
* @group disconnected
*/
public function testSettingDefaultParametersForSentinelRoleAcceptsArrayOnly(): void
{
$this->expectException('InvalidArgumentException');
$this->expectExceptionMessage('Default parameters for `role.sentinel` must be passed as a named array');
$factory = new Factory();
$factory->setDefaultParameters(array(
'role.sentinel' => 'invalid value',
));
$parameters = array('database' => 10, 'persistent' => true);
}
/**
@@ -295,7 +195,7 @@ class FactoryTest extends PredisTestCase
/**
* @group disconnected
*/
public function testCreateConnectionWithDefaultParametersDoNotOverrideExplicitInputParameters(): void
public function testCreateConnectionWithArrayParametersAndDefaults(): void
{
$factory = new Factory();
@@ -323,218 +223,6 @@ class FactoryTest extends PredisTestCase
$this->assertNull($parameters->path);
}
/**
* @group disconnected
*/
public function testCreateConnectionForSentinelRoleIgnoresUsernameAndDatabase(): void
{
$factory = new Factory();
$connection = $factory->create($inputParams = array(
'role' => 'sentinel',
'username' => 'myusername',
'password' => 'mypassword',
'database' => 10,
));
$parameters = $connection->getParameters();
$this->assertInstanceOf('Predis\Connection\NodeConnectionInterface', $connection);
$this->assertEquals($inputParams['role'], $parameters->role);
$this->assertEquals($inputParams['password'], $parameters->password);
$this->assertNull($parameters->username);
$this->assertNull($parameters->database);
}
/**
* @group disconnected
*/
public function testCreateConnectionForSentinelRoleDoesNotInheritPasswordFromGlobalDefaultParameters(): void
{
$factory = new Factory();
$factory->setDefaultParameters($defaultParams = array(
'password' => 'pwd.default',
));
$connectionSentinelRole = $factory->create($inputParamsSentinelRole = array(
'role' => 'sentinel',
));
$parameters = $connectionSentinelRole->getParameters();
$this->assertNull($parameters->password);
}
/**
* @group disconnected
*/
public function testCreateConnectionForSentinelRoleDoesNotInheritUsernameFromGlobalDefaultParameters(): void
{
$factory = new Factory();
$factory->setDefaultParameters($defaultParams = array(
'username' => 'usr.default',
));
$connectionSentinelRole = $factory->create($inputParamsSentinelRole = array(
'role' => 'sentinel',
));
$parameters = $connectionSentinelRole->getParameters();
$this->assertNull($parameters->username);
}
/**
* @group disconnected
*/
public function testCreateConnectionForSentinelRoleDoesNotInheritDatabaseFromGlobalDefaultParameters(): void
{
$factory = new Factory();
$factory->setDefaultParameters($defaultParams = array(
'database' => 15,
));
$connectionSentinelRole = $factory->create($inputParamsSentinelRole = array(
'role' => 'sentinel',
));
$parameters = $connectionSentinelRole->getParameters();
$this->assertNull($parameters->database);
}
/**
* @group disconnected
*/
public function testCreateConnectionWithDefaultRoleParametersDoNotOverrideExplicitInputParameters(): void
{
$factory = new Factory();
$factory->setDefaultParameters($defaultParams = array(
'timeout' => 20,
'password' => 'pwd.default.norole',
'role.master' => [
'password' => 'pwd.role.master',
'timeout' => 10,
],
'role.slave' => [
'password' => 'pwd.role.slave',
'timeout' => 5,
],
'role.sentinel' => [
'password' => 'pwd.role.sentinel',
'timeout' => 1,
],
));
// NO ROLE
$connectionNoRole = $factory->create($inputParamsNoRole = array(
'password' => 'pwd.local.norole',
'timeout' => 30,
));
$parameters = $connectionNoRole->getParameters();
$this->assertEquals('pwd.local.norole', $parameters->password);
$this->assertEquals(30, $parameters->timeout);
// ROLE MASTER
$connectionMasterRole = $factory->create($inputParamsMasterRole = array(
'role' => 'master',
'password' => 'pwd.local.master',
'timeout' => 30,
));
$parameters = $connectionMasterRole->getParameters();
$this->assertEquals('pwd.local.master', $parameters->password);
$this->assertEquals(30, $parameters->timeout);
// ROLE SLAVE
$connectionSlaveRole = $factory->create($inputParamsSlaveRole = array(
'role' => 'slave',
'password' => 'pwd.local.slave',
'timeout' => 30,
));
$parameters = $connectionSlaveRole->getParameters();
$this->assertEquals('pwd.local.slave', $parameters->password);
$this->assertEquals(30, $parameters->timeout);
// ROLE SENTINEL
$connectionSentinelRole = $factory->create($inputParamsSentinelRole = array(
'role' => 'slave',
'password' => 'pwd.local.sentinel',
'timeout' => 30,
));
$parameters = $connectionSentinelRole->getParameters();
$this->assertEquals('pwd.local.sentinel', $parameters->password);
$this->assertEquals(30, $parameters->timeout);
}
/**
* @group disconnected
*/
public function testCreateConnectionWithDefaultRoleParametersOverridesDefaultGlobalParameters(): void
{
$factory = new Factory();
$factory->setDefaultParameters($defaultParams = array(
'timeout' => 20,
'password' => 'pwd.default.norole',
'role.master' => [
'password' => 'pwd.role.master',
'timeout' => 10,
],
'role.slave' => [
'password' => 'pwd.role.slave',
'timeout' => 5,
],
'role.sentinel' => [
'password' => 'pwd.role.sentinel',
'timeout' => 1,
],
));
// NO ROLE
$connectionNoRole = $factory->create($inputParamsNoRole = array(
// EMPTY
));
$parameters = $connectionNoRole->getParameters();
$this->assertEquals('pwd.default.norole', $parameters->password);
$this->assertEquals(20, $parameters->timeout);
// ROLE MASTER
$connectionMasterRole = $factory->create($inputParamsMasterRole = array(
'role' => 'master',
));
$parameters = $connectionMasterRole->getParameters();
$this->assertEquals('pwd.role.master', $parameters->password);
$this->assertEquals(10, $parameters->timeout);
// ROLE SLAVE
$connectionSlaveRole = $factory->create($inputParamsSlaveRole = array(
'role' => 'slave',
));
$parameters = $connectionSlaveRole->getParameters();
$this->assertEquals('pwd.role.slave', $parameters->password);
$this->assertEquals(5, $parameters->timeout);
// ROLE SENTINEL
$connectionSentinelRole = $factory->create($inputParamsSentinelRole = array(
'role' => 'sentinel',
));
$parameters = $connectionSentinelRole->getParameters();
$this->assertEquals('pwd.role.sentinel', $parameters->password);
$this->assertEquals(1, $parameters->timeout);
}
/**
* @group disconnected
*/
@@ -41,7 +41,7 @@ class SentinelReplicationTest extends PredisTestCase
public function testParametersForSentinelConnectionShouldUsePasswordForAuthentication(): void
{
$replication = $this->getReplicationConnection('svc', array(
'tcp://127.0.0.1:5381?password=secret',
'tcp://127.0.0.1:5381?alias=sentinel1&password=secret',
));
$parameters = $replication->getSentinelConnection()->getParameters()->toArray();
@@ -122,9 +122,9 @@ class SentinelReplicationTest extends PredisTestCase
*/
public function testMethodGetSentinelConnectionReturnsFirstAvailableSentinel(): void
{
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?role=sentinel');
$sentinel2 = $this->getMockSentinelConnection('tcp://127.0.0.1:5382?role=sentinel');
$sentinel3 = $this->getMockSentinelConnection('tcp://127.0.0.1:5383?role=sentinel');
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?role=sentinel&alias=sentinel1');
$sentinel2 = $this->getMockSentinelConnection('tcp://127.0.0.1:5382?role=sentinel&alias=sentinel2');
$sentinel3 = $this->getMockSentinelConnection('tcp://127.0.0.1:5383?role=sentinel&alias=sentinel3');
$replication = $this->getReplicationConnection('svc', array($sentinel1, $sentinel2, $sentinel3));
@@ -305,16 +305,15 @@ class SentinelReplicationTest extends PredisTestCase
// TODO: sorry for the smell...
$reflection = new \ReflectionProperty($replication, 'sentinels');
$reflection->setAccessible(true);
$retrievedSentinels = $reflection->getValue($replication);
$expectedSentinels = array(
array('scheme' => 'tcp', 'host' => '127.0.0.1', 'port' => '5381', 'role' => 'sentinel'),
array('host' => '127.0.0.1', 'port' => '5382', 'role' => 'sentinel'),
array('host' => '127.0.0.1', 'port' => '5383', 'role' => 'sentinel'),
$expected = array(
array('host' => '127.0.0.1', 'port' => '5381'),
array('host' => '127.0.0.1', 'port' => '5382'),
array('host' => '127.0.0.1', 'port' => '5383'),
);
$this->assertSame($sentinel1, $replication->getSentinelConnection());
$this->assertEquals($expectedSentinels, $retrievedSentinels);
$this->assertSame($expected, array_intersect_key($expected, $reflection->getValue($replication)));
}
/**
@@ -322,7 +321,7 @@ class SentinelReplicationTest extends PredisTestCase
*/
public function testMethodUpdateSentinelsRemovesCurrentSentinelAndRetriesNextOneOnFailure(): void
{
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?role=sentinel');
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?role=sentinel&alias=sentinel1');
$sentinel1
->expects($this->once())
->method('executeCommand')
@@ -333,7 +332,7 @@ class SentinelReplicationTest extends PredisTestCase
new Connection\ConnectionException($sentinel1, 'Unknown connection error [127.0.0.1:5381]')
);
$sentinel2 = $this->getMockSentinelConnection('tcp://127.0.0.1:5382?role=sentinel');
$sentinel2 = $this->getMockSentinelConnection('tcp://127.0.0.1:5382?role=sentinel&alias=sentinel2');
$sentinel2
->expects($this->once())
->method('executeCommand')
@@ -358,15 +357,14 @@ class SentinelReplicationTest extends PredisTestCase
// TODO: sorry for the smell...
$reflection = new \ReflectionProperty($replication, 'sentinels');
$reflection->setAccessible(true);
$retrievedSentinels = $reflection->getValue($replication);
$expectedSentinels = array(
array('scheme' => 'tcp', 'host' => '127.0.0.1', 'port' => '5382', 'role' => 'sentinel'),
array('host' => '127.0.0.1', 'port' => '5383', 'role' => 'sentinel'),
$expected = array(
array('host' => '127.0.0.1', 'port' => '5382'),
array('host' => '127.0.0.1', 'port' => '5383'),
);
$this->assertSame($sentinel2, $replication->getSentinelConnection());
$this->assertEquals($expectedSentinels, $retrievedSentinels);
$this->assertSame($expected, array_intersect_key($expected, $reflection->getValue($replication)));
}
/**
@@ -397,7 +395,7 @@ class SentinelReplicationTest extends PredisTestCase
*/
public function testMethodQuerySentinelFetchesMasterNodeSlaveNodesAndSentinelNodes(): void
{
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?role=sentinel');
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?role=sentinel&alias=sentinel1');
$sentinel1
->expects($this->exactly(3))
->method('executeCommand')
@@ -444,7 +442,7 @@ class SentinelReplicationTest extends PredisTestCase
)
);
$sentinel2 = $this->getMockSentinelConnection('tcp://127.0.0.1:5382?role=sentinel');
$sentinel2 = $this->getMockSentinelConnection('tcp://127.0.0.1:5382?role=sentinel&alias=sentinel2');
$master = $this->getMockConnection('tcp://127.0.0.1:6381?role=master');
$slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?role=slave');
@@ -456,15 +454,14 @@ class SentinelReplicationTest extends PredisTestCase
// TODO: sorry for the smell...
$reflection = new \ReflectionProperty($replication, 'sentinels');
$reflection->setAccessible(true);
$retrievedSentinels = $reflection->getValue($replication);
$expectedSentinels = array(
array('scheme' => 'tcp', 'host' => '127.0.0.1', 'port' => '5381', 'role' => 'sentinel'),
array('host' => '127.0.0.1', 'port' => '5382', 'role' => 'sentinel'),
$sentinels = array(
array('host' => '127.0.0.1', 'port' => '5381'),
array('host' => '127.0.0.1', 'port' => '5382'),
);
$this->assertSame($sentinel1, $replication->getSentinelConnection());
$this->assertEquals($expectedSentinels, $retrievedSentinels);
$this->assertSame($sentinels, array_intersect_key($sentinels, $reflection->getValue($replication)));
$master = $replication->getMaster();
$slaves = $replication->getSlaves();
+1 -1
View File
@@ -749,7 +749,7 @@ class MultiExecTest extends PredisTestCase
$tx->set('hoge', 'piyo');
});
$this->assertSame(1, count($responses));
$this->assertCount(1, $responses);
$this->assertSame(0, $client->exists('foo'));
$this->assertSame(1, $client->exists('hoge'));
}