Failed Conditions
Pull Request — master (#2)
by Mathieu
02:24 queued 21s
created

RedisSimpleLock::releaseClosure()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 19
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
c 1
b 1
f 0
dl 0
loc 19
rs 9.4285
cc 2
eloc 12
nc 1
nop 0
1
<?php
2
3
namespace TH\RedisLock;
4
5
use Exception;
6
use Predis\Client;
7
use Predis\Response\Status;
8
use Psr\Log\LoggerInterface;
9
use Psr\Log\NullLogger;
10
use TH\Lock\Lock;
11
12
class RedisSimpleLock implements Lock
13
{
14
    private $identifier;
15
    private $client;
16
    private $ttl;
17
    private $logger;
18
    private $id;
19
20
    /**
21
     * Create new RedisSimpleLock
22
     *
23
     * @param string               $identifier the redis lock key
24
     * @param Client               $client     the Predis client
25
     * @param integer              $ttl        lock time-to-live in milliseconds
26
     * @param LoggerInterface|null $logger
27
     */
28
    public function __construct($identifier, Client $client, $ttl = 10000, LoggerInterface $logger = null)
29
    {
30
        $this->identifier = $identifier;
31
        $this->client     = $client;
32
        $this->ttl        = $ttl;
33
        $this->logger     = $logger ?: new NullLogger;
34
        $this->id         = mt_rand();
35
        register_shutdown_function($this->releaseClosure());
36
    }
37
38
    public function acquire()
39
    {
40
        $log_data = ["identifier" => $this->identifier];
41
        $response = $this->client->set($this->identifier, $this->id, "PX", $this->ttl, "NX");
42
        if (!$response instanceof Status || $response->getPayload() !== "OK") {
43
            $this->logger->debug("could not acquire lock on {identifier}", $log_data);
44
45
            throw new Exception("Could not acquire lock on " . $this->identifier);
46
        }
47
        $this->logger->debug("lock acquired on {identifier}", $log_data);
48
    }
49
50
    public function release()
51
    {
52
        $closure = $this->releaseClosure();
53
        $closure();
54
    }
55
56
    public function __destruct()
57
    {
58
        $this->release();
59
    }
60
61
    private function releaseClosure()
62
    {
63
        $client = $this->client;
64
        $id = $this->id;
65
        $identifier = $this->$identifier;
0 ignored issues
show
Bug introduced by
The variable $identifier seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
66
        $logger = $this->logger;
67
68
        $closure = function () use ($client, $identifier, $id, $logger) {
69
            $script = <<<LUA
70
    if redis.call("get", KEYS[1]) == ARGV[1] then
71
        return redis.call("del", KEYS[1])
72
    end
73
LUA;
74
            if ($this->client->eval($script, 1, $this->identifier, $this->id)) {
75
                $this->logger->debug("lock released on {identifier}", ["identifier" => $this->identifier]);
76
            }
77
        };
78
        return $closure->bindTo(null);
79
    }
80
}
81