Skip to content

Commit 41a2afe

Browse files
Merge pull request #9 from shadowhand/feature/redis-adapter
Add Redis storage adapter
2 parents 39ad702 + ff49439 commit 41a2afe

File tree

4 files changed

+170
-3
lines changed

4 files changed

+170
-3
lines changed

README.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,15 @@ Storage
4040
There are a number of different storage implementations for where the configuration for the rollout is stored.
4141

4242
* ArrayStorage - default storage, not persistent
43-
* DoctrineCacheStorageAdapter - requires `doctrine/cache`
44-
* PDOStorageAdapter - persistent with a simple \PDO object
43+
* DoctrineCacheStorageAdapter - requires [doctrine/cache][doctrine-cache]
44+
* PDOStorageAdapter - persistent using [PDO][pdo]
45+
* RedisStorageAdapter - persistent using [Redis][redis]
4546

46-
The storage implementation must implement the `Storage\StorageInterface`'s methods.
47+
[doctrine-cache]: https://packagist.org/packages/doctrine/cache
48+
[pdo]: http://php.net/pdo
49+
[redis]: http://redis.io
50+
51+
All storage adapters must implement `Opensoft\Rollout\Storage\StorageInterface`.
4752

4853
Groups
4954
------

phpunit.xml.dist

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,8 @@
2525
</whitelist>
2626
</filter>
2727

28+
<logging>
29+
<log type="coverage-text" target="php://stdout"/>
30+
</logging>
31+
2832
</phpunit>
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
3+
namespace Opensoft\Rollout\Storage;
4+
5+
/**
6+
* Storage adapter using Redis
7+
*
8+
* @author Woody Gilk <@shadowhand>
9+
*/
10+
class RedisStorageAdapter implements StorageInterface
11+
{
12+
/**
13+
* @var string
14+
*/
15+
const DEFAULT_GROUP = 'rollout_feature';
16+
17+
/**
18+
* @var object
19+
*/
20+
private $redis;
21+
22+
/**
23+
* @var string
24+
*/
25+
private $group = self::DEFAULT_GROUP;
26+
27+
public function __construct($redis, $group = null)
28+
{
29+
$this->redis = $redis;
30+
31+
if ($group) {
32+
$this->group = $group;
33+
}
34+
}
35+
36+
/**
37+
* @inheritdoc
38+
*/
39+
public function get($key)
40+
{
41+
$result = $this->redis->hget($this->group, $key);
42+
43+
if (empty($result)) {
44+
return null;
45+
}
46+
47+
$result = json_decode($result, true);
48+
49+
if (JSON_ERROR_NONE !== json_last_error()) {
50+
return null;
51+
}
52+
53+
return $result;
54+
}
55+
56+
/**
57+
* @inheritdoc
58+
*/
59+
public function set($key, $value)
60+
{
61+
$this->redis->hset($this->group, $key, json_encode($value));
62+
}
63+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
<?php
2+
3+
namespace Opensoft\Tests\Storage;
4+
5+
use Opensoft\Rollout\Storage\RedisStorageAdapter;
6+
7+
class RedisStorageAdapterTest extends \PHPUnit_Framework_TestCase
8+
{
9+
private $redis;
10+
11+
public function setUp()
12+
{
13+
$this->redis = $this->getMockBuilder('\Opensoft\Tests\Storage\mockRedis')->getMock();
14+
}
15+
16+
public function testGet()
17+
{
18+
$this->redis->expects($this->once())
19+
->method('hget')
20+
->with(RedisStorageAdapter::DEFAULT_GROUP, 'key')
21+
->willReturn(json_encode('success'));
22+
23+
$adapter = new RedisStorageAdapter($this->redis);
24+
25+
$result = $adapter->get('key');
26+
$this->assertSame('success', $result);
27+
}
28+
29+
public function testGetWithCustomGroup()
30+
{
31+
$this->redis->expects($this->once())
32+
->method('hget')
33+
->with('rollout_test', 'key')
34+
->willReturn(json_encode('success'));
35+
36+
$adapter = new RedisStorageAdapter($this->redis, 'rollout_test');
37+
38+
$result = $adapter->get('key');
39+
$this->assertSame('success', $result);
40+
}
41+
42+
public function testGetNotExistsFailure()
43+
{
44+
$this->redis->expects($this->once())
45+
->method('hget')
46+
->with(RedisStorageAdapter::DEFAULT_GROUP, 'key')
47+
->willReturn('');
48+
49+
$adapter = new RedisStorageAdapter($this->redis);
50+
51+
$result = $adapter->get('key');
52+
$this->assertNull($result);
53+
}
54+
55+
public function testGetJsonDecodeFailure()
56+
{
57+
$this->redis->expects($this->once())
58+
->method('hget')
59+
->with(RedisStorageAdapter::DEFAULT_GROUP, 'key')
60+
->willReturn('not json');
61+
62+
$adapter = new RedisStorageAdapter($this->redis);
63+
64+
$result = $adapter->get('key');
65+
$this->assertNull($result);
66+
}
67+
68+
public function testSet()
69+
{
70+
$this->redis->expects($this->once())
71+
->method('hset')
72+
->with(RedisStorageAdapter::DEFAULT_GROUP, 'key', json_encode('value'));
73+
74+
$adapter = new RedisStorageAdapter($this->redis);
75+
76+
$adapter->set('key', 'value');
77+
}
78+
79+
public function testSetWithCustomGroup()
80+
{
81+
$this->redis->expects($this->once())
82+
->method('hset')
83+
->with('rollout_test', 'key', json_encode('value'));
84+
85+
$adapter = new RedisStorageAdapter($this->redis, 'rollout_test');
86+
87+
$adapter->set('key', 'value');
88+
}
89+
}
90+
91+
interface mockRedis
92+
{
93+
public function hget($key, $field);
94+
public function hset($key, $field, $value);
95+
}

0 commit comments

Comments
 (0)