Skip to content

Commit

Permalink
Merge pull request #4 from MyOnlineStore/MWW-4056
Browse files Browse the repository at this point in the history
Fixes inconsistencies in (milli)seconds in LeakyBucketThrottler.
  • Loading branch information
spdotdev authored Nov 8, 2016
2 parents 5acc059 + 2788819 commit faaf14e
Show file tree
Hide file tree
Showing 7 changed files with 17 additions and 16 deletions.
3 changes: 1 addition & 2 deletions src/Throttle/Settings/LeakyBucketSettings.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,7 @@ public function isValid()
return
null !== $this->tokenLimit &&
null !== $this->timeLimit &&
0 !== $this->timeLimit &&
$this->tokenLimit !== $this->threshold;
0 !== $this->timeLimit;
}

/**
Expand Down
10 changes: 5 additions & 5 deletions src/Throttle/Throttler/LeakyBucketThrottler.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,8 @@ public function hit()
{
$tokenCount = $this->count();

if (0 !== $wait = $this->getWaitTime($tokenCount)) {
$this->timeProvider->usleep($wait * 1e3);
if (0 < $wait = $this->getWaitTime($tokenCount)) {
$this->timeProvider->usleep($wait);
}

$this->setUsedCapacity($tokenCount + 1);
Expand All @@ -134,7 +134,7 @@ public function clear()
public function count()
{
try {
$timeSinceLastRequest = $this->timeProvider->now() - $this->cache->get($this->key.self::TIME_CACHE_KEY);
$timeSinceLastRequest = 1e3 * ($this->timeProvider->now() - $this->cache->get($this->key.self::TIME_CACHE_KEY));

if ($timeSinceLastRequest > $this->timeLimit) {
return 0;
Expand All @@ -147,7 +147,7 @@ public function count()
return 0;
}

return (int) ceil($lastTokenCount - ($this->tokenlimit * $timeSinceLastRequest / ($this->timeLimit)));
return (int) max(0, ceil($lastTokenCount - ($this->tokenlimit * $timeSinceLastRequest / ($this->timeLimit))));
}

/**
Expand Down Expand Up @@ -185,7 +185,7 @@ private function getWaitTime($tokenCount)
return 0;
}

return ceil($this->timeLimit / ($this->tokenlimit - $this->threshold));
return ceil($this->timeLimit / max(1, ($this->tokenlimit - $this->threshold)));
}

/**
Expand Down
6 changes: 4 additions & 2 deletions src/Time/PhpTimeAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,13 @@
final class PhpTimeAdapter implements TimeAdapterInterface
{
/**
* @return int
* @return float
*/
public function now()
{
return time();
list($usec, $sec) = explode(" ", microtime());

return ((float) $usec + (float) $sec);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/Time/TimeAdapterInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
interface TimeAdapterInterface
{
/**
* @return int
* @return float
*/
public function now();

Expand Down
2 changes: 1 addition & 1 deletion tests/Functional/LeakyBucketTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public function testThrottlePostLimit()
public function testThrottleAccess()
{
$expectedWaitTime = self::TIME_LIMIT / (self::TOKEN_LIMIT - self::THRESHOLD);
$this->timeAdapter->shouldReceive('usleep')->with(1e3 * $expectedWaitTime)->once();
$this->timeAdapter->shouldReceive('usleep')->with($expectedWaitTime)->once();

$throttle = $this->ratelimiter->get('access-test');
$throttle->access();
Expand Down
2 changes: 1 addition & 1 deletion tests/Throttle/Settings/LeakyBucketSettingsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public function inputProvider()
[null, 600, null, false],
[3, null, null, false],
[3, 0, null, false],
[3, 600, 3, false],
[3, 600, 3, true],
[30, 600, 15, true],
];
}
Expand Down
8 changes: 4 additions & 4 deletions tests/Throttle/Throttler/LeakyBucketThrottlerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public function testAccess()
{
//More time has passed than the given window
$this->mockTimePassed(self::TIME_LIMIT + 1, 2);
$this->mockSetUsedCapacity(1, self::INITIAL_TIME + self::TIME_LIMIT + 1);
$this->mockSetUsedCapacity(1, (self::INITIAL_TIME + self::TIME_LIMIT + 1) / 1e3);

$this->assertEquals(true, $this->throttler->access());
}
Expand Down Expand Up @@ -90,7 +90,7 @@ public function testHitOnThreshold()
$this->mockSetUsedCapacity(self::THRESHOLD + 1, self::INITIAL_TIME);

$expectedWaitTime = self::TIME_LIMIT / (self::TOKEN_LIMIT - self::THRESHOLD);
$this->timeAdapter->shouldReceive('usleep')->with(1e3 * $expectedWaitTime)->once();
$this->timeAdapter->shouldReceive('usleep')->with($expectedWaitTime)->once();

$this->assertEquals($expectedWaitTime, $this->throttler->hit());
}
Expand Down Expand Up @@ -167,11 +167,11 @@ private function mockSetUsedCapacity($tokens, $time)
*/
private function mockTimePassed($timeDiff, $numCalls)
{
$this->timeAdapter->shouldReceive('now')->times($numCalls)->andReturn(self::INITIAL_TIME + $timeDiff);
$this->timeAdapter->shouldReceive('now')->times($numCalls)->andReturn((self::INITIAL_TIME + $timeDiff) / 1e3);

$this->cacheAdapter
->shouldReceive('get')
->with('key'.LeakyBucketThrottler::TIME_CACHE_KEY)
->andReturn(self::INITIAL_TIME);
->andReturn(self::INITIAL_TIME / 1e3);
}
}

0 comments on commit faaf14e

Please sign in to comment.