public function lookupList($resource, $requestedCount)
{
if (!$requestedCount) {
throw new Exception('Invalid count requested');
}
// handle no targets
if (empty($this->positionToTarget)) {
return [];
}
// optimize single target
if ($this->targetCount == 1) {
return array_unique(array_values($this->positionToTarget));
}
// hash resource to a position
$resourcePosition = $this->hasher->hash($resource);
$results = [];
$collect = false;
$this->sortPositionTargets();
// search values above the resourcePosition
foreach ($this->positionToTarget as $key => $value) {
// start collecting targets after passing resource position
if (!$collect && $key > $resourcePosition) {
$collect = true;
}
// only collect the first instance of any target
if ($collect && !in_array($value, $results)) {
$results[] = $value;
}
// return when enough results, or list exhausted
if (count($results) == $requestedCount || count($results) == $this->targetCount) {
return $results;
}
}
// loop to start - search values below the resourcePosition
foreach ($this->positionToTarget as $key => $value) {
if (!in_array($value, $results)) {
$results[] = $value;
}
// return when enough results, or list exhausted
if (count($results) == $requestedCount || count($results) == $this->targetCount) {
return $results;
}
}
// return results after iterating through both "parts"
return $results;
}
public function testFallbackPrecedenceWhenServerRemoved() { $mockHasher = new MockHasher(); $hashSpace = new Flexihash($mockHasher, 1); $mockHasher->setHashValue(10); $hashSpace->addTarget('t1'); $mockHasher->setHashValue(20); $hashSpace->addTarget('t2'); $mockHasher->setHashValue(30); $hashSpace->addTarget('t3'); $mockHasher->setHashValue(15); $this->assertEquals($hashSpace->lookup('resource'), 't2'); $this->assertEquals($hashSpace->lookupList('resource', 3), ['t2', 't3', 't1']); $hashSpace->removeTarget('t2'); $this->assertEquals($hashSpace->lookup('resource'), 't3'); $this->assertEquals($hashSpace->lookupList('resource', 3), ['t3', 't1']); $hashSpace->removeTarget('t3'); $this->assertEquals($hashSpace->lookup('resource'), 't1'); $this->assertEquals($hashSpace->lookupList('resource', 3), ['t1']); }