Skip to content

Commit

Permalink
Add replication option
Browse files Browse the repository at this point in the history
  • Loading branch information
acasademont committed Aug 8, 2013
1 parent 1f99523 commit 67646cf
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 15 deletions.
1 change: 1 addition & 0 deletions DependencyInjection/Configuration/Configuration.php
Expand Up @@ -125,6 +125,7 @@ private function addClientsSection(ArrayNodeDefinition $rootNode)
->end()
->scalarNode('cluster')->defaultNull()->end()
->scalarNode('prefix')->defaultNull()->end()
->booleanNode('replication')->defaultFalse()->end()
->end()
->end()
->end()
Expand Down
20 changes: 19 additions & 1 deletion DependencyInjection/Configuration/RedisDsn.php
Expand Up @@ -51,6 +51,11 @@ class RedisDsn
*/
protected $weight;

/**
* @var string
*/
protected $alias;

/**
* Constructor
*
Expand Down Expand Up @@ -114,6 +119,14 @@ public function getSocket()
return $this->socket;
}

/**
* @return string
*/
public function getAlias()
{
return $this->alias;
}

/**
* @return bool
*/
Expand Down Expand Up @@ -145,7 +158,7 @@ protected function parseDsn($dsn)
$this->password = str_replace('\@', '@', substr($dsn, 0, $pos));
$dsn = substr($dsn, $pos + 1);
}
$dsn = preg_replace_callback('/\?(weight)=[^&]+.*$/', array($this, 'parseParameters'), $dsn); // parse parameters
$dsn = preg_replace_callback('/\?(weight|alias)=[^&]+.*$/', array($this, 'parseParameters'), $dsn); // parse parameters
if (preg_match('#^(.*)/(\d+)$#', $dsn, $matches)) {
// parse database
$this->database = (int) $matches[2];
Expand Down Expand Up @@ -184,6 +197,11 @@ protected function parseParameters($matches)
$this->weight = (int) $kv[1];
}
break;
case 'alias':
if ($kv[1]) {
$this->alias = $kv[1];
}
break;
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion DependencyInjection/SncRedisExtension.php
Expand Up @@ -130,7 +130,9 @@ protected function loadPredisClient(array $client, ContainerBuilder $container)
$connectionCount = count($client['dsns']);
foreach ($client['dsns'] as $i => $dsn) {
/** @var \Snc\RedisBundle\DependencyInjection\Configuration\RedisDsn $dsn */
$connectionAlias = 1 === $connectionCount ? $client['alias'] : $client['alias'] . ($i + 1);
if (!$connectionAlias = $dsn->getAlias()) {
$connectionAlias = 1 === $connectionCount ? $client['alias'] : $client['alias'] . ($i + 1);
}
$connectionAliases[] = $connectionAlias;
$connection = $client['options'];
$connection['logging'] = $client['logging'];
Expand Down
1 change: 1 addition & 0 deletions Resources/config/schema/redis-1.0.xsd
Expand Up @@ -58,6 +58,7 @@
<xsd:attribute name="profile" type="client-profile" />
<xsd:attribute name="cluster" type="xsd:string" />
<xsd:attribute name="prefix" type="xsd:string" />
<xsd:attribute name="replication" type="xsd:boolean" />
</xsd:complexType>

<xsd:simpleType name="client-profile">
Expand Down
21 changes: 21 additions & 0 deletions Resources/doc/index.md
Expand Up @@ -93,6 +93,26 @@ $val = $redis_cluster->get('ef:gh');
$val = $redis_cluster->get('ij:kl');
```

A setup using `predis` master-slave replication could look like this:

``` yaml
snc_redis:
clients:
default:
type: predis
alias: default
dsn:
- redis://master-host?alias=master
- redis://slave-host1
- redis://slave-host2
options:
replication: true
```

Please note that the master dsn connection needs to be tagged with the ```master``` alias.
If not, `predis` will complain.


### Sessions ###

Use Redis sessions by adding the following to your config:
Expand Down Expand Up @@ -248,6 +268,7 @@ snc_redis:
iterable_multibulk: false
throw_errors: true
cluster: Snc\RedisBundle\Client\Predis\Connection\PredisCluster
replication: false
session:
client: default
prefix: foo
Expand Down
29 changes: 16 additions & 13 deletions Tests/DependencyInjection/Configuration/RedisDsnTest.php
Expand Up @@ -242,31 +242,34 @@ public function testIsValid($dsn, $valid)
*
* @return array
*/
public static function weightValues()
public static function parameterValues()
{
return array(
array('redis://localhost', null),
array('redis://localhost/1?weight=1', 1),
array('redis://pw@localhost:63790/10?weight=2', 2),
array('redis://127.0.0.1?weight=3', 3),
array('redis://127.0.0.1/1?weight=4', 4),
array('redis://pw@127.0.0.1:63790/10?weight=5', 5),
array('redis:///redis.sock?weight=6', 6),
array('redis:///redis.sock/1?weight=7', 7),
array('redis://pw@/redis.sock/10?weight=8', 8),
array('redis://pw@/redis.sock/10?weight=9', 9),
array('redis://localhost', null, null),
array('redis://localhost/1?weight=1&alias=master', 1, 'master'),
array('redis://pw@localhost:63790/10?alias=master&weight=2', 2, 'master'),
array('redis://127.0.0.1?weight=3', 3, null),
array('redis://127.0.0.1/1?alias=master&weight=4', 4, 'master'),
array('redis://pw@127.0.0.1:63790/10?weight=5&alias=master', 5, 'master'),
array('redis:///redis.sock?weight=6&alias=master', 6, 'master'),
array('redis:///redis.sock/1?weight=7', 7, null),
array('redis://pw@/redis.sock/10?weight=8&alias=master', 8, 'master'),
array('redis://pw@/redis.sock/10?alias=master&weight=9', 9, 'master'),
array('redis://localhost?alias=master', null, 'master'),
);
}

/**
* @param string $dsn DSN
* @param int $weight Weight
* @param string $alias Alias
*
* @dataProvider weightValues
* @dataProvider parameterValues
*/
public function testParameterValues($dsn, $weight)
public function testParameterValues($dsn, $weight, $alias)
{
$dsn = new RedisDsn($dsn);
$this->assertSame($weight, $dsn->getWeight());
$this->assertSame($alias, $dsn->getAlias());
}
}
33 changes: 33 additions & 0 deletions Tests/DependencyInjection/SncRedisExtensionTest.php
Expand Up @@ -212,6 +212,23 @@ public function testConfigurationMerging()
$this->assertEquals(new RedisDsn('redis://test'), current($config['clients']['default']['dsns']));
}

/**
* Test valid config of the replication option
*/
public function testClientReplicationOption()
{
$extension = new SncRedisExtension();
$config = $this->parseYaml($this->getReplicationYamlConfig());
$extension->load(array($config), $container = new ContainerBuilder());

$options = $container->getDefinition('snc_redis.client.default_options')->getArgument(0);
$this->assertTrue($options['replication']);
$parameters = $container->getDefinition('snc_redis.default')->getArgument(0);
$this->assertEquals('snc_redis.connection.master_parameters', (string) $parameters[0]);
$masterParameters = $container->getDefinition((string) $parameters[0])->getArgument(0);
$this->assertTrue($masterParameters['replication']);
}

private function parseYaml($yaml)
{
$parser = new Parser();
Expand Down Expand Up @@ -268,6 +285,7 @@ private function getFullYamlConfig()
iterable_multibulk: false
throw_errors: true
cluster: Snc\RedisBundle\Client\Predis\Connection\PredisCluster
replication: false
session:
client: default
prefix: foo
Expand Down Expand Up @@ -329,6 +347,21 @@ private function getMergeConfig2()
clients:
default:
dsn: redis://test
EOF;
}

private function getReplicationYamlConfig()
{
return <<<'EOF'
clients:
default:
type: predis
alias: default
dsn:
- redis://localhost?alias=master
- redis://otherhost
options:
replication: true
EOF;
}
}

0 comments on commit 67646cf

Please sign in to comment.