diff --git a/src/Ganesha/Storage/Adapter/Redis.php b/src/Ganesha/Storage/Adapter/Redis.php index da72b9a..37412e6 100644 --- a/src/Ganesha/Storage/Adapter/Redis.php +++ b/src/Ganesha/Storage/Adapter/Redis.php @@ -72,11 +72,7 @@ public function setConfiguration(Configuration $configuration): void */ public function load(string $service): int { - $expires = microtime(true) - $this->configuration->timeWindow(); - - if ($this->redis->zRemRangeByScore($service, '-inf', $expires) === false) { - throw new StorageException('Failed to remove expired elements. service: ' . $service); - } + $this->removeExpiredElements($service); $r = $this->redis->zCard($service); @@ -105,6 +101,9 @@ public function save(string $service, int $count): void public function increment(string $service): void { $t = microtime(true); + + $this->removeExpiredElements($service); + $this->redis->zAdd($service, $t, $t); } @@ -178,4 +177,18 @@ public function reset(): void { // TODO: Implement reset() method. } + + /** + * @param string $service + * + * @throws StorageException + */ + private function removeExpiredElements(string $service): void + { + $expires = microtime(true) - $this->configuration->timeWindow(); + + if ($this->redis->zRemRangeByScore($service, '-inf', $expires) === false) { + throw new StorageException('Failed to remove expired elements. service: ' . $service); + } + } } diff --git a/tests/Ackintosh/Ganesha/Storage/Adapter/AbstractRedisTest.php b/tests/Ackintosh/Ganesha/Storage/Adapter/AbstractRedisTest.php index b77faf2..e718fc4 100644 --- a/tests/Ackintosh/Ganesha/Storage/Adapter/AbstractRedisTest.php +++ b/tests/Ackintosh/Ganesha/Storage/Adapter/AbstractRedisTest.php @@ -92,6 +92,20 @@ public function incrementAndLoad() $this->assertSame(2, $result); } + /** + * @test + * @expectedException \Ackintosh\Ganesha\Exception\StorageException + * @expectedExceptionMessageRegExp /\AFailed to remove expired elements/ + */ + public function incrementThrowsExceptionWhenFailedToRunzRemRangeByScore() + { + $mock = $this->getMockBuilder(\Redis::class)->getMock(); + $mock->method('zRemRangeByScore') + ->willReturn(false); + + $this->createAdapterWithMock($mock)->increment($this->service); + } + /** * @test * @expectedException \Ackintosh\Ganesha\Exception\StorageException @@ -156,7 +170,7 @@ public function loadThrowsExceptionWhenFailedToRunzCard() public function loadThrowsException() { $mock = $this->getMockBuilder(\Redis::class)->getMock(); - $mock->method('zRemRangeByScore') + $mock->method('zCard') ->willThrowException(new \RedisException('exception test')); $this->createAdapterWithMock($mock)->load($this->service); diff --git a/tests/Ackintosh/Ganesha/StorageTest.php b/tests/Ackintosh/Ganesha/StorageTest.php index a652733..ba7207d 100644 --- a/tests/Ackintosh/Ganesha/StorageTest.php +++ b/tests/Ackintosh/Ganesha/StorageTest.php @@ -44,7 +44,15 @@ public function getLastFailureTimeWithSlidingTimeWindow() getenv('GANESHA_EXAMPLE_REDIS') ? getenv('GANESHA_EXAMPLE_REDIS') : 'localhost' ); $r->flushAll(); - $storage = new Storage(new Redis(($r)), new Ganesha\Storage\StorageKeys(), null); + + $redisAdapter = new Redis($r); + $context = new Ganesha\Context( + Ganesha\Strategy\Rate::class, + $redisAdapter, + new Configuration(['timeWindow' => 3]) + ); + $redisAdapter->setContext($context); + $storage = new Storage($redisAdapter, new Ganesha\Storage\StorageKeys(), null); $service = 'test'; $storage->incrementFailureCount($service);