Completed
Pull Request — master (#24)
by Julián
04:37
created

MemcachedRateLimiter   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 53
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Test Coverage

Coverage 94.12%

Importance

Changes 0
Metric Value
wmc 9
lcom 1
cbo 1
dl 0
loc 53
ccs 16
cts 17
cp 0.9412
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 10 2
A getCurrent() 0 4 1
A updateCounter() 0 10 3
A getElapsedTime() 0 4 1
A intervalToMemcachedTime() 0 4 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace RateLimit;
6
7
use Memcached;
8
9
final class MemcachedRateLimiter extends AbstractElapsedTimeRateLimiter
10
{
11
    private const MEMCACHED_SECONDS_LIMIT = 2592000; // Number of seconds in 30 days
12
13
    /** @var Memcached */
14
    private $memcached;
15
16 5
    public function __construct(Memcached $memcached, string $keyPrefix = '')
17
    {
18 5
        if ($memcached->getOption(Memcached::OPT_BINARY_PROTOCOL) !== 1) {
19
            throw new \RuntimeException('Memcached "OPT_BINARY_PROTOCOL" option should be set to "true".');
20
        }
21
22 5
        parent::__construct($keyPrefix);
23
24 5
        $this->memcached = $memcached;
25 5
    }
26
27 5
    protected function getCurrent(string $valueKey): int
28
    {
29 5
        return (int) $this->memcached->get($valueKey);
30
    }
31
32 5
    protected function updateCounter(string $valueKey, string $timeKey, int $interval): int
33
    {
34 5
        $current = $this->memcached->increment($valueKey, 1, 1, $this->intervalToMemcachedTime($interval));
35
36 5
        if ($current === 1) {
37 5
            $this->memcached->add($timeKey, \time(), $this->intervalToMemcachedTime($interval));
38
        }
39
40 5
        return $current === false ? 1 : $current;
41
    }
42
43 3
    protected function getElapsedTime(string $timeKey): int
44
    {
45 3
        return \time() - (int) $this->memcached->get($timeKey);
46
    }
47
48
    /**
49
     * Interval to Memcached expiration time.
50
     *
51
     * @see https://www.php.net/manual/en/memcached.expiration.php
52
     *
53
     * @param int $interval
54
     *
55
     * @return int
56
     */
57 5
    private function intervalToMemcachedTime(int $interval): int
58
    {
59 5
        return $interval <= self::MEMCACHED_SECONDS_LIMIT ? $interval : \time() + $interval;
60
    }
61
}
62