Browse Source

Add support for default connection parameters in Connection\Factory.

These parameters augment the set of user-supplied parameters when creating a new
connection, but they do not override specific parameters when already defined.

An example of self-contained configuration using client options:

  $client = new Predis\Client('tcp://127.0.0.1', [
    'parameters' => [
      'timeout' => 10,
    ],
    'connections' => function ($options) {
      $factory = $options->getDefault('connections');
      $factory->setDefaultParameters($options->parameters);

      return $factory;
    },
  ]);

This change will be useful for both redis-cluster and redis-sentinel as it makes
it easy to apply shared parameters such as a common password for authentication
when the server returns one ore more new nodes from response (think of -MOVED).
Daniele Alessandri 9 years ago
parent
commit
55aab86800
3 changed files with 174 additions and 2 deletions
  1. 4 0
      CHANGELOG.md
  2. 37 2
      src/Connection/Factory.php
  3. 133 0
      tests/Predis/Connection/FactoryTest.php

+ 4 - 0
CHANGELOG.md

@@ -13,6 +13,10 @@ v1.1.0 (2015-xx-xx)
   is needed to prevent confusion with how `path` is used to select a database
   with the `redis` scheme.
 
+- Add support for default connection parameters in Predis\Connection\Factory.
+  These parameters augment the user-supplied parameters when creating a new
+  connection but they do not override specific parameters when already defined.
+
 
 v1.0.1 (2015-01-02)
 ================================================================================

+ 37 - 2
src/Connection/Factory.php

@@ -20,6 +20,8 @@ use Predis\Command\RawCommand;
  */
 class Factory implements FactoryInterface
 {
+    private $defaults = array();
+
     protected $schemes = array(
         'tcp' => 'Predis\Connection\StreamConnection',
         'unix' => 'Predis\Connection\StreamConnection',
@@ -35,8 +37,8 @@ class Factory implements FactoryInterface
      * @param mixed $initializer FQN of a connection class or a callable for lazy initialization.
      *
      * @throws \InvalidArgumentException
-     * @return mixed
      *
+     * @return mixed
      */
     protected function checkInitializer($initializer)
     {
@@ -115,6 +117,29 @@ class Factory implements FactoryInterface
         }
     }
 
+    /**
+     * Assigns a default set of parameters applied to new connections.
+     *
+     * The set of parameters passed to create a new connection have precedence
+     * over the default values set for the connection factory.
+     *
+     * @param array $parameters Set of connection parameters.
+     */
+    public function setDefaultParameters(array $parameters)
+    {
+        $this->defaults = $parameters;
+    }
+
+    /**
+     * Returns the default set of parameters applied to new connections.
+     *
+     * @return array
+     */
+    public function getDefaultParameters()
+    {
+        return $this->defaults;
+    }
+
     /**
      * Creates a connection parameters instance from the supplied argument.
      *
@@ -124,7 +149,17 @@ class Factory implements FactoryInterface
      */
     protected function createParameters($parameters)
     {
-        return Parameters::create($parameters);
+        if (is_string($parameters)) {
+            $parameters = Parameters::parse($parameters);
+        } else {
+            $parameters = $parameters ?: array();
+        }
+
+        if ($this->defaults) {
+            $parameters += $this->defaults;
+        }
+
+        return new Parameters($parameters);
     }
 
     /**

+ 133 - 0
tests/Predis/Connection/FactoryTest.php

@@ -28,6 +28,24 @@ class FactoryTest extends PredisTestCase
         $this->assertInstanceOf('Predis\Connection\FactoryInterface', $factory);
     }
 
+    /**
+     * @group disconnected
+     */
+    public function testSettingDefaultParameters()
+    {
+        $factory = new Factory();
+
+        $factory->setDefaultParameters($defaults = array(
+            'password' => 'secret',
+            'database' => 10,
+            'custom' => 'foobar',
+        ));
+
+        $this->assertSame($defaults, $factory->getDefaultParameters());
+
+        $parameters = array('database' => 10, 'persistent' => true);
+    }
+
     /**
      * @group disconnected
      */
@@ -72,6 +90,39 @@ class FactoryTest extends PredisTestCase
         $this->assertEquals($unix->database, $parameters->database);
     }
 
+    /**
+     * @group disconnected
+     */
+    public function testCreateConnectionWithParametersInstanceAndDefaultsDoesNotAlterOriginalParameters()
+    {
+        $factory = new Factory();
+
+        $factory->setDefaultParameters($defaultParams = array(
+            'port' => 7000,
+            'password' => 'secret',
+            'database' => 10,
+            'custom' => 'foobar',
+        ));
+
+        $inputParams = new Parameters(array(
+            'host' => 'localhost',
+            'database' => 5,
+        ));
+
+        $connection = $factory->create($inputParams);
+        $parameters = $connection->getParameters();
+
+        $this->assertEquals('localhost', $parameters->host);
+        $this->assertEquals(6379, $parameters->port);
+        $this->assertEquals(5, $parameters->database);
+
+        $this->assertFalse(isset($parameters->password));
+        $this->assertNull($parameters->password);
+
+        $this->assertFalse(isset($parameters->custom));
+        $this->assertNull($parameters->custom);
+    }
+
     /**
      * @group disconnected
      */
@@ -88,6 +139,31 @@ class FactoryTest extends PredisTestCase
         $this->assertNull($parameters->custom);
     }
 
+    /**
+     * @group disconnected
+     */
+    public function testCreateConnectionWithNullParametersAndDefaults()
+    {
+        $factory = new Factory();
+
+        $factory->setDefaultParameters($defaultParams = array(
+            'port' => 7000,
+            'password' => 'secret',
+            'custom' => 'foobar',
+        ));
+
+        $connection = $factory->create(null);
+        $parameters = $connection->getParameters();
+
+        $this->assertInstanceOf('Predis\Connection\NodeConnectionInterface', $connection);
+
+        $this->assertEquals('127.0.0.1', $parameters->host);
+        $this->assertEquals($defaultParams['port'], $parameters->port);
+        $this->assertEquals($defaultParams['password'], $parameters->password);
+        $this->assertEquals($defaultParams['custom'], $parameters->custom);
+        $this->assertNull($parameters->path);
+    }
+
     /**
      * @group disconnected
      */
@@ -104,6 +180,37 @@ class FactoryTest extends PredisTestCase
         $this->assertSame('foobar', $parameters->custom);
     }
 
+    /**
+     * @group disconnected
+     */
+    public function testCreateConnectionWithArrayParametersAndDefaults()
+    {
+        $factory = new Factory();
+
+        $factory->setDefaultParameters($defaultParams = array(
+            'port' => 7000,
+            'password' => 'secret',
+            'custom' => 'foobar',
+        ));
+
+        $connection = $factory->create($inputParams = array(
+            'host' => 'localhost',
+            'port' => 8000,
+            'persistent' => true,
+        ));
+
+        $parameters = $connection->getParameters();
+
+        $this->assertInstanceOf('Predis\Connection\NodeConnectionInterface', $connection);
+
+        $this->assertEquals($inputParams['host'], $parameters->host);
+        $this->assertEquals($inputParams['port'], $parameters->port);
+        $this->assertEquals($defaultParams['password'], $parameters->password);
+        $this->assertEquals($defaultParams['custom'], $parameters->custom);
+        $this->assertEquals($inputParams['persistent'], $parameters->persistent);
+        $this->assertNull($parameters->path);
+    }
+
     /**
      * @group disconnected
      */
@@ -120,6 +227,32 @@ class FactoryTest extends PredisTestCase
         $this->assertSame('foobar', $parameters->custom);
     }
 
+    /**
+     * @group disconnected
+     */
+    public function testCreateConnectionWithStrinURIAndDefaults()
+    {
+        $factory = new Factory();
+
+        $factory->setDefaultParameters($defaultParams = array(
+            'port' => 7000,
+            'password' => 'secret',
+            'custom' => 'foobar',
+        ));
+
+        $connection = $factory->create('tcp://localhost:8000?persistent=1');
+        $parameters = $connection->getParameters();
+
+        $this->assertInstanceOf('Predis\Connection\NodeConnectionInterface', $connection);
+
+        $this->assertEquals('localhost', $parameters->host);
+        $this->assertEquals('8000', $parameters->port);
+        $this->assertEquals($defaultParams['password'], $parameters->password);
+        $this->assertEquals($defaultParams['custom'], $parameters->custom);
+        $this->assertEquals(true, $parameters->persistent);
+        $this->assertNull($parameters->path);
+    }
+
     /**
      * @group disconnected
      */