diff --git a/build/logs/clover.xml b/build/logs/clover.xml deleted file mode 100644 index fe8b4a0..0000000 --- a/build/logs/clover.xml +++ /dev/null @@ -1,3294 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Cache/AbstractCacheItem.php b/src/Cache/AbstractCacheItem.php new file mode 100644 index 0000000..aa42db0 --- /dev/null +++ b/src/Cache/AbstractCacheItem.php @@ -0,0 +1,38 @@ +fromArray($array); + } + + /** + * @return array + */ + public function serialize() + { + return json_encode($this->toArray()); + } + + /** + * Wake up call to build the cache item object from array representation + * + * @param array $array + */ + abstract protected function fromArray(array $array); + + /** + * Get the array representation of the object + * + * @return array + */ + abstract protected function toArray(): array; +} \ No newline at end of file diff --git a/src/Cache/ThrottlerCache.php b/src/Cache/ThrottlerCache.php index a6cd2ba..bcecaec 100644 --- a/src/Cache/ThrottlerCache.php +++ b/src/Cache/ThrottlerCache.php @@ -48,77 +48,39 @@ public function __construct(CacheItemPoolInterface $cacheItemPool) } /** - * @param string $key - * - * @return ThrottlerItemInterface + * @inheritdoc */ public function getItem(string $key): ThrottlerItemInterface { - $item = $this->getThrottlerItem($key); - - return $item; - } - - /** - * @param string $key - * - * @return bool - */ - public function hasItem(string $key): bool - { - return $this->cacheItemPool->hasItem($key); - } + try { + $item = $this->cacheItemPool->getItem($key); - /** - * @param string $key - * @param mixed $item - * @return bool - */ - public function setItem(string $key, ThrottlerItemInterface $item): bool - { - return $this->setThrottlerItem($key, $item); - } + if ($item->isHit()) { + return unserialize($item->get()); + } + } catch (PsrCacheException $e) { + throw new CacheAdapterException($e->getMessage(), $e->getCode(), $e->getPrevious()); + } - /** - * @param string $key - */ - public function removeItem(string $key) - { - $this->cacheItemPool->deleteItem($key); + throw new ItemNotFoundException('Item not found.'); } /** - * @param string $key - * - * @return ThrottlerItemInterface - * @throws CacheAdapterException - * @throws ItemNotFoundException + * @inheritdoc */ - private function getThrottlerItem(string $key): ThrottlerItemInterface + public function hasItem(string $key): bool { try { - $item = $this->cacheItemPool->getItem($key); - - if ($item->isHit()) { - $params = json_decode($item->get(), true); - $class = $params['class']; - - return $class::createFromArray($params['data']); - } + return $this->cacheItemPool->hasItem($key); } catch (PsrCacheException $e) { + throw new CacheAdapterException($e->getMessage(), $e->getCode(), $e->getPrevious()); } - - throw new ItemNotFoundException('Item not found.'); } /** - * @param string $key - * @param ThrottlerItemInterface $item - * - * @return bool - * @throws CacheAdapterException + * @inheritdoc */ - private function setThrottlerItem(string $key, ThrottlerItemInterface $item) + public function setItem(string $key, ThrottlerItemInterface $item): bool { try { $cacheItem = $this->cacheItemPool->getItem($key); @@ -130,17 +92,21 @@ private function setThrottlerItem(string $key, ThrottlerItemInterface $item) throw new CacheAdapterException($e->getMessage(), $e->getCode(), $e->getPrevious()); } - $cacheItem->set( - json_encode( - [ - 'class' => get_class($item), - 'data' => $item, - ] - ) - ); - + $cacheItem->set(serialize($item)); $cacheItem->expiresAfter($item->getTtl()); return $this->cacheItemPool->save($cacheItem); } + + /** + * @inheritdoc + */ + public function removeItem(string $key) + { + try { + $this->cacheItemPool->deleteItem($key); + } catch (PsrCacheException $e) { + throw new CacheAdapterException($e->getMessage(), $e->getCode(), $e->getPrevious()); + } + } } \ No newline at end of file diff --git a/src/Cache/ThrottlerCacheInterface.php b/src/Cache/ThrottlerCacheInterface.php index e6a3308..a499b3c 100644 --- a/src/Cache/ThrottlerCacheInterface.php +++ b/src/Cache/ThrottlerCacheInterface.php @@ -25,12 +25,17 @@ namespace Sunspikes\Ratelimit\Cache; +use Sunspikes\Ratelimit\Cache\Exception\CacheAdapterException; +use Sunspikes\Ratelimit\Cache\Exception\ItemNotFoundException; + interface ThrottlerCacheInterface { /** * @param string $key * * @return ThrottlerItemInterface + * @throws CacheAdapterException + * @throws ItemNotFoundException */ public function getItem(string $key): ThrottlerItemInterface; @@ -38,6 +43,7 @@ public function getItem(string $key): ThrottlerItemInterface; * @param string $key * @param ThrottlerItemInterface $item * @return bool + * @throws CacheAdapterException */ public function setItem(string $key, ThrottlerItemInterface $item): bool; @@ -45,11 +51,13 @@ public function setItem(string $key, ThrottlerItemInterface $item): bool; * @param string $key * * @return bool + * @throws CacheAdapterException */ public function hasItem(string $key): bool; /** * @param string $key + * @throws CacheAdapterException */ public function removeItem(string $key); } \ No newline at end of file diff --git a/src/Cache/ThrottlerItemInterface.php b/src/Cache/ThrottlerItemInterface.php index aa46f36..e1d6e30 100644 --- a/src/Cache/ThrottlerItemInterface.php +++ b/src/Cache/ThrottlerItemInterface.php @@ -2,15 +2,8 @@ namespace Sunspikes\Ratelimit\Cache; -interface ThrottlerItemInterface extends \JsonSerializable +interface ThrottlerItemInterface extends \Serializable { - /** - * @param array $array - * - * @return ThrottlerItemInterface - */ - public static function createFromArray(array $array): ThrottlerItemInterface; - /** * @return int|null */ diff --git a/src/Throttle/Entity/CacheCount.php b/src/Throttle/Entity/CacheCount.php index 3dcd914..1be47e5 100644 --- a/src/Throttle/Entity/CacheCount.php +++ b/src/Throttle/Entity/CacheCount.php @@ -2,14 +2,15 @@ namespace Sunspikes\Ratelimit\Throttle\Entity; +use Sunspikes\Ratelimit\Cache\AbstractCacheItem; use Sunspikes\Ratelimit\Cache\ThrottlerItemInterface; -class CacheCount implements ThrottlerItemInterface +class CacheCount extends AbstractCacheItem implements ThrottlerItemInterface { /** @var int $count */ private $count; - /** @var int $ttl */ + /** @var int|null $ttl */ private $ttl; /** @@ -23,42 +24,38 @@ public function __construct(int $count, int $ttl = null) } /** - * @param array $array - * - * @return ThrottlerItemInterface + * @return int */ - public static function createFromArray(array $array): ThrottlerItemInterface + public function getCount(): int { - return new static( - $array['count'], - $array['ttl'] - ); + return $this->count; } /** - * @return array + * @inheritdoc */ - public function jsonSerialize() + public function getTtl() { - return [ - 'count' => $this->count, - 'ttl' => $this->ttl, - ]; + return $this->ttl; } /** - * @return int + * @inheritdoc */ - public function getCount(): int + protected function fromArray(array $array) { - return $this->count; + $this->count = $array['count']; + $this->ttl = $array['ttl']; } /** - * @return int|null + * @inheritdoc */ - public function getTtl() + protected function toArray(): array { - return $this->ttl; + return [ + 'count' => $this->count, + 'ttl' => $this->ttl, + ]; } } \ No newline at end of file diff --git a/src/Throttle/Entity/CacheHitMapping.php b/src/Throttle/Entity/CacheHitMapping.php index cba47a2..0b2e6c6 100644 --- a/src/Throttle/Entity/CacheHitMapping.php +++ b/src/Throttle/Entity/CacheHitMapping.php @@ -3,13 +3,14 @@ namespace Sunspikes\Ratelimit\Throttle\Entity; use Sunspikes\Ratelimit\Cache\ThrottlerItemInterface; +use Sunspikes\Ratelimit\Cache\AbstractCacheItem; -class CacheHitMapping implements ThrottlerItemInterface +class CacheHitMapping extends AbstractCacheItem implements ThrottlerItemInterface { /** @var array $hitMapping */ private $hitMapping; - /** @var int $ttl */ + /** @var int|null $ttl */ private $ttl; /** @@ -23,42 +24,38 @@ public function __construct(array $hitMapping, int $ttl = null) } /** - * @param array $array - * - * @return ThrottlerItemInterface + * @return array */ - public static function createFromArray(array $array): ThrottlerItemInterface + public function getHitMapping(): array { - return new static( - $array['hitMapping'], - $array['ttl'] - ); + return $this->hitMapping; } /** - * @return array + * @inheritdoc */ - public function jsonSerialize() + public function getTtl() { - return [ - 'hitMapping' => $this->hitMapping, - 'ttl' => $this->ttl, - ]; + return $this->ttl; } /** - * @return array + * @inheritdoc */ - public function getHitMapping(): array + protected function fromArray(array $array) { - return $this->hitMapping; + $this->hitMapping = $array['hitMapping']; + $this->ttl = $array['ttl']; } /** - * @return int|null + * @inheritdoc */ - public function getTtl() + protected function toArray(): array { - return $this->ttl; + return [ + 'hitMapping' => $this->hitMapping, + 'ttl' => $this->ttl, + ]; } } \ No newline at end of file diff --git a/src/Throttle/Entity/CacheTime.php b/src/Throttle/Entity/CacheTime.php index 50f0a56..87c748e 100644 --- a/src/Throttle/Entity/CacheTime.php +++ b/src/Throttle/Entity/CacheTime.php @@ -2,14 +2,15 @@ namespace Sunspikes\Ratelimit\Throttle\Entity; +use Sunspikes\Ratelimit\Cache\AbstractCacheItem; use Sunspikes\Ratelimit\Cache\ThrottlerItemInterface; -class CacheTime implements ThrottlerItemInterface +class CacheTime extends AbstractCacheItem implements ThrottlerItemInterface { /** @var float $limit */ private $time; - /** @var int $ttl */ + /** @var int|null $ttl */ private $ttl; /** @@ -23,42 +24,38 @@ public function __construct(float $time, int $ttl = null) } /** - * @param array $array - * - * @return ThrottlerItemInterface + * @return float */ - public static function createFromArray(array $array): ThrottlerItemInterface + public function getTime(): float { - return new static( - $array['time'], - $array['ttl'] - ); + return $this->time; } /** - * @return array + * @inheritdoc */ - public function jsonSerialize() + public function getTtl() { - return [ - 'time' => $this->time, - 'ttl' => $this->ttl, - ]; + return $this->ttl; } /** - * @return float + * @inheritdoc */ - public function getTime(): float + protected function fromArray(array $array) { - return $this->time; + $this->time = $array['time']; + $this->ttl = $array['ttl']; } /** - * @return float|null + * @inheritdoc */ - public function getTtl() + protected function toArray(): array { - return $this->ttl; + return [ + 'time' => $this->time, + 'ttl' => $this->ttl, + ]; } } \ No newline at end of file diff --git a/src/Throttle/Throttler/ElasticWindowThrottler.php b/src/Throttle/Throttler/ElasticWindowThrottler.php index 38a5949..58e0b78 100644 --- a/src/Throttle/Throttler/ElasticWindowThrottler.php +++ b/src/Throttle/Throttler/ElasticWindowThrottler.php @@ -74,9 +74,7 @@ public function access() public function hit() { $this->counter = $this->count() + 1; - $item = new CacheCount($this->counter, $this->ttl); - - $this->cache->setItem($this->key, $item); + $this->cache->setItem($this->key, new CacheCount($this->counter, $this->ttl)); return $this; } @@ -87,9 +85,7 @@ public function hit() public function clear() { $this->counter = 0; - $item = new CacheCount($this->counter, $this->ttl); - - $this->cache->setItem($this->key, $item); + $this->cache->setItem($this->key, new CacheCount($this->counter, $this->ttl)); return $this; } diff --git a/src/Throttle/Throttler/FixedWindowThrottler.php b/src/Throttle/Throttler/FixedWindowThrottler.php index 6e31913..6ffba70 100644 --- a/src/Throttle/Throttler/FixedWindowThrottler.php +++ b/src/Throttle/Throttler/FixedWindowThrottler.php @@ -84,8 +84,7 @@ public function count() public function clear() { $this->setCachedHitCount(0); - $item = new CacheTime($this->timeProvider->now(), $this->cacheTtl); - $this->cache->setItem($this->getTimeCacheKey(), $item); + $this->cache->setItem($this->getTimeCacheKey(), new CacheTime($this->timeProvider->now(), $this->cacheTtl)); } /** @@ -127,8 +126,7 @@ private function getCachedHitCount() private function setCachedHitCount($hitCount) { $this->hitCount = $hitCount; - $item = new CacheCount($hitCount, $this->cacheTtl); - $this->cache->setItem($this->getHitsCacheKey(), $item); + $this->cache->setItem($this->getHitsCacheKey(), new CacheCount($hitCount, $this->cacheTtl)); } /** diff --git a/src/Throttle/Throttler/LeakyBucketThrottler.php b/src/Throttle/Throttler/LeakyBucketThrottler.php index b827706..a09139d 100644 --- a/src/Throttle/Throttler/LeakyBucketThrottler.php +++ b/src/Throttle/Throttler/LeakyBucketThrottler.php @@ -211,11 +211,8 @@ private function getWaitTime($tokenCount) */ private function setUsedCapacity($tokens) { - $countItem = new CacheCount($tokens, $this->cacheTtl); - $this->cache->setItem($this->getTokenCacheKey(), $countItem); - - $timeItem = new CacheTime($this->timeProvider->now(), $this->cacheTtl); - $this->cache->setItem($this->getTimeCacheKey(), $timeItem); + $this->cache->setItem($this->getTokenCacheKey(), new CacheCount($tokens, $this->cacheTtl)); + $this->cache->setItem($this->getTimeCacheKey(), new CacheTime($this->timeProvider->now(), $this->cacheTtl)); } /** diff --git a/src/Throttle/Throttler/MovingWindowThrottler.php b/src/Throttle/Throttler/MovingWindowThrottler.php index ce57236..84efa03 100644 --- a/src/Throttle/Throttler/MovingWindowThrottler.php +++ b/src/Throttle/Throttler/MovingWindowThrottler.php @@ -51,9 +51,7 @@ public function hit() //Adds 1 recorded hit to the mapping entry for the current timestamp $this->hitCountMapping[$timestamp]++; - - $item = new CacheHitMapping($this->hitCountMapping, $this->cacheTtl); - $this->cache->setItem($this->key, $item); + $this->cache->setItem($this->key, new CacheHitMapping($this->hitCountMapping, $this->cacheTtl)); return $this; } @@ -97,9 +95,7 @@ public function getRetryTimeout() public function clear() { $this->hitCountMapping = []; - - $item = new CacheHitMapping($this->hitCountMapping, $this->cacheTtl); - $this->cache->setItem($this->key, $item); + $this->cache->setItem($this->key, new CacheHitMapping($this->hitCountMapping, $this->cacheTtl)); } private function updateHitCount() diff --git a/tests/Cache/ThrottlerCacheTest.php b/tests/Cache/ThrottlerCacheTest.php index b438b91..35c45dc 100644 --- a/tests/Cache/ThrottlerCacheTest.php +++ b/tests/Cache/ThrottlerCacheTest.php @@ -17,7 +17,7 @@ public function testGetItemFound() $countItem = new CacheCount(1); $cacheItem = new CacheItem($key); - $cacheItem->set(json_encode(['class' => CacheCount::class, 'data' => $countItem])); + $cacheItem->set(serialize($countItem)); $cacheItemPool = M::mock(CacheItemPoolInterface::class); $cacheItemPool->shouldReceive('getItem') @@ -36,10 +36,13 @@ public function testGetItemFound() public function testGetItemNotFound() { $key = 'key'; + + $cacheItem = new CacheItem('none'); + $cacheItemPool = M::mock(CacheItemPoolInterface::class); $cacheItemPool->shouldReceive('getItem') ->with($key) - ->andThrow(CachePoolException::class); + ->andReturn($cacheItem); $cache = new ThrottlerCache($cacheItemPool); $cache->getItem($key); diff --git a/tests/Functional/AbstractThrottlerTestCase.php b/tests/Functional/AbstractThrottlerTestCase.php index 5c87f38..3628aed 100644 --- a/tests/Functional/AbstractThrottlerTestCase.php +++ b/tests/Functional/AbstractThrottlerTestCase.php @@ -44,7 +44,6 @@ public function testThrottlePostLimit() $throttle->hit(); } - $this->assertFalse($throttle->check()); }