Skip to content

Commit 10e689f

Browse files
authored
Merge pull request #2074 from MohKari/mohkari/throttler
Throttler can access bucket for bucket life time
2 parents 5193780 + 8cceaee commit 10e689f

3 files changed

Lines changed: 21 additions & 21 deletions

File tree

system/Throttle/Throttler.php

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -138,12 +138,12 @@ public function check(string $key, int $capacity, int $seconds, int $cost = 1):
138138
$tokenName = $this->prefix . $key;
139139

140140
// Check to see if the bucket has even been created yet.
141-
if (($tokens = $this->cache->get($tokenName)) === false)
141+
if (($tokens = $this->cache->get($tokenName)) === null)
142142
{
143143
// If it hasn't been created, then we'll set it to the maximum
144144
// capacity - 1, and save it to the cache.
145145
$this->cache->save($tokenName, $capacity - $cost, $seconds);
146-
$this->cache->save($tokenName . 'Time', time());
146+
$this->cache->save($tokenName . 'Time', time(), $seconds);
147147

148148
return true;
149149
}
@@ -152,32 +152,33 @@ public function check(string $key, int $capacity, int $seconds, int $cost = 1):
152152
// based on how long it's been since the last update.
153153
$throttleTime = $this->cache->get($tokenName . 'Time');
154154
$elapsed = $this->time() - $throttleTime;
155+
155156
// Number of tokens to add back per second
156157
$rate = $capacity / $seconds;
157158

158-
// We must have a minimum wait of 1 second for a new token
159+
// How many seconds till a new token is available.
160+
// We must have a minimum wait of 1 second for a new token.
159161
// Primarily stored to allow devs to report back to users.
160-
$this->tokenTime = max(1, $rate);
162+
$newTokenAvailable = (1 / $rate) - $elapsed;
163+
$this->tokenTime = max(1, $newTokenAvailable);
161164

162165
// Add tokens based up on number per second that
163166
// should be refilled, then checked against capacity
164167
// to be sure the bucket didn't overflow.
165168
$tokens += $rate * $elapsed;
166169
$tokens = $tokens > $capacity ? $capacity : $tokens;
167170

168-
// If $tokens > 0, then we are save to perform the action, but
171+
// If $tokens > 0, then we are safe to perform the action, but
169172
// we need to decrement the number of available tokens.
170-
$response = false;
171-
172173
if ($tokens > 0)
173174
{
174-
$response = true;
175+
$this->cache->save($tokenName, $tokens - $cost, $seconds);
176+
$this->cache->save($tokenName . 'Time', time(), $seconds);
175177

176-
$this->cache->save($tokenName, $tokens - $cost, $elapsed);
177-
$this->cache->save($tokenName . 'Time', time());
178+
return true;
178179
}
179180

180-
return $response;
181+
return false;
181182
}
182183

183184
//--------------------------------------------------------------------

tests/_support/Cache/Handlers/MockHandler.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public function get(string $key)
4343

4444
return array_key_exists($key, $this->cache)
4545
? $this->cache[$key]
46-
: false;
46+
: null;
4747
}
4848

4949
//--------------------------------------------------------------------

tests/system/Throttle/ThrottleTest.php

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,19 @@ public function testTokenTime()
1616
{
1717
$throttler = new Throttler($this->cache);
1818

19-
// token time should be zero to start
19+
// tokenTime should be 0 to start
2020
$this->assertEquals(0, $throttler->getTokenTime());
2121

22-
// as soon as we try a rate check, token time affected
23-
$rate = 1; // allow 1 per minute
24-
$cost = 1;
22+
// set $rate
23+
$rate = 1; // allow 1 request per minute
2524

26-
// after using one slot, still good
27-
$throttler->check('127.0.0.1', $rate, MINUTE, $cost);
25+
// first check just creates a bucket, so tokenTime should be 0
26+
$throttler->check('127.0.0.1', $rate, MINUTE);
2827
$this->assertEquals(0, $throttler->getTokenTime());
2928

30-
// after consuming a second, we have to wait
31-
$throttler->check('127.0.0.1', $rate, MINUTE, $cost);
32-
$this->assertEquals(1, $throttler->getTokenTime());
29+
// additional check affects tokenTime, so tokenTime should be 1 or greater
30+
$throttler->check('127.0.0.1', $rate, MINUTE);
31+
$this->assertGreaterThanOrEqual(1, $throttler->getTokenTime());
3332
}
3433

3534
public function testIPSavesBucket()

0 commit comments

Comments
 (0)