Skip to content

Commit 52f296f

Browse files
author
Willem Stuursma
committed
Merge branch '16-predis-cluster'
2 parents 96cd2d8 + 8d6d6f4 commit 52f296f

File tree

5 files changed

+71
-23
lines changed

5 files changed

+71
-23
lines changed

.travis.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ php:
1616
env:
1717
global:
1818
- MEMCACHE_HOST=localhost
19-
- REDIS_URIS=redis://localhost,redis://localhost:63791
19+
- REDIS_URIS=redis://localhost:63791,redis://localhost:63792,redis://localhost:63793
2020
- MYSQL_DSN="mysql:host=localhost;dbname=test"
2121
- MYSQL_USER=travis
2222
- PGSQL_DSN="pgsql:host=localhost;dbname=test;"
@@ -36,6 +36,8 @@ matrix:
3636
before_install:
3737
- phpenv config-add tests/php-travis.ini
3838
- redis-server --port 63791 &
39+
- redis-server --port 63792 &
40+
- redis-server --port 63793 &
3941

4042
install:
4143
- composer install --no-scripts --no-suggest --no-interaction

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,9 @@ which uses the [`phpredis` extension](https://github.com/phpredis/phpredis).
150150

151151
This implementation requires at least `phpredis-2.2.4`.
152152

153+
If used with a cluster of Redis servers, acquiring and releasing locks will continue to function as
154+
long as a majority of the servers still works.
155+
153156
Example:
154157
```php
155158
$redis = new Redis();

tests/mutex/MutexConcurrencyTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@ function ($uri) {
281281
}];
282282

283283
$cases["PHPRedisMutex"] = [function ($timeout = 3) use ($uris) {
284+
/** @var Redis[] $apis */
284285
$apis = array_map(
285286
function ($uri) {
286287
$redis = new Redis();

tests/mutex/MutexTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ function ($uri) {
110110
}];
111111

112112
$cases["PHPRedisMutex"] = [function () use ($uris) {
113+
/** @var Redis[] $apis */
113114
$apis = array_map(
114115
function ($uri) {
115116
$redis = new Redis();

tests/mutex/PHPRedisMutexTest.php

Lines changed: 63 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@
2121
class PHPRedisMutexTest extends \PHPUnit_Framework_TestCase
2222
{
2323
/**
24-
* @var Redis The Redis API.
24+
* @var Redis[]
2525
*/
26-
private $redis;
27-
26+
private $connections = [];
27+
2828
/**
2929
* @var PHPRedisMutex The SUT.
3030
*/
@@ -34,31 +34,53 @@ protected function setUp()
3434
{
3535
parent::setUp();
3636

37-
$this->redis = new Redis();
38-
3937
$uris = explode(",", getenv("REDIS_URIS") ?: "redis://localhost");
40-
$uri = parse_url($uris[0]);
41-
if (!empty($uri["port"])) {
42-
$this->redis->connect($uri["host"], $uri["port"]);
43-
} else {
44-
$this->redis->connect($uri["host"]);
38+
39+
foreach ($uris as $redisUri) {
40+
$uri = parse_url($redisUri);
41+
42+
$connection = new Redis();
43+
44+
if (!empty($uri["port"])) {
45+
$connection->connect($uri["host"], $uri["port"]);
46+
} else {
47+
$connection->connect($uri["host"]);
48+
}
49+
50+
$connection->flushAll(); // Clear any existing locks.
51+
52+
$this->connections[] = $connection;
4553
}
4654

47-
$this->redis->flushAll(); // Clear any existing locks.
55+
$this->mutex = new PHPRedisMutex($this->connections, "test");
56+
}
57+
58+
private function closeMajorityConnections()
59+
{
60+
$numberToClose = ceil(count($this->connections) / 2);
61+
62+
foreach (array_rand($this->connections, $numberToClose) as $keyToClose) {
63+
$this->connections[$keyToClose]->close();
64+
}
65+
}
66+
67+
private function closeMinortyConnections()
68+
{
69+
$numberToClose = ceil(count($this->connections) / 2) - 1;
4870

49-
$this->mutex = new PHPRedisMutex([$this->redis], "test");
71+
foreach ((array) array_rand($this->connections, $numberToClose) as $keyToClose) {
72+
$this->connections[$keyToClose]->close();
73+
}
5074
}
5175

5276
/**
53-
* Tests add() fails.
54-
*
55-
* @test
5677
* @expectedException \malkusch\lock\exception\LockAcquireException
5778
* @expectedExceptionCode \malkusch\lock\exception\MutexException::REDIS_NOT_ENOUGH_SERVERS
5879
*/
5980
public function testAddFails()
6081
{
61-
$this->redis->close();
82+
$this->closeMajorityConnections();
83+
6284
$this->mutex->synchronized(function () {
6385
$this->fail("Code execution is not expected");
6486
});
@@ -73,21 +95,40 @@ public function testAddFails()
7395
public function testEvalScriptFails()
7496
{
7597
$this->mutex->synchronized(function () {
76-
$this->redis->close();
98+
$this->closeMajorityConnections();
7799
});
78100
}
79101

80102
/**
81103
* @param $serialization
82104
* @dataProvider dpSerializationModes
83105
*/
84-
public function testSyncronizedWorks($serialization)
106+
public function testSynchronizedWorks($serialization)
85107
{
86-
$this->redis->setOption(Redis::OPT_SERIALIZER, $serialization);
108+
foreach ($this->connections as $connection) {
109+
$connection->setOption(Redis::OPT_SERIALIZER, $serialization);
110+
}
87111

88-
$this->mutex->synchronized(function () {
89-
$this->assertTrue(true);
90-
});
112+
$this->assertNull($this->mutex->synchronized(function () {
113+
return null;
114+
}));
115+
}
116+
117+
public function testResistantToPartialClusterFailuresForAcquiringLock()
118+
{
119+
$this->closeMinortyConnections();
120+
121+
$this->assertNull($this->mutex->synchronized(function () {
122+
return null;
123+
}));
124+
}
125+
126+
public function testResistantToPartialClusterFailuresForReleasingLock()
127+
{
128+
$this->assertNull($this->mutex->synchronized(function () {
129+
$this->closeMinortyConnections();
130+
return null;
131+
}));
91132
}
92133

93134
public function dpSerializationModes()

0 commit comments

Comments
 (0)