Completed
Push — master ( 468575...d44c22 )
by Freek
21s queued 11s
created

RateLimited::releaseAfter()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
namespace Spatie\RateLimitedMiddleware;
4
5
use Closure;
6
use Illuminate\Support\Facades\Redis;
7
8
class RateLimited
9
{
10
    /** @var bool|\Closure */
11
    protected $enabled = true;
12
13
    /** @var string */
14
    protected $connectionName = '';
15
16
    /** @var string */
17
    protected $key;
18
19
    /** @var int */
20
    protected $timeSpanInSeconds = 1;
21
22
    /** @var int */
23
    protected $allowedNumberOfJobsInTimeSpan = 5;
24
25
    /** @var int */
26
    protected $releaseInSeconds = 5;
27
28
    /** @var callable */
29
    protected $releaseAfterCallback = null;
30
31
    public function __construct()
32
    {
33
        $calledByClass = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1]['class'];
34
35
        $this->key($calledByClass);
36
    }
37
38
    /**
39
     * @param bool|\Closure $enabled
40
     *
41
     * @return $this
42
     */
43
    public function enabled($enabled = true)
44
    {
45
        $this->enabled = $enabled;
46
47
        return $this;
48
    }
49
50
    public function connectionName(string $connectionName)
51
    {
52
        $this->connectionName = $connectionName;
53
54
        return $this;
55
    }
56
57
    public function key(string $key)
58
    {
59
        $this->key = $key;
60
61
        return $this;
62
    }
63
64
    public function timespanInSeconds(int $timespanInSeconds)
65
    {
66
        $this->timeSpanInSeconds = $timespanInSeconds;
67
68
        return $this;
69
    }
70
71
    public function allow(int $allowedNumberOfJobsInTimeSpan)
72
    {
73
        $this->allowedNumberOfJobsInTimeSpan = $allowedNumberOfJobsInTimeSpan;
74
75
        return $this;
76
    }
77
78
    public function everySecond(int $timespanInSeconds = 1)
79
    {
80
        $this->timeSpanInSeconds = $timespanInSeconds;
81
82
        return $this;
83
    }
84
85
    public function everySeconds(int $timespanInSeconds)
86
    {
87
        return $this->everySecond($timespanInSeconds);
88
    }
89
90
    public function everyMinute(int $timespanInMinutes = 1)
91
    {
92
        return $this->everySecond($timespanInMinutes * 60);
93
    }
94
95
    public function everyMinutes(int $timespanInMinutes)
96
    {
97
        return $this->everySecond($timespanInMinutes * 60);
98
    }
99
100
    public function releaseAfterOneSecond()
101
    {
102
        return $this->releaseAfterSeconds(1);
103
    }
104
105
    public function releaseAfterSeconds(int $releaseInSeconds)
106
    {
107
        $this->releaseInSeconds = $releaseInSeconds;
108
109
        return $this;
110
    }
111
112
    public function releaseAfterOneMinute()
113
    {
114
        return $this->releaseAfterMinutes(1);
115
    }
116
117
    public function releaseAfterMinutes(int $releaseInSeconds)
118
    {
119
        return $this->releaseAfterSeconds($releaseInSeconds * 60);
120
    }
121
122
    public function releaseAfter(callable $releaseAfter)
123
    {
124
        $this->releaseAfterCallback = $releaseAfter;
125
126
        return $this;
127
    }
128
129
    protected function releaseDuration($job) :int
130
    {
131
        if (! is_null($this->releaseAfterCallback)) {
132
            return call_user_func($this->releaseAfterCallback, [$job]);
133
        }
134
135
        return $this->releaseInSeconds;
136
    }
137
138
    public function handle($job, $next)
139
    {
140
        if ($this->enabled instanceof Closure) {
141
            $this->enabled = (bool) $this->enabled();
142
        }
143
144
        if (! $this->enabled) {
145
            return $next($job);
146
        }
147
148
        Redis::connection($this->connectionName)
149
            ->throttle($this->key)
150
            ->block(0)
151
            ->allow($this->allowedNumberOfJobsInTimeSpan)
152
            ->every($this->timeSpanInSeconds)
153
            ->then(function () use ($job, $next) {
154
                $next($job);
155
            }, function () use ($job) {
156
                $job->release($this->releaseDuration($job));
157
            });
158
    }
159
}
160