Dramatically improve aggregate connections initialization.

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).
This commit is contained in:
Daniele Alessandri
2020-09-02 13:57:26 +02:00
parent efbe80222e
commit dd5d665156
6 changed files with 214 additions and 133 deletions
+6 -32
View File
@@ -18,7 +18,6 @@ use Predis\Configuration\Options;
use Predis\Configuration\OptionsInterface;
use Predis\Connection\ConnectionInterface;
use Predis\Connection\ParametersInterface;
use Predis\Connection\Replication\SentinelReplication;
use Predis\Monitor\Consumer as MonitorConsumer;
use Predis\Pipeline\Pipeline;
use Predis\PubSub\Consumer as PubSubConsumer;
@@ -126,14 +125,12 @@ class Client implements ClientInterface, \IteratorAggregate
if (is_array($parameters)) {
if (!isset($parameters[0])) {
return $options->connections->create($parameters);
}
if ($options->defined('cluster')) {
return $this->createAggregateConnection($parameters, 'cluster');
} elseif ($options->defined('replication')) {
return $this->createAggregateConnection($parameters, 'replication');
} elseif ($options->defined('aggregate')) {
return $this->createAggregateConnection($parameters, 'aggregate');
} elseif ($options->defined('cluster') && $initializer = $options->cluster) {
return $initializer($parameters, true);
} elseif ($options->defined('replication') && $initializer = $options->replication) {
return $initializer($parameters, true);
} elseif ($options->defined('aggregate') && $initializer = $options->aggregate) {
return $initializer($parameters, false);
} else {
throw new \InvalidArgumentException(
'Array of connection parameters requires `cluster`, `replication` or `aggregate` client option'
@@ -154,29 +151,6 @@ class Client implements ClientInterface, \IteratorAggregate
throw new \InvalidArgumentException('Invalid type for connection parameters');
}
/**
* Creates an aggregate connection.
*
* @param mixed $parameters Connection parameters.
* @param string $option Option for aggregate connections (`aggregate`, `cluster`, `replication`).
*
* @return \Closure
*/
protected function createAggregateConnection($parameters, $option)
{
$options = $this->getOptions();
$initializer = $options->$option;
$connection = $initializer($parameters);
// TODO: this is dirty but we must skip the redis-sentinel backend for now.
if ($option !== 'aggregate' && !$connection instanceof SentinelReplication) {
$options->connections->aggregate($connection, $parameters);
}
return $connection;
}
/**
* {@inheritdoc}
*/