Skip to content

Commit 7d14256

Browse files
Merge branch '5.4' into 6.0
* 5.4: [Lock] Release DoctrineDbalPostgreSqlStore connection lock on failure [DependencyInjection][HttpKernel] Fix enum typed bindings make login link handler tests time sensitive [CI] Remove macOS jobs Suppress psalm error for UndefinedDocblockClass for PHP 8.1 classes
2 parents 5b23515 + 5e1d6ad commit 7d14256

File tree

2 files changed

+67
-20
lines changed

2 files changed

+67
-20
lines changed

Store/DoctrineDbalPostgreSqlStore.php

Lines changed: 40 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -58,18 +58,28 @@ public function save(Key $key)
5858
// prevent concurrency within the same connection
5959
$this->getInternalStore()->save($key);
6060

61-
$sql = 'SELECT pg_try_advisory_lock(:key)';
62-
$result = $this->conn->executeQuery($sql, [
63-
'key' => $this->getHashedKey($key),
64-
]);
61+
$lockAcquired = false;
6562

66-
// Check if lock is acquired
67-
if (true === $result->fetchOne()) {
68-
$key->markUnserializable();
69-
// release sharedLock in case of promotion
70-
$this->unlockShared($key);
63+
try {
64+
$sql = 'SELECT pg_try_advisory_lock(:key)';
65+
$result = $this->conn->executeQuery($sql, [
66+
'key' => $this->getHashedKey($key),
67+
]);
7168

72-
return;
69+
// Check if lock is acquired
70+
if (true === $result->fetchOne()) {
71+
$key->markUnserializable();
72+
// release sharedLock in case of promotion
73+
$this->unlockShared($key);
74+
75+
$lockAcquired = true;
76+
77+
return;
78+
}
79+
} finally {
80+
if (!$lockAcquired) {
81+
$this->getInternalStore()->delete($key);
82+
}
7383
}
7484

7585
throw new LockConflictedException();
@@ -80,18 +90,28 @@ public function saveRead(Key $key)
8090
// prevent concurrency within the same connection
8191
$this->getInternalStore()->saveRead($key);
8292

83-
$sql = 'SELECT pg_try_advisory_lock_shared(:key)';
84-
$result = $this->conn->executeQuery($sql, [
85-
'key' => $this->getHashedKey($key),
86-
]);
93+
$lockAcquired = false;
94+
95+
try {
96+
$sql = 'SELECT pg_try_advisory_lock_shared(:key)';
97+
$result = $this->conn->executeQuery($sql, [
98+
'key' => $this->getHashedKey($key),
99+
]);
87100

88-
// Check if lock is acquired
89-
if (true === $result->fetchOne()) {
90-
$key->markUnserializable();
91-
// release lock in case of demotion
92-
$this->unlock($key);
101+
// Check if lock is acquired
102+
if (true === $result->fetchOne()) {
103+
$key->markUnserializable();
104+
// release lock in case of demotion
105+
$this->unlock($key);
93106

94-
return;
107+
$lockAcquired = true;
108+
109+
return;
110+
}
111+
} finally {
112+
if (!$lockAcquired) {
113+
$this->getInternalStore()->delete($key);
114+
}
95115
}
96116

97117
throw new LockConflictedException();

Tests/Store/DoctrineDbalPostgreSqlStoreTest.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Doctrine\DBAL\DriverManager;
1515
use Symfony\Component\Lock\Exception\InvalidArgumentException;
16+
use Symfony\Component\Lock\Exception\LockConflictedException;
1617
use Symfony\Component\Lock\Key;
1718
use Symfony\Component\Lock\PersistingStoreInterface;
1819
use Symfony\Component\Lock\Store\DoctrineDbalPostgreSqlStore;
@@ -59,4 +60,30 @@ public function getInvalidDrivers()
5960
yield ['sqlite:///tmp/foo.db'];
6061
yield [DriverManager::getConnection(['url' => 'sqlite:///tmp/foo.db'])];
6162
}
63+
64+
public function testSaveAfterConflict()
65+
{
66+
$store1 = $this->getStore();
67+
$store2 = $this->getStore();
68+
69+
$key = new Key(uniqid(__METHOD__, true));
70+
71+
$store1->save($key);
72+
$this->assertTrue($store1->exists($key));
73+
74+
$lockConflicted = false;
75+
try {
76+
$store2->save($key);
77+
} catch (LockConflictedException $lockConflictedException) {
78+
$lockConflicted = true;
79+
}
80+
81+
$this->assertTrue($lockConflicted);
82+
$this->assertFalse($store2->exists($key));
83+
84+
$store1->delete($key);
85+
86+
$store2->save($key);
87+
$this->assertTrue($store2->exists($key));
88+
}
6289
}

0 commit comments

Comments
 (0)