Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit fab5991

Browse files
simon-watiaunicolas-grekas
authored andcommitted
[Lock] Release DoctrineDbalPostgreSqlStore connection lock on failure
1 parent 49c825e commit fab5991

File tree

2 files changed

+67
-20
lines changed

2 files changed

+67
-20
lines changed

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

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

65-
$sql = 'SELECT pg_try_advisory_lock(:key)';
66-
$result = $this->conn->executeQuery($sql, [
67-
'key' => $this->getHashedKey($key),
68-
]);
65+
$lockAcquired = false;
6966

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

76-
return;
73+
// Check if lock is acquired
74+
if (true === $result->fetchOne()) {
75+
$key->markUnserializable();
76+
// release sharedLock in case of promotion
77+
$this->unlockShared($key);
78+
79+
$lockAcquired = true;
80+
81+
return;
82+
}
83+
} finally {
84+
if (!$lockAcquired) {
85+
$this->getInternalStore()->delete($key);
86+
}
7787
}
7888

7989
throw new LockConflictedException();
@@ -84,18 +94,28 @@ public function saveRead(Key $key)
8494
// prevent concurrency within the same connection
8595
$this->getInternalStore()->saveRead($key);
8696

87-
$sql = 'SELECT pg_try_advisory_lock_shared(:key)';
88-
$result = $this->conn->executeQuery($sql, [
89-
'key' => $this->getHashedKey($key),
90-
]);
97+
$lockAcquired = false;
98+
99+
try {
100+
$sql = 'SELECT pg_try_advisory_lock_shared(:key)';
101+
$result = $this->conn->executeQuery($sql, [
102+
'key' => $this->getHashedKey($key),
103+
]);
91104

92-
// Check if lock is acquired
93-
if (true === $result->fetchOne()) {
94-
$key->markUnserializable();
95-
// release lock in case of demotion
96-
$this->unlock($key);
105+
// Check if lock is acquired
106+
if (true === $result->fetchOne()) {
107+
$key->markUnserializable();
108+
// release lock in case of demotion
109+
$this->unlock($key);
97110

98-
return;
111+
$lockAcquired = true;
112+
113+
return;
114+
}
115+
} finally {
116+
if (!$lockAcquired) {
117+
$this->getInternalStore()->delete($key);
118+
}
99119
}
100120

101121
throw new LockConflictedException();

src/Symfony/Component/Lock/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)