Compare commits

..

37 Commits

Author SHA1 Message Date
Daniele Alessandri aa1b070f9b Bump VERSION and update CHANGELOG. 2013-02-03 13:59:55 +01:00
Daniele Alessandri 3e125c964c Implement Predis\Session\SessionHandler.
This class makes it easy to use Predis to store PHP sessions on Redis.

NOTE: requires PHP >= 5.4.0 or a polyfill for PHP's SessionHandlerInterface.
2013-02-02 15:14:06 +01:00
Daniele Alessandri e9fdc47d3f Minor fix in readme.
[ci skip]
2013-02-02 10:48:22 +01:00
Daniele Alessandri d3930ea298 Update markdown files to use relative links.
See https://help.github.com/articles/relative-links-in-readmes for details.

[ci skip]
2013-02-02 10:44:54 +01:00
Daniele Alessandri 0efcbb7992 Add a way to get the default value of an option from options.
It is not possible to get the default value of a client option using
either its name or instance:

  $options = array(
    'profile' => function ($options, $option) {
      // instance of Predis\Option\OptionInterface
      $profile = $options->getDefault($option);

      // string representing an option handled by $options,
      // returns NULL if the specified name is not handled.
      $profile = $options->getDefault('profile');

      return $profile;
    },
  );

This addition makes it less awkward to get the default value of an
option, especially when not in the context of a callable option
initializer.
2013-02-02 10:30:53 +01:00
Daniele Alessandri f2af247c63 Push minor changes in the standard executor internals. 2013-01-29 12:38:19 +01:00
Daniele Alessandri a5cf6d72cd Fix standard pipeline executor not parsing raw replies.
This bug was actually introduced right before pushing the stable release
of v0.8.0 in which we moved the responsibility of parsing raw replies
with command parser to consumer classes.

This commit closes #101.
2013-01-29 12:13:01 +01:00
Daniele Alessandri 7173f0c80c Get back to development. 2013-01-29 11:55:47 +01:00
Daniele Alessandri 495e3c6f8a Bump VERSION and update CHANGELOG.
[ci skip]
2013-01-19 11:18:58 +01:00
Daniele Alessandri 3465bc7c1f Add PHP 5.5 to the CI build matrix and switch to branch blacklisting. 2013-01-19 11:16:20 +01:00
Daniele Alessandri 8bf896f81f Update CHANGELOG. 2013-01-19 09:56:51 +01:00
Daniele Alessandri 0085bc08ae Fix CHANGELOG. 2013-01-19 09:46:58 +01:00
Daniele Alessandri f7232b9ddc Highlight PHP code in FAQ. 2013-01-19 09:44:14 +01:00
Daniele Alessandri 95cc528904 Remove <?php tags from README.
It seems like GitHub can now highlight PHP syntax without those ones.
2013-01-19 09:44:09 +01:00
Daniele Alessandri 4a16cb9417 Update .gitignore.
[ci skip]
2013-01-13 13:54:09 +01:00
Daniele Alessandri 94758d5f58 Update CHANGELOG.
[ci skip]
2013-01-13 13:53:22 +01:00
Daniele Alessandri acc0f04bdb Add missing param to phpdoc entry.
[ci skip]
2013-01-13 13:48:50 +01:00
Daniele Alessandri 09de7be7cb Add optional callable to drive extraction of node hash in distributor.
This is mainly in response to the longstanding issue #36 in which my
proposed solution was fine in terms of functionalities, but eventually
never made into the repository since it was far from being clean enough
for my taste.

Now developers can optionally pass a callable object when creating the
hashring instance to decide how the distributor should extract the hash
from a node (really a connection instance) to populate the ring:

  use Predis\Cluster\Distribution\HashRing;
  use Predis\Connection\PredisCluster;

  $servers = array(
    'tcp://10.0.0.1?alias=node01',
    'tcp://10.0.0.2?alias=node02',
  );

  $options = array(
    'nodehash' => function ($connection) {
      return $connection->getParameters()->alias;
    },
    'cluster' => function ($options) {
      $replicas = HashRing::DEFAULT_REPLICAS;
      $hashring = new HashRing($replicas, $options->nodehash);
      $cluster  = new PredisCluster($hashring);

      return $cluster;
    },
  );

  $client = new Predis\Client($servers, $options);

Both HashRing and KetamaPureRing in the Predis\Cluster\Distribution
namespace support this new approach.
2013-01-13 13:10:01 +01:00
Daniele Alessandri 70b279bbdc Bump year in LICENSE.
On a related note, happy new year!

[ci skip]
2013-01-01 13:58:18 +01:00
Daniele Alessandri f8cbbc5b8f Update URL for phpiredis.
Ownership of the repository has been transferred. Thanks again to
@seppo0010, the original author of phpiredis, for his work on the
extension!

[ci skip]
2012-12-28 20:51:34 +01:00
Daniele Alessandri 83720075f3 Make it possible to cast key prefix processor instance to string.
Mostly useful with string interpolation when getting the current prefix
associated to a client instance.
2012-12-27 10:50:25 +01:00
Daniele Alessandri 9901233fa1 Instantiate the current class when subclassing Client.
Previously the getClientFor() method in a subclass of Predis\Client
returned an instance of Predis\Client instead of a new instance of
the subclass. The new behaviour is more correct.
2012-12-24 14:50:07 +01:00
Daniele Alessandri dcb4093046 Update CHANGELOG. 2012-12-15 17:46:00 +01:00
Daniele Alessandri 1e8af648cb [tests] Add missing tests for Predis\Option\ClientReplication. 2012-12-15 17:22:10 +01:00
Daniele Alessandri ff5e3515c3 Implement callable initializer for "connections" client option. 2012-12-15 17:12:37 +01:00
Daniele Alessandri 59813cd74e Pass option handler instance to callable initializers.
This is just a convention implemented to client options supporting
callable initializers such as "profile", "cluster" and "replication".

This is useful to get a fully-initialized default value and perform
additional operations before returning it. An example with "profile":

  $options = array(
    'commands' => array(
      'test1' => 'Predis\Command\ConnectionEcho',
      'test2' => 'Predis\Command\ConnectionEcho',
    ),
    'profile'  => function ($options, $option) {
      $profile = $option->getDefault($options);

      if (is_array($options->commands)) {
        foreach ($options->commands as $id => $cmd) {
          $profile->defineCommand($id, $cmd);
        }
      }

      return $profile;
    },
  );
2012-12-15 16:47:32 +01:00
Daniele Alessandri bfd96b15dc Fix response parsing with scripted commands after -NOSCRIPT.
This commit fixes issue #94.
2012-12-12 14:28:06 +01:00
Daniele Alessandri 51b466267d Fix missing use directives.
This miss caused a PHP error when Redis did not return a +QUEUED
reply inside a MULTI / EXEC command.
2012-11-21 22:57:23 +01:00
Daniele Alessandri 78f3596566 Merge branch 'tests/update-redis-2.8' into v0.8 2012-11-21 22:13:42 +01:00
Daniele Alessandri ac01c1a17f [tests] TTL and PTTL return -2 on non existing keys in Redis >= 2.8. 2012-11-21 22:09:05 +01:00
Daniele Alessandri 46920c9c77 [tests] Fix expected exception message on wrong key type.
Redis >= 2.8 returns -WRONGTYPE errors instead of -ERR when executing
operations on wrong key type (such as trying to LPUSH on a string key).

Luckily for us, phpunit's @expectedExceptionMessage annotation actually
does not perform an exact match but works on a substring so we just omit
the initial part of the exception message to make the test work.
2012-11-21 21:49:49 +01:00
Daniele Alessandri b26d6103a6 Avoid channels reordering issues when testing UNSUBSCRIBE.
When using UNSUBSCRIBE without a list of channels (which actually means
"unsubscribe from all the subscribed channels") Redis 2.6 does not
guarantee that channels are returned following the same order of
subscription.
2012-11-13 16:44:55 +01:00
Daniele Alessandri a4760d65cd Bump Redis version used in tests on Travis CI.
It seems like Travis CI switched silently to Redis 2.6, which means
that we can enable the full test suite of Predis.
2012-11-13 16:13:07 +01:00
Daniele Alessandri 49aa6f0aca Update performance numbers in the related FAQ section.
We use newer version of PHP, phpiredis, phpredis, Redis and Ubuntu.

[ci skip]
2012-11-08 13:06:24 +01:00
Daniele Alessandri 292f9939b2 Tweak CONTRIBUTING instructions.
[ci skip]
2012-11-03 16:02:43 +01:00
Daniele Alessandri daa36a980d Make Predis\Connection\PhpiredisConnection::write() protected.
We should actually make use of more protected methods in this
class instead of the private ones, this is most likely going
to be addressed in future commits.

See also issue #86 on GitHub for the reason behind this change.
2012-11-03 15:21:52 +01:00
Daniele Alessandri 0b09d2c359 Back to development for the next patch release. 2012-11-03 15:16:01 +01:00
112 changed files with 807 additions and 207 deletions
+2
View File
@@ -2,4 +2,6 @@
*.phar
phpunit.xml
package.xml
composer.lock
experiments/
vendor/
+6 -4
View File
@@ -2,10 +2,12 @@ language: php
php:
- 5.3
- 5.4
- 5.5
branches:
only:
- master
- v0.7
- v0.8
except:
- v0.5
- v0.6
- php5.2_backport
- documentation
services: redis-server
script: phpunit -c phpunit.xml.travisci
+49 -2
View File
@@ -1,3 +1,50 @@
v0.8.2 (2013-02-03)
===============================================================================
- Added `Predis\Session\SessionHandler` to make it easy to store PHP sessions
on Redis using Predis. Please note that this class needs either PHP >= 5.4.0
or a polyfill for PHP's `SessionHandlerInterface`.
- Added the ability to get the default value of a client option directly from
`Predis\Option\ClientOption` using the `getDefault()` method by passing the
option name or its instance.
- __FIX__: the standard pipeline executor was not using the response parser
methods associated to commands to process raw responses (ISSUE #101).
v0.8.1 (2013-01-19)
===============================================================================
- The `connections` client option can now accept a callable object returning
an instance of `Predis\Connection\ConnectionFactoryInterface`.
- Client options accepting callable objects as factories now pass their actual
instance to the callable as the second argument.
- `Predis\Command\Processor\KeyPrefixProcessor` can now be directly casted to
string to obtain the current prefix, useful with string interpolation.
- Added an optional callable argument to `Predis\Cluster\Distribution\HashRing`
and `Predis\Cluster\Distribution\KetamaPureRing` constructor that can be used
to customize how the distributor should extract the connection hash when
initializing the nodes distribution (ISSUE #36).
- Correctly handle `TTL` and `PTTL` returning -2 on non existing keys starting
with Redis 2.8.
- __FIX__: a missing use directive in `Predis\Transaction\MultiExecContext`
caused PHP errors when Redis did not return `+QUEUED` replies to commands
when inside a MULTI / EXEC context.
- __FIX__: the `parseResponse()` method implemented for a scripted command was
ignored when retrying to execute a Lua script by falling back to `EVAL` after
a `-NOSCRIPT` error (ISSUE #94).
- __FIX__: when subclassing `Predis\Client` the `getClientFor()` method returns
a new instance of the subclass instead of a new instance of `Predis\Client`.
v0.8.0 (2012-10-23)
===============================================================================
@@ -351,7 +398,7 @@ v0.6.0 (2010-05-24)
to instances of Redis 1.2.x).
- Support for Redis 1.0 is now optional and it is provided by requiring
'Predis_Compatibility.php' before creating an instance of Predis\Client.
'Predis_Compatibility.php' before creating an instance of `Predis\Client`.
- New commands added to the Redis 2.0 profile since Predis 0.5.1:
- Strings: `SETEX`, `APPEND`, `SUBSTR`
@@ -364,7 +411,7 @@ v0.6.0 (2010-05-24)
- Introduced client-level options with the new `Predis\ClientOptions` class.
Options can be passed to the constructor of `Predis\Client` in its second
argument as an array or an instance of Predis\ClientOptions. For brevity's
argument as an array or an instance of `Predis\ClientOptions`. For brevity's
sake and compatibility with older versions, the constructor still accepts
an instance of `Predis\RedisServerProfile` in its second argument. The
currently supported client options are:
+5 -4
View File
@@ -6,10 +6,11 @@ section of the project.
When reporting bugs, in addition to the obvious description of your issue you __must__ always provide
some essential information about your environment such as:
1. version of Predis.
2. version of PHP.
3. name and version of the operating system.
4. when possible, a small snippet of code that reproduces the issue.
1. version of Predis (check the `VERSION` file or the `Predis\Client::VERSION` constant).
2. version of Redis (check the `redis_version` field returned by [`INFO`](http://redis.io/commands/info)).
3. version of PHP.
4. name and version of the operating system.
5. when possible, a small snippet of code that reproduces the issue.
__Think about it__: we do not have a crystal ball and cannot predict things and peer into the unknown,
so please provide as much details as possible to help us isolating issues and fix them.
+28 -26
View File
@@ -37,7 +37,7 @@ connections to the server, but this behavior can be inconvenient in certain scen
need to do an upfront check to detect if the server is up and running and eventually catch exceptions on
failures. In this case developers can use `Predis\Client::connect()` to explicitly connect to the server:
```
```php
$client = new Predis\Client();
try {
@@ -59,7 +59,7 @@ Redis works or if you need to look up how to use certain commands. Alternatively
accept an array for keys or values (depending on the command) instead of a list of arguments. See for
example how [RPUSH](http://redis.io/commands/rpush) or [HMSET](http://redis.io/commands/hmset) work:
```
```php
$client->rpush('my:list', 'value1', 'value2', 'value3'); // values as arguments
$client->rpush('my:list', array('value1', 'value2', 'value3')); // values as single argument array
@@ -68,7 +68,7 @@ $client->hmset('my:hash', array('field1'=>'value1', 'field2'=>'value2'); // valu
```
The only exception to this _rule_ is the [SORT](http://redis.io/commands/sort) command for which modifiers are
[passed using a named array](https://github.com/nrk/predis/blob/master/tests/Predis/Command/KeySortTest.php#L56-77).
[passed using a named array](tests/Predis/Command/KeySortTest.php#L56-77).
@@ -79,18 +79,18 @@ _________________________________________________
### Predis is a pure-PHP implementation: it can not be fast enough! ###
It really depends, but most of the times the answer is: _yes, it is fast enough_. I will give you
a couple of easy numbers using a single Predis client with PHP 5.3.5 (custom build) and Redis 2.2
(localhost) under Ubuntu 11.04 (running on a Intel Q6600):
a couple of easy numbers using a single Predis client with PHP 5.4.7 (custom build) and Redis 2.2
(localhost) under Ubuntu 12.04.1 (running on a Intel Q6600):
19600 SET/sec using 12 bytes for both key and value
18900 GET/sec while retrieving the very same values
0.200 seconds to fetch 30000 keys using _KEYS *_.
21500 SET/sec using 12 bytes for both key and value
21000 GET/sec while retrieving the very same values
0.130 seconds to fetch 30000 keys using _KEYS *_.
How does it compare with a nice C-based extension such as [__phpredis__](http://github.com/nicolasff/phpredis)?
30500 SET/sec using 12 bytes for both key and value
31000 GET/sec while retrieving the very same values
0.030 seconds to fetch 30000 keys using "KEYS *"".
30100 SET/sec using 12 bytes for both key and value
29400 GET/sec while retrieving the very same values
0.035 seconds to fetch 30000 keys using "KEYS *"".
Wow, __phpredis__ looks so much faster! Well we are comparing a C extension with a pure-PHP library so
lower numbers are quite expected, but there is a fundamental flaw in them: is this really how you are
@@ -104,14 +104,14 @@ Redis, but how these numbers change when we hit the network by connecting to ins
reside on other servers?
Using Predis:
3600 SET/sec using 12 bytes for both key and value
3600 GET/sec while retrieving the very same values
0.210 seconds to fetch 30000 keys using "KEYS *".
3200 SET/sec using 12 bytes for both key and value
3200 GET/sec while retrieving the very same values
0.132 seconds to fetch 30000 keys using "KEYS *".
Using phpredis:
4000 SET/sec using 12 bytes for both key and value
4000 GET/sec while retrieving the very same values
0.051 seconds to fetch 30000 keys using "KEYS *".
3500 SET/sec using 12 bytes for both key and value
3500 GET/sec while retrieving the very same values
0.045 seconds to fetch 30000 keys using "KEYS *".
There you go, you get almost the same average numbers and the reason is quite simple: network latency
is a real performance killer and you cannot do (almost) anything about that. As a disclaimer, please
@@ -124,14 +124,16 @@ to how your application will use Redis.
### I am convinced, but performances for multi-bulk replies (e.g. _KEYS *_) are still worse ###
Fair enough, but there is actually an option for you if you need even more speed and it consists on
installing __[phpiredis](http://github.com/seppo0010/phpiredis)__ (note the additional _i_ in the
name) and let Predis using it. __phpiredis__ is a C-based extension that wraps __hiredis__ (the
official Redis C client library) with a thin layer that exposes its features to PHP. You will now
get the benefits of a faster protocol parser just by adding a single line of code in your application:
installing __[phpiredis](http://github.com/nrk/phpiredis)__ (note the additional _i_ in the name)
and let Predis using it. __phpiredis__ is a C-based extension that wraps __hiredis__ (the official
Redis C client library) with a thin layer that exposes its features to PHP. You will now get the
benefits of a faster protocol parser just by adding a single line of code in your application:
$client = new Predis\Client('tcp://127.0.0.1', array(
'connections' => array('tcp' => 'Predis\Connection\PhpiredisConnection')
));
```php
$client = new Predis\Client('tcp://127.0.0.1', array(
'connections' => array('tcp' => 'Predis\Connection\PhpiredisConnection')
));
```
As simple as it is, nothing will really change in the way you use the library in your application. So,
how fast is it now? There are not much improvements for inline or short bulk replies (e.g. _SET_ or
@@ -139,8 +141,8 @@ _GET_), but the speed for parsing multi-bulk replies is now on par with phpredis
Using Predis with a phpiredis-based connection to fetch 30000 keys using _KEYS *_:
0.031 seconds from a local Redis instance
0.058 seconds from a remote Redis instance
0.035 seconds from a local Redis instance
0.047 seconds from a remote Redis instance
### If I need to install a C extension to get better performances, why not using phpredis? ###
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright (c) 2009-2012 Daniele Alessandri
Copyright (c) 2009-2013 Daniele Alessandri
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
+14 -21
View File
@@ -3,7 +3,7 @@
Predis is a flexible and feature-complete PHP (>= 5.3) client library for the Redis key-value store.
The library does not require any additional extension loaded in PHP but it can be optionally paired
with the [phpiredis](https://github.com/seppo0010/phpiredis) C extension to lower the overhead of
with the [phpiredis](https://github.com/nrk/phpiredis) C-based extension to lower the overhead of
serializing and parsing the Redis protocol. Predis is also available in an asynchronous fashion
through the experimental client provided by the [Predis\Async](http://github.com/nrk/predis-async)
library.
@@ -46,7 +46,7 @@ compatible with most of the major frameworks and libraries. Autoloading in your
automatically when managing the dependencies with Composer, but you can also leverage its own autoloader
class if you are going to use it in a project or script without any PSR-0 compliant autoloading facility:
``` php
```php
<?php
// prepend a base path if Predis is not present in your "include_path".
require 'Predis/Autoloader.php';
@@ -68,8 +68,7 @@ using functions such as `require` and `include`, but this practice is not encour
By default Predis uses `127.0.0.1` and `6379` as the default host and port when creating a new client
instance without specifying any connection parameter:
``` php
<?php
```php
$redis = new Predis\Client();
$redis->set('foo', 'bar');
$value = $redis->get('foo');
@@ -77,8 +76,7 @@ $value = $redis->get('foo');
It is possible to specify the various connection parameters using URI strings or named arrays:
``` php
<?php
```php
$redis = new Predis\Client('tcp://10.0.0.1:6379');
// is equivalent to:
@@ -98,8 +96,7 @@ Furthermore, pipelining works transparently even on aggregated connections. To a
supports client-side sharding using consistent-hashing on keys while clustered connections are supported
natively by the client class.
``` php
<?php
```php
$redis = new Predis\Client(array(
array('host' => '10.0.0.1', 'port' => 6379),
array('host' => '10.0.0.2', 'port' => 6379)
@@ -117,11 +114,10 @@ $replies = $redis->pipeline(function ($pipe) {
### Multiple and customizable connection backends ###
Predis can optionally use different connection backends to connect to Redis. One of them leverages
the [phpiredis](http://github.com/seppo0010/phpiredis) C extension resulting in a major speed bump
the [phpiredis](http://github.com/nrk/phpiredis) C-based extension resulting in a major speed bump
especially when dealing with long multibulk replies (the `socket` extension is also required):
``` php
<?php
```php
$client = new Predis\Client('tcp://127.0.0.1', array(
'connections' => array('tcp' => 'Predis\Connection\PhpiredisConnection')
));
@@ -131,8 +127,7 @@ Developers can also create their own connection backends to add support for new
existing ones or provide different implementations. Connection backend classes must implement
`Predis\Connection\SingleConnectionInterface` or extend `Predis\Connection\AbstractConnection`:
``` php
<?php
```php
class MyConnectionClass implements Predis\Connection\SingleConnectionInterface
{
// implementation goes here
@@ -145,7 +140,7 @@ $client = new Predis\Client('tcp://127.0.0.1', array(
```
For a more in-depth insight on how to create new connection backends you can look at the actual
implementation of the classes contained in `Predis\Connection` namespace.
implementation of the classes contained in the `Predis\Connection` namespace.
### Defining and registering new commands on the client at runtime ###
@@ -156,8 +151,7 @@ code or waiting for it to find its way into a stable Predis release, then you ca
a new class that matches the command type and its behaviour and then bind it to a client instance at
runtime. Actually, it is easier done than said:
``` php
<?php
```php
class BrandNewRedisCommand extends Predis\Command\AbstractCommand
{
public function getId()
@@ -181,8 +175,7 @@ in the server profile being used by the client instance. Internally, scripted co
to save bandwidth, but they are capable of falling back to [EVAL](http://redis.io/commands/eval)
when needed:
``` php
<?php
```php
class ListPushRandomValue extends Predis\Command\ScriptedCommand
{
public function getKeysCount()
@@ -221,7 +214,7 @@ Redis. If you do not have Redis up and running, integration tests can be disable
suite is configured to execute integration tests using the server profile for Redis v2.4 (which is the
current stable version of Redis). You can optionally run the suite against a Redis instance built from
the `unstable` branch with the development profile by changing the `REDIS_SERVER_VERSION` to `dev` in
the `phpunit.xml` file. More details about testing Predis are available in `tests/README.md`.
the `phpunit.xml` file. More details on testing Predis can be found in [the tests README](tests/README.md).
Predis uses Travis CI for continuous integration. You can find the results of the test suite and the build
history [on its project page](http://travis-ci.org/nrk/predis).
@@ -255,8 +248,8 @@ history [on its project page](http://travis-ci.org/nrk/predis).
- [Lorenzo Castelli](http://github.com/lcastelli)
- [Jordi Boggiano](http://github.com/Seldaek) ([twitter](http://twitter.com/seldaek))
- [Sebastian Waisbrot](http://github.com/seppo0010) ([twitter](http://twitter.com/seppo0010))
for his work on extending [phpiredis](http://github.com/seppo0010/phpiredis) for Predis
for his past work on extending [phpiredis](http://github.com/nrk/phpiredis) for Predis.
## License ##
The code for Predis is distributed under the terms of the MIT license (see LICENSE).
The code for Predis is distributed under the terms of the MIT license (see [LICENSE](LICENSE)).
+1 -1
View File
@@ -1 +1 @@
0.8.0
0.8.2
+2 -2
View File
@@ -51,8 +51,8 @@ $parameters = array(
);
$options = array(
'profile' => function ($options) {
$profile = ServerProfile::get('2.6');
'profile' => function ($options, $option) {
$profile = $options->getDefault($option);
$profile->defineCommand('hmgetall', 'HashMultipleGetAll');
return $profile;
+39
View File
@@ -0,0 +1,39 @@
<?php
require 'SharedConfigurations.php';
// This example demonstrates how to leverage Predis to save PHP sessions on Redis.
//
// The value of `session.gc_maxlifetime` in `php.ini` will be used by default as the
// the TTL for keys holding session data on Redis, but this value can be overridden
// when creating the session handler instance with the `gc_maxlifetime` option.
//
// Note that this class needs PHP >= 5.4 but can be used on PHP 5.3 if a polyfill for
// SessionHandlerInterface (see http://www.php.net/class.sessionhandlerinterface.php)
// is provided either by you or an external package like `symfony/http-foundation`.
if (!interface_exists('SessionHandlerInterface')) {
die("ATTENTION: the session handler implemented by Predis needs PHP >= 5.4.0 or a polyfill ".
"for \SessionHandlerInterface either provided by you or an external package.\n");
}
// Instantiate a new client just like you would normally do. We'll prefix our session keys here.
$client = new Predis\Client($single_server, array('prefix' => 'sessions:'));
// Set `gc_maxlifetime` so that a session will be expired after 5 seconds since last access.
$handler = new Predis\Session\SessionHandler($client, array('gc_maxlifetime' => 5));
// Register our session handler (it uses `session_set_save_handler()` internally).
$handler->register();
// Set a fixed session ID just for the sake of our example.
session_id('example_session_id');
session_start();
if (isset($_SESSION['foo'])) {
echo "Session has `foo` set to {$_SESSION['foo']}\n";
} else {
$_SESSION['foo'] = $value = mt_rand();
echo "Empty session, `foo` has been set with $value\n";
}
+9 -3
View File
@@ -33,7 +33,7 @@ use Predis\Transaction\MultiExecContext;
*/
class Client implements ClientInterface
{
const VERSION = '0.8.0';
const VERSION = '0.8.2';
private $options;
private $profile;
@@ -142,7 +142,7 @@ class Client implements ClientInterface
throw new \InvalidArgumentException("Invalid connection ID: '$connectionID'");
}
return new Client($connection, $this->options);
return new static($connection, $this->options);
}
/**
@@ -267,7 +267,13 @@ class Client implements ClientInterface
$eval = $this->createCommand('eval');
$eval->setRawArguments($command->getEvalArguments());
return $this->executeCommand($eval);
$response = $this->executeCommand($eval);
if (false === $response instanceof ResponseObjectInterface) {
$response = $command->parseResponse($response);
}
return $response;
}
if ($this->options->exceptions === true) {
+10 -4
View File
@@ -26,19 +26,21 @@ class HashRing implements DistributionStrategyInterface, HashGeneratorInterface
const DEFAULT_REPLICAS = 128;
const DEFAULT_WEIGHT = 100;
private $nodes;
private $ring;
private $ringKeys;
private $ringKeysCount;
private $replicas;
private $nodeHashCallback;
private $nodes = array();
/**
* @param int $replicas Number of replicas in the ring.
* @param mixed $nodeHashCallback Callback returning the string used to calculate the hash of a node.
*/
public function __construct($replicas = self::DEFAULT_REPLICAS)
public function __construct($replicas = self::DEFAULT_REPLICAS, $nodeHashCallback = null)
{
$this->replicas = $replicas;
$this->nodes = array();
$this->nodeHashCallback = $nodeHashCallback;
}
/**
@@ -164,7 +166,11 @@ class HashRing implements DistributionStrategyInterface, HashGeneratorInterface
*/
protected function getNodeHash($nodeObject)
{
return (string) $nodeObject;
if ($this->nodeHashCallback === null) {
return (string) $nodeObject;
}
return call_user_func($this->nodeHashCallback, $nodeObject);
}
/**
@@ -24,11 +24,11 @@ class KetamaPureRing extends HashRing
const DEFAULT_REPLICAS = 160;
/**
*
* @param mixed $nodeHashCallback Callback returning the string used to calculate the hash of a node.
*/
public function __construct()
public function __construct($nodeHashCallback = null)
{
parent::__construct($this::DEFAULT_REPLICAS);
parent::__construct($this::DEFAULT_REPLICAS, $nodeHashCallback);
}
/**
@@ -61,4 +61,12 @@ class KeyPrefixProcessor implements CommandProcessorInterface
$command->prefixKeys($this->prefix);
}
}
/**
* {@inheritdoc}
*/
public function __toString()
{
return $this->getPrefix();
}
}
@@ -328,7 +328,7 @@ class PhpiredisConnection extends AbstractConnection
/**
* {@inheritdoc}
*/
private function write($buffer)
protected function write($buffer)
{
$socket = $this->getResource();
+1 -1
View File
@@ -43,7 +43,7 @@ class ClientCluster extends AbstractOption
public function filter(ClientOptionsInterface $options, $value)
{
if (is_callable($value)) {
return $this->checkInstance(call_user_func($value, $options));
return $this->checkInstance(call_user_func($value, $options, $this));
}
$initializer = $this->getInitializer($options, $value);
+14 -2
View File
@@ -40,8 +40,20 @@ class ClientConnectionFactory extends AbstractOption
return $factory;
}
if (is_string($value) && class_exists($value)) {
if (!($factory = new $value()) && !$factory instanceof ConnectionFactoryInterface) {
if (is_callable($value)) {
$factory = call_user_func($value, $options, $this);
if (!$factory instanceof ConnectionFactoryInterface) {
throw new \InvalidArgumentException('Instance of Predis\Connection\ConnectionFactoryInterface expected');
}
return $factory;
}
if (@class_exists($value)) {
$factory = new $value();
if (!$factory instanceof ConnectionFactoryInterface) {
throw new \InvalidArgumentException("Class $value must be an instance of Predis\Connection\ConnectionFactoryInterface");
}
+19
View File
@@ -103,4 +103,23 @@ class ClientOptions implements ClientOptionsInterface
return $value;
}
}
/**
* Returns the default value for the specified option.
*
* @param string|OptionInterface $option Name or instance of the option.
* @return mixed
*/
public function getDefault($option)
{
if ($option instanceof OptionInterface) {
return $option->getDefault($this);
}
$options = $this->getDefaultOptions();
if (isset($options[$option])) {
return $options[$option]->getDefault($this);
}
}
}
+1 -1
View File
@@ -35,7 +35,7 @@ class ClientProfile extends AbstractOption
}
if (is_callable($value)) {
$value = call_user_func($value, $options);
$value = call_user_func($value, $options, $this);
}
if (!$value instanceof ServerProfileInterface) {
+1 -1
View File
@@ -42,7 +42,7 @@ class ClientReplication extends AbstractOption
public function filter(ClientOptionsInterface $options, $value)
{
if (is_callable($value)) {
$connection = call_user_func($value, $options);
$connection = call_user_func($value, $options, $this);
if (!$connection instanceof ReplicationConnectionInterface) {
throw new \InvalidArgumentException('Instance of Predis\Connection\ReplicationConnectionInterface expected');
+37 -10
View File
@@ -11,9 +11,12 @@
namespace Predis\Pipeline;
use Iterator;
use SplQueue;
use Predis\ResponseErrorInterface;
use Predis\ResponseObjectInterface;
use Predis\ServerException;
use Predis\Command\CommandInterface;
use Predis\Connection\ConnectionInterface;
use Predis\Connection\ReplicationConnectionInterface;
@@ -50,6 +53,27 @@ class StandardExecutor implements PipelineExecutorInterface
}
}
/**
* Handles a response object.
*
* @param ConnectionInterface $connection
* @param CommandInterface $command
* @param ResponseObjectInterface $response
* @return mixed
*/
protected function onResponseObject(ConnectionInterface $connection, CommandInterface $command, ResponseObjectInterface $response)
{
if ($response instanceof ResponseErrorInterface) {
return $this->onResponseError($connection, $response);
}
if ($response instanceof Iterator) {
return $command->parseResponse(iterator_to_array($response));
}
return $response;
}
/**
* Handles -ERR responses returned by Redis.
*
@@ -58,6 +82,10 @@ class StandardExecutor implements PipelineExecutorInterface
*/
protected function onResponseError(ConnectionInterface $connection, ResponseErrorInterface $response)
{
if (!$this->exceptions) {
return $response;
}
// Force disconnection to prevent protocol desynchronization.
$connection->disconnect();
$message = $response->getMessage();
@@ -70,24 +98,23 @@ class StandardExecutor implements PipelineExecutorInterface
*/
public function execute(ConnectionInterface $connection, SplQueue $commands)
{
$size = count($commands);
$values = array();
$exceptions = $this->exceptions;
$this->checkConnection($connection);
foreach ($commands as $command) {
$connection->writeCommand($command);
}
for ($i = 0; $i < $size; $i++) {
$response = $connection->readResponse($commands->dequeue());
$values = array();
if ($response instanceof ResponseErrorInterface && $exceptions === true) {
$this->onResponseError($connection, $response);
while (!$commands->isEmpty()) {
$command = $commands->dequeue();
$response = $connection->readResponse($command);
if ($response instanceof ResponseObjectInterface) {
$values[] = $this->onResponseObject($connection, $command, $response);
} else {
$values[] = $command->parseResponse($response);
}
$values[$i] = $response instanceof \Iterator ? iterator_to_array($response) : $response;
}
return $values;
+141
View File
@@ -0,0 +1,141 @@
<?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\Session;
use SessionHandlerInterface;
use Predis\ClientInterface;
/**
* Session handler class that relies on Predis\Client to store PHP's sessions
* data into one or multiple Redis servers.
*
* This class is mostly intended for PHP 5.4 but it can be used under PHP 5.3 provided
* that a polyfill for `SessionHandlerInterface` is defined by either you or an external
* package such as `symfony/http-foundation`.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class SessionHandler implements SessionHandlerInterface
{
protected $client;
protected $ttl;
/**
* @param ClientInterface $client Fully initialized client instance.
* @param array $options Session handler options.
*/
public function __construct(ClientInterface $client, Array $options = array())
{
$this->client = $client;
$this->ttl = (int) (isset($options['gc_maxlifetime']) ? $options['gc_maxlifetime'] : ini_get('session.gc_maxlifetime'));
}
/**
* Registers the handler instance as the current session handler.
*/
public function register()
{
if (version_compare(PHP_VERSION, '5.4.0') >= 0) {
session_set_save_handler($this, true);
} else {
session_set_save_handler(
array($this, 'open'),
array($this, 'close'),
array($this, 'read'),
array($this, 'write'),
array($this, 'destroy'),
array($this, 'gc')
);
}
}
/**
* {@inheritdoc}
*/
public function open($save_path, $session_id)
{
// NOOP
return true;
}
/**
* {@inheritdoc}
*/
public function close()
{
// NOOP
return true;
}
/**
* {@inheritdoc}
*/
public function gc($maxlifetime)
{
// NOOP
return true;
}
/**
* {@inheritdoc}
*/
public function read($session_id)
{
if ($data = $this->client->get($session_id)) {
return $data;
}
return '';
}
/**
* {@inheritdoc}
*/
public function write($session_id, $session_data)
{
$this->client->setex($session_id, $this->ttl, $session_data);
return true;
}
/**
* {@inheritdoc}
*/
public function destroy($session_id)
{
$this->client->del($session_id);
return true;
}
/**
* Returns the underlying client instance.
*
* @return ClientInterface
*/
public function getClient()
{
return $this->client;
}
/**
* Returns the session max lifetime value.
*
* @return int
*/
public function getMaxLifeTime()
{
return $this->ttl;
}
}
@@ -17,6 +17,7 @@ use Predis\ClientException;
use Predis\ClientInterface;
use Predis\CommunicationException;
use Predis\ExecutableContextInterface;
use Predis\Helpers;
use Predis\NotSupportedException;
use Predis\ResponseErrorInterface;
use Predis\ResponseQueued;
+1 -1
View File
@@ -10,7 +10,7 @@ name = "Predis"
desc = "Flexible and feature-complete PHP client library for Redis"
homepage = "http://github.com/nrk/predis"
license = "MIT"
version = "0.8.0"
version = "0.8.2"
stability = "stable"
channel = "pear.nrk.io"
+1 -1
View File
@@ -31,7 +31,7 @@
<php>
<!-- Redis -->
<const name="REDIS_SERVER_VERSION" value="2.4" />
<const name="REDIS_SERVER_VERSION" value="2.6" />
<const name="REDIS_SERVER_HOST" value="127.0.0.1" />
<const name="REDIS_SERVER_PORT" value="6379" />
<const name="REDIS_SERVER_DBNUM" value="15" />
+1 -1
View File
@@ -262,7 +262,7 @@ abstract class ConnectionTestCase extends StandardTestCase
$connection->writeCommand($profile->createCommand('rpush', array('foo', 'baz')));
$this->assertInstanceOf('Predis\ResponseError', $error = $connection->read());
$this->assertSame('ERR Operation against a key holding the wrong kind of value', $error->getMessage());
$this->assertRegExp('/[ERR|WRONGTYPE] Operation against a key holding the wrong kind of value/', $error->getMessage());
}
/**
+20 -4
View File
@@ -313,7 +313,7 @@ class ClientTest extends StandardTestCase
/**
* @group disconnected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testExecuteCommandThrowsExceptionOnRedisError()
{
@@ -376,7 +376,7 @@ class ClientTest extends StandardTestCase
/**
* @group disconnected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testCallingRedisCommandThrowsExceptionOnServerError()
{
@@ -462,10 +462,22 @@ class ClientTest extends StandardTestCase
$clientNode02 = $client->getClientFor('node02');
$this->assertInstanceOf('Predis\Client', $clientNode02);
$this->assertSame($node02, $clientNode02->getConnection());
$this->assertSame($client->getOptions(), $clientNode02->getOptions());
}
/**
* @group disconnected
*/
public function testGetClientForReturnsInstanceOfSubclass()
{
$nodes = array('tcp://host1?alias=node01', 'tcp://host2?alias=node02');
$client = $this->getMock('Predis\Client', array('dummy'), array($nodes), 'SubclassedClient');
$this->assertInstanceOf('SubclassedClient', $client->getClientFor('node02'));
}
/**
* @group disconnected
*/
@@ -656,10 +668,14 @@ class ClientTest extends StandardTestCase
*/
public function testClientResendScriptedCommandUsingEvalOnNoScriptErrors()
{
$command = $this->getMockForAbstractClass('Predis\Command\ScriptedCommand');
$command = $this->getMockForAbstractClass('Predis\Command\ScriptedCommand', array(), '', true, true, true, array('parseResponse'));
$command->expects($this->once())
->method('getScript')
->will($this->returnValue('return redis.call(\'exists\', KEYS[1])'));
$command->expects($this->once())
->method('parseResponse')
->with('OK')
->will($this->returnValue(true));
$connection = $this->getMock('Predis\Connection\SingleConnectionInterface');
$connection->expects($this->at(0))
@@ -669,7 +685,7 @@ class ClientTest extends StandardTestCase
$connection->expects($this->at(1))
->method('executeCommand')
->with($this->isInstanceOf('Predis\Command\ServerEval'))
->will($this->returnValue(true));
->will($this->returnValue('OK'));
$client = new Client($connection);
@@ -129,4 +129,25 @@ class HashRingTest extends DistributionStrategyTestCase
$this->assertSame($expected2, $actual2);
$this->assertSame($expected3, $actual3);
}
/**
* @todo This tests should be moved in Predis\Cluster\Distribution\DistributionStrategyTestCase
* @group disconnected
*/
public function testCallbackToGetNodeHash()
{
$node = '127.0.0.1:7000';
$replicas = HashRing::DEFAULT_REPLICAS;
$callable = $this->getMock('stdClass', array('__invoke'));
$callable->expects($this->once())
->method('__invoke')
->with($node)
->will($this->returnValue($node));
$ring = new HashRing($replicas, $callable);
$ring->add($node);
$this->getNodes($ring);
}
}
@@ -130,4 +130,24 @@ class KetamaPureRingTest extends DistributionStrategyTestCase
$this->assertSame($expected2, $actual2);
$this->assertSame($expected3, $actual3);
}
/**
* @todo This tests should be moved in Predis\Cluster\Distribution\DistributionStrategyTestCase
* @group disconnected
*/
public function testCallbackToGetNodeHash()
{
$node = '127.0.0.1:7000';
$callable = $this->getMock('stdClass', array('__invoke'));
$callable->expects($this->once())
->method('__invoke')
->with($node)
->will($this->returnValue($node));
$ring = new KetamaPureRing($callable);
$ring->add($node);
$this->getNodes($ring);
}
}
+1 -1
View File
@@ -102,7 +102,7 @@ class HashDeleteTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -91,7 +91,7 @@ class HashExistsTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -92,7 +92,7 @@ class HashGetAllTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -108,7 +108,7 @@ class HashGetMultipleTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -88,7 +88,7 @@ class HashGetTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
@@ -113,7 +113,7 @@ class HashIncrementByFloatTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -113,7 +113,7 @@ class HashIncrementByTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -92,7 +92,7 @@ class HashKeysTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -87,7 +87,7 @@ class HashLengthTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -114,7 +114,7 @@ class HashSetMultipleTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -91,7 +91,7 @@ class HashSetPreserveTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -90,7 +90,7 @@ class HashSetTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -92,7 +92,7 @@ class HashValuesTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
@@ -86,16 +86,6 @@ class KeyPreciseTimeToLiveTest extends CommandTestCase
$this->assertLessThanOrEqual(10000, $redis->pttl('foo'));
}
/**
* @group connected
*/
public function testReturnsLessThanZeroOnNonExistingKeys()
{
$redis = $this->getClient();
$this->assertSame(-1, $redis->pttl('foo'));
}
/**
* @group connected
*/
@@ -106,4 +96,16 @@ class KeyPreciseTimeToLiveTest extends CommandTestCase
$redis->set('foo', 'bar');
$this->assertSame(-1, $redis->pttl('foo'));
}
/**
* @group connected
* @todo PTTL changed in Redis >= 2.8 to return -2 on non existing keys, we
* should handle this case with a better solution than the current one.
*/
public function testReturnsLessThanZeroOnNonExistingKeys()
{
$redis = $this->getClient();
$this->assertLessThanOrEqual(-1, $redis->pttl('foo'));
}
}
+1 -1
View File
@@ -258,7 +258,7 @@ class KeySortTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+12 -10
View File
@@ -86,16 +86,6 @@ class KeyTimeToLiveTest extends CommandTestCase
$this->assertSame(10, $redis->ttl('foo'));
}
/**
* @group connected
*/
public function testReturnsLessThanZeroOnNonExistingKeys()
{
$redis = $this->getClient();
$this->assertSame(-1, $redis->ttl('foo'));
}
/**
* @group connected
*/
@@ -106,4 +96,16 @@ class KeyTimeToLiveTest extends CommandTestCase
$redis->set('foo', 'bar');
$this->assertSame(-1, $redis->ttl('foo'));
}
/**
* @group connected
* @todo TTL changed in Redis >= 2.8 to return -2 on non existing keys, we
* should handle this case with a better solution than the current one.
*/
public function testReturnsLessThanZeroOnNonExistingKeys()
{
$redis = $this->getClient();
$this->assertLessThanOrEqual(-1, $redis->ttl('foo'));
}
}
+1 -1
View File
@@ -103,7 +103,7 @@ class ListIndexTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -111,7 +111,7 @@ class ListInsertTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -98,7 +98,7 @@ class ListLengthTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -98,7 +98,7 @@ class ListPopFirstTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
@@ -117,7 +117,7 @@ class ListPopLastPushHeadTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongTypeOfSourceKey()
{
@@ -130,7 +130,7 @@ class ListPopLastPushHeadTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongTypeOfDestinationKey()
{
+1 -1
View File
@@ -98,7 +98,7 @@ class ListPopLastTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -101,7 +101,7 @@ class ListPushHeadTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -99,7 +99,7 @@ class ListPushHeadXTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -101,7 +101,7 @@ class ListPushTailTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -99,7 +99,7 @@ class ListPushTailXTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -142,7 +142,7 @@ class ListRangeTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -126,7 +126,7 @@ class ListRemoveTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -100,7 +100,7 @@ class ListSetTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -132,7 +132,7 @@ class ListTrimTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
@@ -80,4 +80,15 @@ class KeyPrefixProcessorTest extends StandardTestCase
$processor->process($command);
}
/**
* @group disconnected
*/
public function testInstanceCanBeCastedToString()
{
$prefix = 'prefix:';
$processor = new KeyPrefixProcessor($prefix);
$this->assertEquals($prefix, (string) $processor);
}
}
@@ -132,8 +132,10 @@ class PubSubUnsubscribeTest extends CommandTestCase
$this->assertSame(array('subscribe', 'channel:foo', 1), $redis->subscribe('channel:foo'));
$this->assertSame(array('subscribe', 'channel:bar', 2), $redis->subscribe('channel:bar'));
$this->assertSame(array('unsubscribe', 'channel:foo', 1), $redis->unsubscribe());
$this->assertSame(array('unsubscribe', 'channel:bar', 0), $redis->getConnection()->read());
list($_, $unsubscribed1, $_) = $redis->unsubscribe();
list($_, $unsubscribed2, $_) = $redis->getConnection()->read();
$this->assertSameValues(array('channel:foo', 'channel:bar'), array($unsubscribed1, $unsubscribed2));
$this->assertSame('echoed', $redis->echo('echoed'));
}
}
+1 -1
View File
@@ -100,7 +100,7 @@ class SetAddTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -96,7 +96,7 @@ class SetCardinalityTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
@@ -119,7 +119,7 @@ class SetDifferenceStoreTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongTypeOfSourceKey()
{
+1 -1
View File
@@ -121,7 +121,7 @@ class SetDifferenceTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
@@ -132,7 +132,7 @@ class SetIntersectionStoreTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongTypeOfSourceKey()
{
+1 -1
View File
@@ -132,7 +132,7 @@ class SetIntersectionTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -100,7 +100,7 @@ class SetIsMemberTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -92,7 +92,7 @@ class SetMembersTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+2 -2
View File
@@ -93,7 +93,7 @@ class SetMoveTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongTypeOfSourceKey()
{
@@ -107,7 +107,7 @@ class SetMoveTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongTypeOfDestinationKey()
{
+1 -1
View File
@@ -89,7 +89,7 @@ class SetPopTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -97,7 +97,7 @@ class SetRandomMemberTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -104,7 +104,7 @@ class SetRemoveTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -119,7 +119,7 @@ class SetUnionStoreTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongTypeOfSourceKey()
{
+1 -1
View File
@@ -121,7 +121,7 @@ class SetUnionTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -99,7 +99,7 @@ class StringAppendTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -96,7 +96,7 @@ class StringBitCountTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -168,7 +168,7 @@ class StringBitOpTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnInvalidSourceKey()
{
@@ -124,7 +124,7 @@ class StringDecrementByTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -111,7 +111,7 @@ class StringDecrementTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -117,7 +117,7 @@ class StringGetBitTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -102,7 +102,7 @@ class StringGetRangeTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -88,7 +88,7 @@ class StringGetSetTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -109,7 +109,7 @@ class StringGetTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
@@ -124,7 +124,7 @@ class StringIncrementByFloatTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
@@ -124,7 +124,7 @@ class StringIncrementByTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -98,7 +98,7 @@ class StringIncrementTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -133,7 +133,7 @@ class StringSetBitTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -127,7 +127,7 @@ class StringSetRangeTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -98,7 +98,7 @@ class StringStrlenTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -113,7 +113,7 @@ class ZSetAddTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -87,7 +87,7 @@ class ZSetCardinalityTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -120,7 +120,7 @@ class ZSetCountTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -87,7 +87,7 @@ class ZSetIncrementByTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
@@ -181,7 +181,7 @@ class ZSetIntersectionStoreTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
@@ -218,7 +218,7 @@ class ZSetRangeByScoreTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -141,7 +141,7 @@ class ZSetRangeTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
+1 -1
View File
@@ -90,7 +90,7 @@ class ZSetRankTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
@@ -102,7 +102,7 @@ class ZSetRemoveRangeByRankTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
@@ -102,7 +102,7 @@ class ZSetRemoveRangeByScoreTest extends CommandTestCase
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{

Some files were not shown because too many files have changed in this diff Show More