This is meant as a basic layer of protection for those cases where the whole
Predis repository is cloned into a path which is publicly exposed by the web
server.
Closes#408
Predis\Client now requires a list of connection parameters pointing to
sentinel instances and mandatory options "replication" and "service" set
respectively to "sentinel" and the chosen name for the master instance.
$sentinels = ['tcp://127.0.0.1:5381', 'tcp://127.0.0.1:5382'];
$options = ['replication' => 'sentinel', 'service' => 'mymaster'];
$client = new Predis\Client($sentinels, $options);
Despite being nice and clean on the outside I am not really fond of the
code being used internally to make this kind of configuration possible.
Improvements in this respect would require a few breaking changes (not
even an option for a minor release) so things will change for the good
with Predis 2.0.
This change actually had a positive impact on the design of the whole
internals for clustering which is now cleaner and easier to maintain.
It is still far from perfect, but we also have to keep performances in
consideration so we can say that we ended up with a good compromise.
Previously Predis assigned an hash to each command instance which was
computed from its key, now we changed approach and the library caches
the slot assigned to each command. This works for both our client-side
sharding cluster and the upcoming redis-cluster, but the former is the
one that needed most changes.
The PredisCluster aggregate connection now only takes an instance of
StrategyInterface, which in turn wraps the chosen distributor. After
all, in order to be able to calculate the assigned slot for a command
or key, the cluster strategy must have access to the distributor that
manages the distribution of the whole keyspace. Nothing really changes
in terms of configurability as it is still possible to decide which
distributor to use for client-side sharding, it is simply different:
$distributor = new Predis\Cluster\Distribution\KetamaRing();
$strategy = new Predis\Cluster\PredisStrategy($distributor);
$cluster = new Predis\Connection\Aggregate\PredisCluster($strategy);
As for the RedisCluster aggregate connection, the only change is that
the mathematical operation of calculating the assigned slot from a key
has been completely moved inside the cluster strategy instance.
The strategy for redis-cluster does not use external distributors so
trying to StrategyInterface::getDistributor() will throw an exception.
This may change in future releases, but this is not a priority since
redis-cluster relies on a fixed, well-defined distribution mechanism.
* Renamed SingleConnectionInterface to NodeConnectionInterface since
this name is better and makes even more sense in the context of
cluster and replication scenarios.
* Moved specialized aggregate connections (the ones implementing both
predis and redis cluster and master/slave replication) in a newly
created Predis\Connection\Aggregate sub-namespace.
* Removed the "Connection" part from names of aggregate connection
interfaces in the Predis\Connection\Aggregate sub-namespace.
* Changed "Composable" to "Composite" in the name of interfaces and
classes that can use pluggable protocol processors.
This is more consistent with Predis\Client::executeRaw() and its more
explicit since simply "raw" as a method name was a bit too vague even
despite being nicely short.
Status response objects are needed mostly to make it possible from the
client perspective to differentiate a status response with the payload
"OK" from a normale bulk reply containing "OK".
The biggest change is for commands returning +OK responses: these were
previously translated to TRUE (bool value), but they are now returned
as instances of Predis\Response\Status. Just to illustrate an example
of the possibilities with this change we will use SET since it is the
most widely used command returning +OK:
$response = $client->set('foo', 'bar');
echo $response; // 'OK'
$response == 'OK'; // TRUE
isset($response->ok); // TRUE
$response == true; // TRUE
$response === true; // FALSE
$response instanceof Predis\Response\ObjectInterface; // TRUE
$response instanceof Predis\Response\Status; // TRUE
For those checking responses returned by commands such as SET or PONG,
the breaking change basically lies in the usage of strict comparison:
doing $response === true will now evaluate to FALSE instead of TRUE.
By default Predis caches common status responses such as OK or QUEUED
to lower the memory usage when using pipelines or transactions.
We also changed our wording to indentify this kind of abstraction so
instead of using "scripted commands" (kind of broken English) we now
use "scriptable commands".
First of all we completely removed the concept of pipeline executors.
Now pipelines can be easily customized by extending our default class
Predis\Pipeline\Pipeline.
Tests coverage for the Predis\Pipeline namespace is decent but can be
definitely improved while test cases can be beautified.
Supporting this feature has been problematic and leaded to some ugly
code to make abstractions such as pipelines and transactions aware of
these kind of response objects. Furthermore, it was not possible to
add them to all the connection classes due to implementation limits.
For such reasons Predis do not support them globally anymore, but the
actual classes are still shipped within the library so that they can
be used to build custom stuff at a level lower than client (that is,
unless we decide to remove them for good before going stable).
We are experimenting with a new approach at naming classes using less
redundant names by leveraging the containing namespace. The PHP "use"
directive is not limited to class names but can be used to import the
whole namespace, which means you can do something like this:
use Predis\Collection\Iterator;
// ...
foreach (new Iterator\Keyspace($client) as $key) {
// ...
}
Alternatively you can always rely on "use ... as ..." to import one of
the classes by giving it a more meaningful name in the context of the
root namespace:
use Predis\Collection\Iterator\Keyspace as KeyspaceIterator;
// ...
foreach (new KeyspaceIterator($client) as $key) {
// ...
}
In this specific case we chose to apply the -Key postfix to classes
iterating Redis keys to be more explicit about the fact that those
iterators does not work on local in-memory collections, but fetch
items from a key stored on a remote Redis server.
Client::pubSub() still works like usual by returning a new pub/sub
context, but it is now considered an alias of Client::pubSubLoop().
This change is necessary in preparation for the next major version
of Predis where Client::pubSub() will be used for the new PUBSUB
command introduced in Redis 2.8.
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.
This should make things a tiny bit faster (we are speaking about micro
optimizations anyway) but more importantly it results in a better
encapsulation.
With a negative number Predis will count from the end of the arguments list
to calculate the actual number of keys that will be interpreted as elements
for `KEYS` by the underlying `EVAL` command.