Test Failed
Pull Request — master (#12)
by Evgeniy
14:01 queued 11:25
created

PgsqlMutex::release()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
cc 2
eloc 8
c 2
b 1
f 0
nc 2
nop 0
dl 0
loc 14
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Mutex;
6
7
use PDO;
8
9
/**
10
 * PgsqlMutex implements mutex "lock" mechanism via PgSQL locks.
11
 */
12
final class PgsqlMutex extends Mutex
13
{
14
    use RetryAcquireTrait;
15
16
    private string $name;
17
    private PDO $connection;
18
    private bool $released = false;
19
20
    /**
21
     * @param string $name Mutex name.
22
     * @param PDO $connection PDO connection instance to use.
23
     */
24
    public function __construct(string $name, PDO $connection)
25
    {
26
        $this->name = $name;
27
        $this->connection = $connection;
28
        $driverName = $connection->getAttribute(PDO::ATTR_DRIVER_NAME);
29
        if ($driverName !== 'pgsql') {
30
            throw new \InvalidArgumentException(
31
                'Connection must be configured to use PgSQL database. Got ' . $driverName . '.'
32
            );
33
        }
34
    }
35
36
    /**
37
     * {@inheritdoc}
38
     *
39
     * @see http://www.postgresql.org/docs/9.0/static/functions-admin.html
40
     */
41
    public function acquire(int $timeout = 0): bool
42
    {
43
        [$key1, $key2] = $this->getKeysFromName($this->name);
44
45
        return $this->retryAcquire($timeout, function () use ($key1, $key2) {
46
            $statement = $this->connection->prepare('SELECT pg_try_advisory_lock(:key1, :key2)');
47
            $statement->bindValue(':key1', $key1);
48
            $statement->bindValue(':key2', $key2);
49
            $statement->execute();
50
51
            if ($statement->fetchColumn()) {
52
                $this->released = false;
53
                return true;
54
            }
55
56
            return false;
57
        });
58
    }
59
60
    /**
61
     * {@inheritdoc}
62
     *
63
     * @see http://www.postgresql.org/docs/9.0/static/functions-admin.html
64
     */
65
    public function release(): void
66
    {
67
        [$key1, $key2] = $this->getKeysFromName($this->name);
68
69
        $statement = $this->connection->prepare('SELECT pg_advisory_unlock(:key1, :key2)');
70
        $statement->bindValue(':key1', $key1);
71
        $statement->bindValue(':key2', $key2);
72
        $statement->execute();
73
74
        if (!$statement->fetchColumn()) {
75
            throw new RuntimeExceptions("Unable to release lock \"$this->name\".");
0 ignored issues
show
Bug introduced by
The type Yiisoft\Mutex\RuntimeExceptions was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
76
        }
77
78
        $this->released = true;
79
    }
80
81
    public function isReleased(): bool
82
    {
83
        return $this->released;
84
    }
85
86
    /**
87
     * Converts a string into two 16 bit integer keys using the SHA1 hash function.
88
     *
89
     * @param string $name
90
     *
91
     * @return array contains two 16 bit integer keys
92
     */
93
    private function getKeysFromName(string $name): array
94
    {
95
        return array_values(unpack('n2', sha1($name, true)));
96
    }
97
}
98