* Fix almost all PHPStan level 2 problems
* Fix master loop and remove empty line
* Fix variadic functions
* Fix CS
* Disable xdebug in CI and improve a condition
* Fix CI fix
This is a complete overhaul of how aggregate connections are created and
initialized, now everything is self-contained in our usual 3 supported
client options: "aggregate", "cluster" and "replication".
The usage of callables acting as connection initializerss is now more
consistent through the various options. When the callable is invoked it
receives 3 arguments (the original set of connection parameters passed
by reference, the options container, the current option) and must return
an instance of Predis\Connection\AggregateConnectionInterface otherwise
an InvalidArgumentException is thrown.
When using "cluster" and "replication" the returned aggregate connection
is automatically populated by adding the list of nodes in $parameters,
on the other hand "aggregate" skips this automatism so it is up to the
user. In any case the user-supplied callable receives $parameters as a
reference, setting $parameters to NULL inside the body of the callable
makes the client skip automatic aggregation regardless of the option in
use.
In addition to this the actual procedure of adding nodes to an aggregate
connection has been moved directly into the respective options instead
of being spread between the client (which instead should just pass a set
of parameters and get back a fully-configured aggregate connection) and
the connection factory (and the scope of a connection factory is only to
create new connetion instances to single Redis servers).
The option handler has been extended to accept descriptive string values
in order to create and configure an appropriate command factory.
Accepted string values are:
- "predis" creates the usual command factory
- "raw" creates a raw command factory
- "default" is simply an alias of "predis"
We have renamed most methods to drop the "command" suffix as it is quite
redundant. Due to this change and thanks to variadic methods introduced
with PHP 5.6 we took the opportunity to replace both "supportsCommand()"
and "supportsCommands()" with a single new method "supports()".
Added more stringent typehints for method arguments and typehints for
return values now that we do not need to support anything below PHP 7.2.
Also moved from using array() to [] in source code of class involved.
Using "default" returns a connection factory instance with the default
configuration. Basically it is no different than omitting "connections"
in the client options array but it can be useful when applications want
to automatically configure Predis to use phpiredis when it is loaded:
$client = new Predis\Client('tcp://127.0.0.1', [
'connections' =>
extension_loaded('phpiredis')
? 'phpiredis'
: 'default'
]);
This is in response to ISSUE #397.
The "connections" client option now accepts certain string values that
are mapped to specific and most used configurations for the connection
factory. This is used to make it easier to configure Predis to load our
phpiredis-based connection backends without having to manually pass a
map of URI schemes and fully-qualified class names.
- "phpiredis-stream" maps `tcp` and `unix` to the connection backend
based on PHP streams (Predis\Connection\PhpiredisStreamConnection).
- "phpiredis-socket" maps `tcp` and `unix` to the connection backend
based on ext-socket (Predis\Connection\PhpiredisStreamConnection).
- `phpiredis` is simply an alias of `phpiredis-stream`.
An InvalidArgumentException is thrown on unsupported string values.
The previous implementation was not good because we were exposing in the
public API an internal implementation detail of the base factory class,
furthermore it made Predis\Command\Factory::define() confusing. Having a
separate method to undefine commands in the factory is self-explanatory.
We also changed `Predis\Configuration\Option\Commands` accordingly when
a dictionary of $commandID => $classCommand is passed to the "commands"
client option and $classCommand is NULL.
A few minor changes (mostly cosmetic or documentation) were applied too.
From feedback to PR #644.
By default Predis chooses automatically which hash generator to use:
if a suitable version of ext-phpiredis is loaded (that is, a version
that implements the phpiredis_utils_crc16() function) it uses the new
Predis\Cluster\Hash\PhpiredisCRC16 generator, otherwise it falls back
to the usual pure-PHP Predis\Cluster\Hash\CRC16 generator.
All option classes have been moved in the Predis\Configuration\Option
namespace and some have been optimized to have less impact on client
initialization timings.
Furthermore the accepted values for some options have been changed,
this is the complete list of accepted values:
- _aggregate_: callable returning an aggregate connection.
- cluster: string value ("predis", "redis"), callable returning an
aggregate connection.
- replication: string value ("predis", "sentinel"), callable returning
an aggregate connection.
- commands: command factory, named array mapping command IDs to PHP
classes, callable returning a command factory or a named array.
- connections: connection factory, callable returning a connection
factory, named array mapping connection schemes to PHP classes.
- _prefix_: string value, command processor, callable.
- _exceptions_: boolean value.
Note that the cluster and replication options now return a closure
acting as initializer instead of an aggregate connection.
This change reduces some unnecessary complexity in the library, Redis
commands do not change much after all. Developers can still implement
their own commands factory, inject new commands or override existing
ones. The "profile" client options has been renamed to "commands" and
it accepts instances of Predis\Command\FactoryInterface.
The test suite checks at runtime the version of the running instance
of Redis for integration tests to adapt itself automatically.
Now the client can discover the whole replication configuration by
asking to one of the servers (master has the precedence) using the
INFO REPLICATION command. This is obviously a best-effort fallback
and there is no strong guarantee about reliability and efficiency.
By enabling auto-discovery, the client automates this process when
the execution of a command fails because one of the target servers
is unreachable. The replication connection requires an instance of
connection factory associated to it in order to be able to create
new connections on the fly.
It is possible to enable the auto-discovery procedure easily via
client options:
$client = new Predis\Client($servers, [
'replication' => true,
'autodiscovery' => true,
]);
This is mostly useful when configuring the client to use redis-cluster
or redis-sentinel in order to set a common password for authentication
or database. In these kind of configurations it is impossible to pass
them via connection parameters as connections are created dinamically
by the client depending on the server response.
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.