Lines 100.00% 3 / 3
Functions and Methods 100.00% 3 / 3
Classes and Traits 100.00% 1 / 1
Name Lines Functions and Methods CRAP Classes and Traits
MySqlLock 100.00% 3 / 3 100.00% 3 / 3 3 100.00% 1 / 1
 __construct 100.00% 1 / 1 100.00% 1 / 1 1
 lockStatement 100.00% 1 / 1 100.00% 1 / 1 1
 unlockStatement 100.00% 1 / 1 100.00% 1 / 1 1
1<?php
2
3declare(strict_types=1);
4
5namespace BlueprintAU\Radiant\Database\Locks;
6
7use BlueprintAU\Radiant\Database\Connections\MySqlConnection;
8
9/**
10 * MySQL lock: `GET_LOCK` / `RELEASE_LOCK` on a named lock.
11 *
12 * `GET_LOCK` blocks until the named lock is free (or the timeout elapses,
13 * returning 0 — PDO then surfaces a non-exception zero row, so the
14 * statement is executed and checked by the caller in the base class's
15 * `statement()` path only insofar as SQL allows; the fixed 30-second
16 * timeout keeps a wedged worker from hanging forever).
17 *
18 * The lock name is supplied at call time via {@see withLock()} — one name
19 * is one mutual-exclusion domain, so distinct jobs use distinct names.
20 */
21final class MySqlLock extends SqlLock
22{
23    /**
24     * @param  MySqlConnection  $connection
25     */
26    public function __construct(MySqlConnection $connection)
27    {
28        parent::__construct($connection);
29    }
30
31    /**
32     * The lock acquisition statement — blocks up to 30s, then fails.
33     *
34     * GET_LOCK returns 0 on timeout and NULL on error; the SELECT wraps the
35     * call in a signal expression that raises an error via a division by
36     * zero on a non-1 result.
37     *
38     * @return string
39     */
40    #[\Override]
41    protected function lockStatement(): string
42    {
43        return "SELECT IF(GET_LOCK(?, 30) = 1, 1, crc32('lock-timeout') DIV 0)";
44    }
45
46    /**
47     * The lock release statement.
48     *
49     * @return string
50     */
51    #[\Override]
52    protected function unlockStatement(): string
53    {
54        return 'DO RELEASE_LOCK(?)';
55    }
56}