Skip to content

Commit bba2712

Browse files
committed
Move state into store from key
1 parent 6954fc6 commit bba2712

File tree

2 files changed

+24
-35
lines changed

2 files changed

+24
-35
lines changed

src/Symfony/Component/Lock/Store/MysqlStore.php

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ class MysqlStore implements PersistingStoreInterface
2929

3030
private array $options;
3131

32+
/** @var bool[] */
33+
private static array $locksAcquired = [];
34+
3235
public function __construct(\PDO|string $connOrDsn, array $options = [])
3336
{
3437
if ($connOrDsn instanceof \PDO) {
@@ -46,22 +49,20 @@ public function __construct(\PDO|string $connOrDsn, array $options = [])
4649

4750
public function save(Key $key): void
4851
{
49-
if ($key->hasState(__CLASS__)) {
52+
$id = $this->getLockId($key);
53+
54+
if (self::$locksAcquired[$id] ?? false) {
5055
return;
5156
}
5257

53-
// mysql limits lock name length to 64 chars
54-
$name = (string) $key;
55-
$name = \strlen($name) > 64 ? hash('xxh128', $name) : $name;
56-
5758
$stmt = $this->conn->prepare('SELECT IF(IS_USED_LOCK(:name) = CONNECTION_ID(), -1, GET_LOCK(:name, 0))');
58-
$stmt->bindValue(':name', $name, \PDO::PARAM_STR);
59+
$stmt->bindValue(':name', self::getLockName($key), \PDO::PARAM_STR);
5960
$stmt->execute();
6061
$result = $stmt->fetchColumn();
6162

6263
// lock acquired
6364
if (1 === $result) {
64-
$key->setState(__CLASS__, $name);
65+
self::$locksAcquired[$this->getLockId($key)] = true;
6566

6667
return;
6768
}
@@ -84,28 +85,16 @@ public function putOffExpiration(Key $key, float $ttl): void
8485

8586
public function delete(Key $key): void
8687
{
87-
if (!$key->hasState(__CLASS__)) {
88-
return;
89-
}
90-
9188
$stmt = $this->conn->prepare('DO RELEASE_LOCK(:name)');
92-
$stmt->bindValue(':name', $key->getState(__CLASS__), \PDO::PARAM_STR);
89+
$stmt->bindValue(':name', self::getLockName($key), \PDO::PARAM_STR);
9390
$stmt->execute();
9491

95-
$key->removeState(__CLASS__);
92+
unset(self::$locksAcquired[$this->getLockId($key)]);
9693
}
9794

9895
public function exists(Key $key): bool
9996
{
100-
if (!$key->hasState(__CLASS__)) {
101-
return false;
102-
}
103-
104-
$stmt = $this->conn->prepare('SELECT IF(IS_USED_LOCK(:name) = CONNECTION_ID(), 1, 0)');
105-
$stmt->bindValue(':name', $key->getState(__CLASS__), \PDO::PARAM_STR);
106-
$stmt->execute();
107-
108-
return 1 === $stmt->fetchColumn();
97+
return self::$locksAcquired[$this->getLockId($key)] ?? false;
10998
}
11099

111100
private function getConnection(): \PDO
@@ -130,4 +119,17 @@ private function assertMysqlDriver(): void
130119
throw new InvalidArgumentException(sprintf('The adapter "%s" does not support the "%s" driver.', __CLASS__, $driver));
131120
}
132121
}
122+
123+
private function getLockId(Key $key): string
124+
{
125+
return spl_object_id($this->getConnection()).'_'.spl_object_id($key);
126+
}
127+
128+
private static function getLockName(Key $key): string
129+
{
130+
// mysql limits lock name length to 64 chars
131+
$name = (string) $key;
132+
133+
return \strlen($name) > 64 ? hash('xxh128', $name) : $name;
134+
}
133135
}

src/Symfony/Component/Lock/Tests/Store/MysqlStoreTest.php

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -53,19 +53,6 @@ public function testExceptionModeRequirement()
5353
new MysqlStore($pdo);
5454
}
5555

56-
public function testSelfConflictException()
57-
{
58-
$store = $this->getStore();
59-
$store->save(new Key('foo'));
60-
61-
try {
62-
$store->save(new Key('foo'));
63-
$this->fail('Expected exception: '.LockConflictedException::class);
64-
} catch (LockConflictedException $e) {
65-
$this->assertStringContainsString('acquired by this', $e->getMessage());
66-
}
67-
}
68-
6956
public function testOtherConflictException()
7057
{
7158
$storeA = $this->getStore();

0 commit comments

Comments
 (0)