From b7721d932e392969e57d4133a130bfa87691f67d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikola=20Po=C5=A1a?= Date: Fri, 17 May 2024 16:28:10 +0200 Subject: [PATCH 1/2] Add RuntimeConfigurableRateLimiter --- src/RuntimeConfigurableRateLimiter.php | 40 ++++++++++++++++++++ tests/RuntimeConfigurableRateLimiterTest.php | 40 ++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 src/RuntimeConfigurableRateLimiter.php create mode 100644 tests/RuntimeConfigurableRateLimiterTest.php diff --git a/src/RuntimeConfigurableRateLimiter.php b/src/RuntimeConfigurableRateLimiter.php new file mode 100644 index 0000000..28d8a33 --- /dev/null +++ b/src/RuntimeConfigurableRateLimiter.php @@ -0,0 +1,40 @@ +rateLimiter instanceof RateLimiter) { + throw new LogicException('Decorated Rate Limiter must implement RateLimiter interface'); + } + + if ($this->rateLimiter instanceof ConfigurableRateLimiter) { + $this->rateLimiter->rate = $rate; + } + + $this->rateLimiter->limit($identifier); + } + + public function limitSilently(string $identifier, Rate $rate = null): Status + { + if (!$this->rateLimiter instanceof SilentRateLimiter) { + throw new LogicException('Decorated Rate Limiter must implement SilentRateLimiter interface'); + } + + if ($this->rateLimiter instanceof ConfigurableRateLimiter) { + $this->rateLimiter->rate = $rate; + } + + return $this->rateLimiter->limitSilently($identifier); + } +} diff --git a/tests/RuntimeConfigurableRateLimiterTest.php b/tests/RuntimeConfigurableRateLimiterTest.php new file mode 100644 index 0000000..e41657e --- /dev/null +++ b/tests/RuntimeConfigurableRateLimiterTest.php @@ -0,0 +1,40 @@ +getRateLimiter(Rate::perMinute(100)); + $identifier = 'test'; + + $rateLimiter->limit($identifier, $rate); + + try { + $rateLimiter->limit($identifier, $rate); + + $this->fail('Limit should have been reached'); + } catch (LimitExceeded $exception) { + $this->assertSame($identifier, $exception->getIdentifier()); + $this->assertSame($rate, $exception->getRate()); + } + } + + protected function getRateLimiter(Rate $rate): RateLimiter + { + return new RuntimeConfigurableRateLimiter(new InMemoryRateLimiter($rate)); + } +} From 7290c507ed5e5039a848f716528d050296597b0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikola=20Po=C5=A1a?= Date: Fri, 17 May 2024 16:36:10 +0200 Subject: [PATCH 2/2] Fix tests --- src/RuntimeConfigurableRateLimiter.php | 1 + tests/RuntimeConfigurableRateLimiterTest.php | 13 ++++--------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/RuntimeConfigurableRateLimiter.php b/src/RuntimeConfigurableRateLimiter.php index 28d8a33..e023bbe 100644 --- a/src/RuntimeConfigurableRateLimiter.php +++ b/src/RuntimeConfigurableRateLimiter.php @@ -10,6 +10,7 @@ final class RuntimeConfigurableRateLimiter extends ConfigurableRateLimiter imple { public function __construct(private RateLimiter|SilentRateLimiter $rateLimiter) { + parent::__construct(Rate::perSecond(1)); } public function limit(string $identifier, Rate $rate = null): void diff --git a/tests/RuntimeConfigurableRateLimiterTest.php b/tests/RuntimeConfigurableRateLimiterTest.php index e41657e..eaafc6f 100644 --- a/tests/RuntimeConfigurableRateLimiterTest.php +++ b/tests/RuntimeConfigurableRateLimiterTest.php @@ -4,13 +4,13 @@ namespace RateLimit\Tests; +use PHPUnit\Framework\TestCase; use RateLimit\Exception\LimitExceeded; use RateLimit\InMemoryRateLimiter; use RateLimit\Rate; -use RateLimit\RateLimiter; use RateLimit\RuntimeConfigurableRateLimiter; -class RuntimeConfigurableRateLimiterTest extends RateLimiterTest +class RuntimeConfigurableRateLimiterTest extends TestCase { /** * @test @@ -18,10 +18,10 @@ class RuntimeConfigurableRateLimiterTest extends RateLimiterTest public function it_allows_rate_to_be_configured_at_runtime(): void { $rate = Rate::perHour(1); - $rateLimiter = $this->getRateLimiter(Rate::perMinute(100)); + $rateLimiter = new RuntimeConfigurableRateLimiter(new InMemoryRateLimiter(Rate::perMinute(100))); $identifier = 'test'; - $rateLimiter->limit($identifier, $rate); + $rateLimiter->limitSilently($identifier, $rate); try { $rateLimiter->limit($identifier, $rate); @@ -32,9 +32,4 @@ public function it_allows_rate_to_be_configured_at_runtime(): void $this->assertSame($rate, $exception->getRate()); } } - - protected function getRateLimiter(Rate $rate): RateLimiter - { - return new RuntimeConfigurableRateLimiter(new InMemoryRateLimiter($rate)); - } }