-
Notifications
You must be signed in to change notification settings - Fork 12
Closed
Milestone
Description
In order to make the API easier to use would be nice to have conflict resolution strategies..
- Add attribute
Riak\Input\PutInput#conflictResolver - Add attribute
Riak\Bucket#conflictResolver - Add method
Riak\Output\Output#getObject() - Add interface
Riak\Output\Resolver\ConflictResolver - Add exception
Riak\NonUniqueException - Add exception
Riak\UnresolvedConflictException
API Changes :
<?php
namespace Riak\Output;
class PutOutput
{
// ...
/**
* Retrieves a unique riak object
*
* If this output contain more than one object
* it will try to resolve its siblings using a ConflictResolver specified by PutInput or Bucket
*
* if there are no ConflictResolver configured for its Bucket nor PutInput it will throws a NonUniqueException
* otherwise the ConflictResolver will be responsible for resolving the siblings into a single object.
*
* @return \Riak\Object
*
* @throws \Riak\NotFoundException If this output contain none objects
* @throws \Riak\NonUniqueException If this output contain more than one object
* @throws \Riak\UnresolvedConflictException If the ConflictResolver cannot determine a single object.
*/
public function getObject(){}
}
namespace Riak\Output\Resolver;
interface ConflictResolver
{
/**
* Applies encoded logic to produce a single value from a list of siblings.
*
* @param \Riak\Bucket $bucket
* @param \Riak\Output\Output $output
* @param \Riak\Input\PutInput|null $putInput
*
* @return \Riak\Object
*
* @throws \Riak\UnresolvedConflictException If it cannot determine a single value.
*/
public function resolve(Bucket $bucket, Output $output, PutInput $putInput = null);
}Some basic built-in conflict resolver
FirstSiblingResolver- Resolve the conflict using the first object in Output#objectlistLastSiblingResolver- Resolve the conflict using the last object in Output#objectlist
API Usage :
Manually resolving siblings
<?php
$props = new \Riak\BucketPropertyList($nVal = 3, $allowMult = true);
$bucket = new \Riak\Bucket($client, 'test_bucket');
$output = null;
try {
$output = $bucket->get($key);
$object = $output->getObject();
} catch (\Riak\NotFoundException $e) {
// Not found
} catch (\Riak\NonUniqueException $e) {
$winner = doSomeMagicAndResolveTheWinner();
$options = new \Riak\Input\PutInput();
$options->setVClock($output->getVClock());
$bucket->put($winner, $options);
$output = $winner;
}Auto resolving sibling using the last object
<?php
$props = new \Riak\BucketPropertyList($nVal = 3, $allowMult = true);
$bucket = new \Riak\Bucket($client, 'test_bucket');
// Configure a default resolver
$props->setConflictResolver(new LastSiblingResolver());
$bucket->setPropertyList($props);
$output = $bucket->get($key);
// this $output contain more than one object
echo $output->hasSiblings();
// Resolve the conflict using the LastSiblingResolver
$object = $output->getObject();Auto resolving a specific key using a custom ConflictResolver
<?php
class MyResolver implements ConflictResolver
{
/**
* {@inheritdoc}
*/
public function resolve(Bucket $bucket, Output $output, PutInput $putInput = null)
{
$winner = doSomeMagicAndResolveTheWinner();
$options = new \Riak\Input\PutInput();
$options->setVClock($output->getVClock());
$bucket->put($winner, $options);
return $winner;
}
}
$props = new \Riak\BucketPropertyList($nVal = 3, $allowMult = true);
$options = \Riak\Input\GetInput();
// Configure a resolver for a specific get operation
$options->setConflictResolver(new MyResolver());
$bucket->setPropertyList($props);
$output = $bucket->get($key, $options);
// this $output contain more than one object
echo $output->hasSiblings();
// Resolve the conflict using MyResolver
$object = $output->getObject();If you guys agree with this approach I'll be happy to prepare a PR ;)
PS: We could probably use a similar approach to handle retry policies during get/put operations..
Cheers ..
Metadata
Metadata
Assignees
Labels
No labels