* Added CommandResolver, moved resolve command logic there, added ClientConfiguration object
* Fixed test, added dependecies
* Added resolved command to commands array
* Used aggregation approach for modules
* Added decorator to check Redis JSON module version
* Added support for JSON.SET and JSON.GET commands
* Added separate workflow for redis-stack tests
* Changed docker imange name to correct one
* Fixed indentation
* Added test coverage for JSON.GET command
* Changed module version resolving using annotations mapping
* Re-written CommandResolver test
* Update ClientInterface.php
* Changes to CI, readme, removed unused modules from configuration
* Fixed build badge URL
* Refactored annotation check to be generic for each module
* Fixed bug with incorrect tests skip
* Added CommandResolver, moved resolve command logic there, added ClientConfiguration object
* Fixed test, added dependecies
* Added resolved command to commands array
* Used aggregation approach for modules
* Added decorator to check Redis JSON module version
* Added support for JSON.SET and JSON.GET commands
* Added separate workflow for redis-stack tests
* Changed docker imange name to correct one
* Fixed indentation
* Added test coverage for JSON.GET command
* Changed module version resolving using annotations mapping
* Re-written CommandResolver test
* Update ClientInterface.php
* Changes to CI, readme, removed unused modules from configuration
* Fixed build badge URL
* Refactored annotation check to be generic for each module
* Fixed bug with incorrect tests skip
* Fixed naming issue with nxXx argument
* Removed redundant trait
* Fixed NxXxArgument test
* add Redis stack tests
* don't run tests twice
* use
* Update stack.yml
* Rename workflows
* Added version 6.x to workflow
* Removed exception thrown to avoid version bug
* Resolve conflicts within tests.yml
* Codestyle fixes
* Removew trailing whitespaces
Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
See commit dd5d665 for the above mentioned changes.
Tests for Option\Aggregate, Option\Replication and Option\Cluster should
be refactored because code is a bit too repetitive and a bunch of tests
are shared among them (replication and cluster options extend aggregate
and share the same logic after all).
The "at" matcher will be removed in PHPUnit 10 but it is not a bad thing
after all because it was cumbersome and error-prone.
Took the opportunity to improve some tests while converting them.
- Make use of more typehints for function parameters
- Make use of typehints for function return values
- Use @var where needed to give proper hints to IDEs and avoid warnings
- Replace MockObject::setMethods() with addMethods() and onlyMethods()
- Rewording of some phpdocs
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"
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.
* 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.
We now have a base test case class for Predis (namely PredisTestCase)
grouping various commonly used utility methods shared by all of the
tests in the suite, greatly improving reusability.
This commit is a complete rewrite of the classes previously contained
in the Predis\Option namespace aimed at lowering the initialization
overhead while bringing in more consistency. The overall idea is still
the same with a mini DI container, Predis\Configuration\Options, which
carries options with values that can be initialized lazily.
The first difference with our previous implementation is that now even
user-defined options can be initialized lazily, everything needed is
an object responding to the __invoke() magic method such as a closure.
Other kind of callable arguments (strings, arrays) will be treated as
plain values. The only drawback is that we cannot pass any instance of
classes implementing __invoke() as an option value, but considered the
limited scope of our use case we can say it's more of an acceptable
compromise. Callbacks used for lazy initialization will receive two
arguments upon invokation:
- The current instance of Predis\Configuration\Option ($options)
- A string containing the name of the option ($option)
This is an example in actual code:
$options = new Predis\Configuration\Options([
'exceptions' => true,
'profile' => '2.8',
'distributor' => function () {
return new Predis\Cluster\Distribution\KetamaPureRing();
},
'cluster' => function ($options) {
$distr = $options->distributor;
$strategy = new Predis\Cluster\PredisClusterHashStrategy($distr);
$cluster = new Predis\Connection\PredisCluster();
return $cluster;
},
'connections' => function ($options, $option) {
$factory = $options->getDefault($option);
$factory->define('tcp', 'Predis\Connection\PhpiredisConnection');
return $factory;
},
]);
As you can see there's very little difference compared to before in
the actual usage as most changes are under the hood. Some options such
as "exceptions" and "replication" can now correctly parse bool values
from strings (so the string "false" is not evaluated as boolean true).
While options were initially conceived to configure the client and its
behavior, the concept has matured and it's perfectly fine to consider
the use of Predis\Configuration\Options to propagate configurations to
inner parts of the library.