Replace riak client with php-riak/riak-client

This commit is contained in:
EmanueleMinotto
2019-09-06 23:59:07 +02:00
parent 186c8e04d2
commit 8f07e47320
4 changed files with 186 additions and 217 deletions

View File

@@ -9,14 +9,13 @@
"doctrine/couchdb": "^1.0.0-beta4",
"phpunit/phpunit": "^4.8|^5.0",
"aws/aws-sdk-php": "^3.8",
"riak/riak-client": "dev-master",
"php-riak/riak-client": "^1.0@alpha",
"mongodb/mongodb": "^1.4"
},
"suggest": {
"aws/aws-sdk-php": "to use the DynamoDB storage",
"doctrine/couchdb": "to use the CouchDB storage",
"ext-couchbase": "to use the Couchbase storage",
"riak/riak-client": "to use the Riak storage"
"ext-couchbase": "to use the Couchbase storage"
},
"description": "Simple Key-Value Store Abstraction Layer that maps to PHP objects, allowing for many backends.",
"license": "MIT",

View File

@@ -242,15 +242,17 @@ instance.
Riak
----
Riak support is provided through the library `riak/riak-client <https://github.com/nacmartin/riak-client>`_ :
Riak support is provided through the library `php-riak/riak-client <https://github.com/php-riak/riak-client>`_ :
.. code-block:: php
<?php
use Doctrine\KeyValueStore\Storage\RiakStorage;
use Riak\Client;
use Riak\Client\RiakClientBuilder;
$conn = new Riak(/* connection parameters */);
$conn = (new RiakClientBuilder())
->withNodeUri(/* connection DNS */)
->build();
$storage = new RiakStorage($conn);

View File

@@ -21,7 +21,14 @@
namespace Doctrine\KeyValueStore\Storage;
use Doctrine\KeyValueStore\NotFoundException;
use Riak\Client;
use Riak\Client\Command\Kv\DeleteValue;
use Riak\Client\Command\Kv\FetchValue;
use Riak\Client\Command\Kv\StoreValue;
use Riak\Client\Core\Query\RiakLocation;
use Riak\Client\Core\Query\RiakNamespace;
use Riak\Client\Core\Query\RiakObject;
use Riak\Client\RiakClient;
use Riak\Client\RiakException;
/**
* @author Markus Bachmann <markus.bachmann@bachi.biz>
@@ -29,17 +36,11 @@ use Riak\Client;
class RiakStorage implements Storage
{
/**
* @var \Riak\Client
* @var RiakClient
*/
protected $client;
private $client;
/**
* Constructor
*
* @param \Riak\Client $riak
* @param string $bucketName
*/
public function __construct(Client $riak)
public function __construct(RiakClient $riak)
{
$this->client = $riak;
}
@@ -68,14 +69,25 @@ class RiakStorage implements Storage
return false;
}
private function store($storageName, $key, array $data)
{
$location = $this->getRiakLocation($storageName, $key);
$riakObject = new RiakObject();
$riakObject->setContentType('application/json');
$riakObject->setValue(json_encode($data));
$store = StoreValue::builder($location, $riakObject)->build();
$this->client->execute($store);
}
/**
* {@inheritDoc}
*/
public function insert($storageName, $key, array $data)
{
$bucket = $this->client->bucket($storageName);
$object = $bucket->newObject($key, $data);
$object->store();
$this->store($storageName, $key, $data);
}
/**
@@ -83,12 +95,7 @@ class RiakStorage implements Storage
*/
public function update($storageName, $key, array $data)
{
$bucket = $this->client->bucket($storageName);
/** @var $object \Riak\Object */
$object = $bucket->get($key);
$object->setData($data);
$object->store();
$this->store($storageName, $key, $data);
}
/**
@@ -96,17 +103,15 @@ class RiakStorage implements Storage
*/
public function delete($storageName, $key)
{
$bucket = $this->client->bucket($storageName);
$location = $this->getRiakLocation($storageName, $key);
/** @var $object \Riak\Object */
$object = $bucket->get($key);
$delete = DeleteValue::builder($location)->build();
if (! $object->exists()) {
// object does not exist, do nothing
return;
try {
$this->client->execute($delete);
} catch (RiakException $exception) {
// deletion can fail silent
}
$object->delete();
}
/**
@@ -114,16 +119,29 @@ class RiakStorage implements Storage
*/
public function find($storageName, $key)
{
$bucket = $this->client->bucket($storageName);
$location = $this->getRiakLocation($storageName, $key);
/** @var $object \Riak\Object */
$object = $bucket->get($key);
// fetch object
$fetch = FetchValue::builder($location)->build();
if (! $object->exists()) {
throw new NotFoundException;
try {
$result = $this->client->execute($fetch);
} catch (RiakException $exception) {
throw new NotFoundException();
}
return $object->getData();
$json = (string) $result
->getValue()
->getValue();
return json_decode($json, true);
}
private function getRiakLocation($storageName, $key)
{
$namespace = new RiakNamespace('default', $storageName);
return new RiakLocation($namespace, $key);
}
/**

View File

@@ -20,34 +20,46 @@
namespace Doctrine\Tests\KeyValueStore\Storage;
use Doctrine\KeyValueStore\NotFoundException;
use Doctrine\KeyValueStore\Storage\RiakStorage;
use PHPUnit_Framework_TestCase;
use Riak\Client\Command\Kv\Builder\ListKeysBuilder;
use Riak\Client\Command\Kv\FetchValue;
use Riak\Client\Core\Query\RiakLocation;
use Riak\Client\Core\Query\RiakNamespace;
use Riak\Client\Core\Query\RiakObject;
use Riak\Client\Core\Transport\RiakTransportException;
use Riak\Client\RiakClient;
use Riak\Client\RiakClientBuilder;
/**
* @author Markus Bachmann <markus.bachmann@bachi.biz>
*/
class RiakStorageTest extends \PHPUnit_Framework_TestCase
class RiakStorageTest extends PHPUnit_Framework_TestCase
{
/**
* @var RiakClient
*/
private $client;
/**
* @var RiakStorage
*/
private $storage;
/**
* @var \PHPUnit_Framework_MockObject_MockObject
*/
private $riak;
protected function setup()
protected function setUp()
{
if (PHP_MAJOR_VERSION >= 7) {
$this->markTestSkipped('Riak extension is not available for PHP versions >= 7');
$dns = getenv('RIAK_DNS');
if (empty($dns)) {
$this->markTestSkipped('Missing Riak DNS');
}
$this->riak = $this->getMockBuilder('Riak\\Client')
->disableOriginalConstructor()
->getMock();
$this->client = (new RiakClientBuilder())
->withNodeUri($dns)
->build();
$this->storage = new RiakStorage($this->riak);
$this->storage = new RiakStorage($this->client);
}
public function testSupportsPartialUpdates()
@@ -67,186 +79,124 @@ class RiakStorageTest extends \PHPUnit_Framework_TestCase
public function testInsert()
{
$bucket = $this->getMockBuilder('Riak\Bucket')
->disableOriginalConstructor()
->getMock();
$data = [
'title' => 'Riak test',
];
$this->riak->expects($this->once())
->method('bucket')
->will($this->returnValue($bucket));
$this->storage->insert('riak-test', 'foobar', $data);
$objectMock = $this->getMockBuilder('Riak\Object')
->disableOriginalConstructor()
->getMock();
$location = $this->getRiakLocation();
$objectMock->expects($this->once())
->method('store');
$fetch = FetchValue::builder($location)->build();
$that = $this;
$bucket->expects($this->once())
->method('newObject')
->will($this->returnCallback(function ($key, $data) use ($objectMock, $that) {
$that->assertEquals('foobar', $key);
$that->assertEquals(['title' => 'Riak test'], $data);
return $objectMock;
}));
$json = (string) $this->client
->execute($fetch)
->getValue()
->getValue();
$this->storage->insert('riak-test', 'foobar', ['title' => 'Riak test']);
}
public function testUpdate()
{
$objectMock = $this->getMockBuilder('Riak\Object')
->disableOriginalConstructor()
->getMock();
$bucket = $this->getMockBuilder('Riak\Bucket')
->disableOriginalConstructor()
->getMock();
$this->riak->expects($this->once())
->method('bucket')
->will($this->returnValue($bucket));
$bucket->expects($this->once())
->method('get')
->will($this->returnValue($objectMock));
$that = $this;
$objectMock->expects($this->once())
->method('setData')
->will($this->returnCallback(function ($data) use ($that) {
$that->assertEquals(['title' => 'Riak cookbook'], $data);
}));
$objectMock->expects($this->once())
->method('store');
$this->storage->update('riak-test', 'foobar', ['title' => 'Riak cookbook']);
}
public function testDelete()
{
$objectMock = $this->getMockBuilder('Riak\Object')
->disableOriginalConstructor()
->getMock();
$bucket = $this->getMockBuilder('Riak\Bucket')
->disableOriginalConstructor()
->getMock();
$this->riak->expects($this->once())
->method('bucket')
->will($this->returnValue($bucket));
$bucket->expects($this->once())
->method('get')
->with('foobar')
->will($this->returnValue($objectMock));
$objectMock->expects($this->once())
->method('exists')
->will($this->returnValue(true));
$objectMock->expects($this->once())
->method('delete');
$this->storage->delete('riak-test', 'foobar');
}
public function testDeleteWithNotExistKey()
{
$objectMock = $this->getMockBuilder('Riak\Object')
->disableOriginalConstructor()
->getMock();
$bucket = $this->getMockBuilder('Riak\Bucket')
->disableOriginalConstructor()
->getMock();
$this->riak->expects($this->once())
->method('bucket')
->will($this->returnValue($bucket));
$bucket->expects($this->once())
->method('get')
->with('foobar')
->will($this->returnValue($objectMock));
$objectMock->expects($this->once())
->method('exists')
->will($this->returnValue(false));
$objectMock->expects($this->never())
->method('delete');
$this->storage->delete('riak-test', 'foobar');
}
public function testFind()
{
$objectMock = $this->getMockBuilder('Riak\Object')
->disableOriginalConstructor()
->getMock();
$bucket = $this->getMockBuilder('Riak\Bucket')
->disableOriginalConstructor()
->getMock();
$this->riak->expects($this->once())
->method('bucket')
->will($this->returnValue($bucket));
$bucket->expects($this->once())
->method('get')
->with('foobar')
->will($this->returnValue($objectMock));
$objectMock->expects($this->once())
->method('exists')
->will($this->returnValue(true));
$objectMock->expects($this->once())
->method('getData')
->will($this->returnValue(['title' => 'Riak Test']));
$this->assertEquals(['title' => 'Riak Test'], $this->storage->find('riaktest', 'foobar'));
$this->assertSame($data, json_decode($json, true));
}
/**
* @expectedException Doctrine\KeyValueStore\NotFoundException
* @depends testInsert
*/
public function testUpdate()
{
$data = [
'title' => 'Riak update',
];
$this->storage->insert('riak-test', 'foobar', [
'title' => 'Riak insert',
]);
$location = $this->getRiakLocation();
$this->assertTotalBucketKeys(1, $location);
$this->storage->update('riak-test', 'foobar', $data);
$fetch = FetchValue::builder($location)->build();
$json = (string) $this->client
->execute($fetch)
->getValue()
->getValue();
$this->assertSame($data, json_decode($json, true));
$this->assertTotalBucketKeys(1, $location);
}
/**
* @depends testInsert
*/
public function testDelete()
{
$this->testInsert();
$this->storage->delete('riak-test', 'foobar');
$location = $this->getRiakLocation();
$fetch = FetchValue::builder($location)->build();
$this->setExpectedException(RiakTransportException::class);
$this->client->execute($fetch);
$this->assertTotalBucketKeys(0, $location);
}
/**
* @depends testDelete
*/
public function testDeleteWithNotExistKey()
{
$this->storage->delete('riak-test', 'foobar');
$this->storage->delete('riak-test', 'foobar');
}
/**
* @depends testInsert
*/
public function testFind()
{
$data = [
'title' => 'Riak test',
];
$this->storage->insert('riak-test', 'foobar', $data);
$result = $this->storage->find('riak-test', 'foobar');
$this->assertSame($data, $result);
}
public function testFindWithNotExistKey()
{
$objectMock = $this->getMockBuilder('Riak\Object')
->disableOriginalConstructor()
->getMock();
$bucket = $this->getMockBuilder('Riak\Bucket')
->disableOriginalConstructor()
->getMock();
$this->riak->expects($this->once())
->method('bucket')
->will($this->returnValue($bucket));
$bucket->expects($this->once())
->method('get')
->with('foobar')
->will($this->returnValue($objectMock));
$objectMock->expects($this->once())
->method('exists')
->will($this->returnValue(false));
$objectMock->expects($this->never())
->method('getData');
$this->storage->find('riak-test', 'foobar');
$this->setExpectedException(NotFoundException::class);
$this->storage->find('riak-test', 'foobar-1');
}
public function testGetName()
{
$this->assertEquals('riak', $this->storage->getName());
}
private function assertTotalBucketKeys($expectedTotal, $location)
{
$command = (new ListKeysBuilder($location->getNamespace()))->build();
$iterator = $this->client
->execute($command)
->getIterator();
$this->assertCount($expectedTotal, iterator_to_array($iterator));
}
private function getRiakLocation()
{
$namespace = new RiakNamespace('default', 'riak-test');
return new RiakLocation($namespace, 'foobar');
}
}