Test Failed
Pull Request — master (#15)
by Evgeniy
11:17 queued 08:56
created

MysqlMutex::isReleased()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Mutex;
6
7
use InvalidArgumentException;
8
use PDO;
9
use RuntimeException;
10
11
/**
12
 * MysqlMutex implements mutex "lock" mechanism via MySQL locks.
13
 */
14
final class MysqlMutex extends Mutex
15
{
16
    private string $name;
17
    private PDO $connection;
18
    private bool $released = false;
19
20
    /**
21
     * DbMutex constructor.
22
     *
23
     * @param string $name Mutex name.
24
     * @param PDO $connection PDO connection instance to use.
25
     */
26
    public function __construct(string $name, PDO $connection)
27
    {
28
        $this->name = $name;
29
        $this->connection = $connection;
30
        $driverName = $connection->getAttribute(PDO::ATTR_DRIVER_NAME);
31
        if ($driverName !== 'mysql') {
32
            throw new InvalidArgumentException('MySQL connection instance should be passed. Got ' . $driverName . '.');
33
        }
34
    }
35
36
    /**
37
     * {@inheritdoc}
38
     *
39
     * @see http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_get-lock
40
     */
41
    public function acquire(int $timeout = 0): bool
42
    {
43
        $statement = $this->connection->prepare('SELECT GET_LOCK(:name, :timeout)');
44
        $statement->bindValue(':name', $this->hashLockName($this->name));
45
        $statement->bindValue(':timeout', $timeout);
46
        $statement->execute();
47
48
        if ($statement->fetchColumn()) {
49
            $this->released = false;
50
            return true;
51
        }
52
53
        return false;
54
    }
55
56
    /**
57
     * {@inheritdoc}
58
     *
59
     * @see http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_release-lock
60
     */
61
    public function release(): void
62
    {
63
        $statement = $this->connection->prepare('SELECT RELEASE_LOCK(:name)');
64
        $statement->bindValue(':name', $this->hashLockName($this->name));
65
        $statement->execute();
66
67
        if (!$statement->fetchColumn()) {
68
            throw new RuntimeException("Unable to release lock \"$this->name\".");
69
        }
70
71
        $this->released = true;
72
    }
73
74
    public function isReleased(): bool
75
    {
76
        return $this->released;
77
    }
78
79
    /**
80
     * Generate hash for lock name to avoid exceeding lock name length limit.
81
     *
82
     * @param string $name
83
     *
84
     * @return string
85
     *
86
     * @see https://github.com/yiisoft/yii2/pull/16836
87
     */
88
    private function hashLockName(string $name): string
89
    {
90
        return sha1($name);
91
    }
92
}
93