From 1bf9c1131ba559ca387570cb1409d0dd22c17f29 Mon Sep 17 00:00:00 2001 From: Aleksandr Denisyuk Date: Wed, 26 Jun 2024 11:07:02 +0300 Subject: [PATCH] Update strategies --- src/Cluster/ClusterPool.php | 2 +- src/RoundRobinThrottler.php | 2 +- src/SmoothWeightedRoundRobinThrottler.php | 2 +- src/WeightedRandomThrottler.php | 2 +- src/WeightedRoundRobinThrottler.php | 45 ++++++++++++++++------- 5 files changed, 35 insertions(+), 18 deletions(-) diff --git a/src/Cluster/ClusterPool.php b/src/Cluster/ClusterPool.php index 315af84..6b98c0f 100644 --- a/src/Cluster/ClusterPool.php +++ b/src/Cluster/ClusterPool.php @@ -42,7 +42,7 @@ public function pick(CollectionInterface $collection, array $context = []): Node } if (!\is_string($context['cluster'])) { - throw new \RuntimeException('The parameter "cluster" must be as a string.'); // @codeCoverageIgnore + throw new \RuntimeException(sprintf('The parameter "cluster" must be as a string, %s given.', get_debug_type($context['cluster']))); // @codeCoverageIgnore } if (!isset($this->clusterNames[$context['cluster']])) { diff --git a/src/RoundRobinThrottler.php b/src/RoundRobinThrottler.php index fbd734a..aa1e140 100644 --- a/src/RoundRobinThrottler.php +++ b/src/RoundRobinThrottler.php @@ -25,7 +25,7 @@ public function pick(CollectionInterface $collection, array $context = []): Node } if (isset($context['counter']) && !\is_string($context['counter'])) { - throw new \RuntimeException(sprintf('The parameter "counter" must be as string, %s given.', get_debug_type($context['counter']))); // @codeCoverageIgnore + throw new \RuntimeException(sprintf('The parameter "counter" must be as a string, %s given.', get_debug_type($context['counter']))); // @codeCoverageIgnore } $counter = $context['counter'] ?? spl_object_hash($collection); diff --git a/src/SmoothWeightedRoundRobinThrottler.php b/src/SmoothWeightedRoundRobinThrottler.php index 4344cb2..1c0d893 100644 --- a/src/SmoothWeightedRoundRobinThrottler.php +++ b/src/SmoothWeightedRoundRobinThrottler.php @@ -28,7 +28,7 @@ public function pick(CollectionInterface $collection, array $context = []): Node } if (isset($context['counter']) && !\is_string($context['counter'])) { - throw new \RuntimeException(sprintf('The parameter "counter" must be as string, %s given.', get_debug_type($context['counter']))); // @codeCoverageIgnore + throw new \RuntimeException(sprintf('The parameter "counter" must be as a string, %s given.', get_debug_type($context['counter']))); // @codeCoverageIgnore } $counter = $context['counter'] ?? spl_object_hash($collection); diff --git a/src/WeightedRandomThrottler.php b/src/WeightedRandomThrottler.php index 5a91adc..50ffdf7 100644 --- a/src/WeightedRandomThrottler.php +++ b/src/WeightedRandomThrottler.php @@ -23,7 +23,7 @@ public function pick(CollectionInterface $collection, array $context = []): Node $randomWeight = mt_rand(1, $sumWeight); foreach ($collection as $node) { - if (0 == $node->getWeight()) { + if (0 === $node->getWeight()) { throw new \RuntimeException('All nodes in the collection must be weighted.'); // @codeCoverageIgnore } diff --git a/src/WeightedRoundRobinThrottler.php b/src/WeightedRoundRobinThrottler.php index 570d00b..80a5465 100644 --- a/src/WeightedRoundRobinThrottler.php +++ b/src/WeightedRoundRobinThrottler.php @@ -10,9 +10,18 @@ final class WeightedRoundRobinThrottler implements ThrottlerInterface { - private int $gcdWeight = 0; - private int $maxWeight = 0; - private int $currentWeight = 0; + /** + * @var array + */ + private array $gcdWeight = []; + /** + * @var array + */ + private array $maxWeight = []; + /** + * @var array + */ + private array $currentWeight = []; public function __construct( private CounterInterface $counter, @@ -29,34 +38,42 @@ public function pick(CollectionInterface $collection, array $context = []): Node } if (isset($context['counter']) && !\is_string($context['counter'])) { - throw new \RuntimeException(sprintf('The parameter "counter" must be as string, %s given.', get_debug_type($context['counter']))); // @codeCoverageIgnore + throw new \RuntimeException(sprintf('The parameter "counter" must be as a string, %s given.', get_debug_type($context['counter']))); // @codeCoverageIgnore } $counter = $context['counter'] ?? spl_object_hash($collection); - foreach ($collection as $node) { - if (0 == $node->getWeight()) { - throw new \RuntimeException('All nodes in the collection must be weighted.'); // @codeCoverageIgnore - } + if (!isset($this->gcdWeight[$counter]) || !isset($this->maxWeight[$counter]) || !isset($this->currentWeight[$counter])) { + $this->gcdWeight[$counter] = 0; + $this->maxWeight[$counter] = 0; + $this->currentWeight[$counter] = 0; + } - $this->gcdWeight = gcd($this->gcdWeight, $node->getWeight()); - $this->maxWeight = max($this->maxWeight, $node->getWeight()); + if (0 === $this->gcdWeight[$counter] || 0 === $this->maxWeight[$counter] || 0 === $this->currentWeight[$counter]) { + foreach ($collection as $node) { + if (0 === $node->getWeight()) { + throw new \RuntimeException('All nodes in the collection must be weighted.'); // @codeCoverageIgnore + } + + $this->gcdWeight[$counter] = gcd($this->gcdWeight[$counter], $node->getWeight()); + $this->maxWeight[$counter] = max($this->maxWeight[$counter], $node->getWeight()); + } } while (true) { $key = $this->counter->next($counter) % \count($collection); if (0 == $key) { - $this->currentWeight -= $this->gcdWeight; + $this->currentWeight[$counter] -= $this->gcdWeight[$counter]; - if (0 >= $this->currentWeight) { - $this->currentWeight = $this->maxWeight; + if (0 >= $this->currentWeight[$counter]) { + $this->currentWeight[$counter] = $this->maxWeight[$counter]; } } $node = $collection->get($key); - if ($node->getWeight() >= $this->currentWeight) { + if ($node->getWeight() >= $this->currentWeight[$counter]) { return $node; } }