Completed
Push — master ( 073c6d...49d4ca )
by Dmitry
06:07
created

Lock   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 69
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 15
lcom 1
cbo 0
dl 0
loc 69
ccs 0
cts 55
cp 0
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A acquire() 0 7 2
A exists() 0 4 1
A lock() 0 12 3
A releaseLocks() 0 6 2
A unlock() 0 16 4
A waitUnlock() 0 7 2
1
<?php
2
3
namespace Basis;
4
5
use Exception;
6
use Predis\Client;
7
8
class Lock
9
{
10
    private $redis;
11
    private $locks = [];
12
13
    public function __construct(Client $redis)
14
    {
15
        $this->redis = $redis;
16
        register_shutdown_function([$this, 'releaseLocks']);
17
    }
18
19
    public function acquire($name, $ttl = 1)
20
    {
21
        while (!$this->lock($name, $ttl)) {
22
            $this->waitUnlock($name);
23
        }
24
        return true;
25
    }
26
27
    public function exists($name)
28
    {
29
        return $this->redis->get("lock-$name") !== null;
30
    }
31
32
    public function lock($name, $ttl = 1)
33
    {
34
        if (in_array($name, $this->locks)) {
35
            throw new Exception("Lock $name was already registered");
36
        }
37
        $result = $this->redis->set("lock-$name", 1, 'EX', $ttl, 'NX');
38
        if ($result) {
39
            $this->locks[] = $name;
40
            return true;
41
        }
42
        return false;
43
    }
44
45
    public function releaseLocks()
46
    {
47
        foreach ($this->locks as $name) {
48
            $this->unlock($name);
49
        }
50
    }
51
52
    public function unlock($name)
53
    {
54
        if (!in_array($name, $this->locks)) {
55
            throw new Exception("Lock $name was already registered");
56
        }
57
        
58
        foreach ($this->locks as $i => $candidate) {
59
            if ($candidate == $name) {
60
                unset($this->locks[$i]);
61
                $this->redis->del("lock-$name");
62
                break;
63
            }
64
        }
65
66
        $this->locks = array_values($this->locks);
67
    }
68
69
    public function waitUnlock($name)
70
    {
71
        while ($this->exists($name)) {
72
            usleep(100);
73
        }
74
        return true;
75
    }
76
}
77