Funneled::releaseAfterMinutes()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
namespace Telkins\JobFunnelingMiddleware;
4
5
use Closure;
6
use Illuminate\Support\Facades\Redis;
7
8
class Funneled
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 $allowedNumberOfJobs = 1;
21
22
    /** @var int */
23
    protected $releaseInSeconds = 5;
24
25
    /** @var array */
26
    protected $releaseRandomSeconds = null;
27
28
    public function __construct()
29
    {
30
        $calledByClass = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1]['class'];
31
32
        $this->key($calledByClass);
33
    }
34
35
    /**
36
     * @param bool|\Closure $enabled
37
     *
38
     * @return $this
39
     */
40
    public function enabled($enabled = true)
41
    {
42
        $this->enabled = $enabled;
43
44
        return $this;
45
    }
46
47
    public function connectionName(string $connectionName)
48
    {
49
        $this->connectionName = $connectionName;
50
51
        return $this;
52
    }
53
54
    public function key(string $key)
55
    {
56
        $this->key = $key;
57
58
        return $this;
59
    }
60
61
    public function allow(int $allowedNumberOfJobs)
62
    {
63
        $this->allowedNumberOfJobs = $allowedNumberOfJobs;
64
65
        return $this;
66
    }
67
68
    public function releaseAfterOneSecond()
69
    {
70
        return $this->releaseAfterSeconds(1);
71
    }
72
73
    public function releaseAfterSeconds(int $releaseInSeconds)
74
    {
75
        $this->releaseInSeconds = $releaseInSeconds;
76
77
        return $this;
78
    }
79
80
    public function releaseAfterOneMinute()
81
    {
82
        return $this->releaseAfterMinutes(1);
83
    }
84
85
    public function releaseAfterMinutes(int $releaseInMinutes)
86
    {
87
        return $this->releaseAfterSeconds($releaseInMinutes * 60);
88
    }
89
90
    public function releaseAfterRandomSeconds(int $min = 1, int $max = 10)
91
    {
92
        $this->releaseRandomSeconds = [$min, $max];
93
94
        return $this;
95
    }
96
97
    protected function releaseDuration() :int
98
    {
99
        if (! is_null($this->releaseRandomSeconds)) {
100
            return random_int(...$this->releaseRandomSeconds);
101
        }
102
103
        return $this->releaseInSeconds;
104
    }
105
106
    public function handle($job, $next)
107
    {
108
        if ($this->enabled instanceof Closure) {
109
            $this->enabled = (bool) $this->enabled();
110
        }
111
112
        if (! $this->enabled) {
113
            return $next($job);
114
        }
115
116
        Redis::connection($this->connectionName)
117
            ->funnel($this->key)
118
            ->limit($this->allowedNumberOfJobs)
119
            ->then(function () use ($job, $next) {
120
                $next($job);
121
            }, function () use ($job) {
122
                $job->release($this->releaseDuration());
123
            });
124
    }
125
}
126