Skip to content

Commit

Permalink
Add RuntimeConfigurableRateLimiter (#57)
Browse files Browse the repository at this point in the history
  • Loading branch information
nikolaposa authored May 17, 2024
1 parent fa5d32f commit 84bc08a
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 0 deletions.
41 changes: 41 additions & 0 deletions src/RuntimeConfigurableRateLimiter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

declare(strict_types=1);

namespace RateLimit;

use LogicException;

final class RuntimeConfigurableRateLimiter extends ConfigurableRateLimiter implements RateLimiter, SilentRateLimiter
{
public function __construct(private RateLimiter|SilentRateLimiter $rateLimiter)
{
parent::__construct(Rate::perSecond(1));
}

public function limit(string $identifier, Rate $rate = null): void
{
if (!$this->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);
}
}
35 changes: 35 additions & 0 deletions tests/RuntimeConfigurableRateLimiterTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

declare(strict_types=1);

namespace RateLimit\Tests;

use PHPUnit\Framework\TestCase;
use RateLimit\Exception\LimitExceeded;
use RateLimit\InMemoryRateLimiter;
use RateLimit\Rate;
use RateLimit\RuntimeConfigurableRateLimiter;

class RuntimeConfigurableRateLimiterTest extends TestCase
{
/**
* @test
*/
public function it_allows_rate_to_be_configured_at_runtime(): void
{
$rate = Rate::perHour(1);
$rateLimiter = new RuntimeConfigurableRateLimiter(new InMemoryRateLimiter(Rate::perMinute(100)));
$identifier = 'test';

$rateLimiter->limitSilently($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());
}
}
}

0 comments on commit 84bc08a

Please sign in to comment.