Skip to content

Commit 5b23515

Browse files
Merge branch '5.4' into 6.0
* 5.4: expand uninitialized session tests [Lock] Release PostgreSqlStore connection lock on failure [DomCrawler] Fix HTML5 parser charset option cs fix [HttpKernel] Do not attempt to register enum arguments in controller service locator [Mime] Fix missing sprintf in DkimSigner [Translation] [LocoProvider] Use rawurlencode and separate tag setting [Security] fix unserializing session payloads from v4 [Cache] Don't lock when doing nested computations [Messenger] fix Redis support on 32b arch [HttpFoundation] Fix notice when HTTP_PHP_AUTH_USER passed without pass [Security] Add getting started example to README
2 parents fda0e97 + dbc600b commit 5b23515

File tree

2 files changed

+68
-20
lines changed

2 files changed

+68
-20
lines changed

Store/PostgreSqlStore.php

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

75-
$sql = 'SELECT pg_try_advisory_lock(:key)';
76-
$stmt = $this->getConnection()->prepare($sql);
77-
$stmt->bindValue(':key', $this->getHashedKey($key));
78-
$result = $stmt->execute();
75+
$lockAcquired = false;
7976

80-
// Check if lock is acquired
81-
if (true === $stmt->fetchColumn()) {
82-
$key->markUnserializable();
83-
// release sharedLock in case of promotion
84-
$this->unlockShared($key);
77+
try {
78+
$sql = 'SELECT pg_try_advisory_lock(:key)';
79+
$stmt = $this->getConnection()->prepare($sql);
80+
$stmt->bindValue(':key', $this->getHashedKey($key));
81+
$result = $stmt->execute();
8582

86-
return;
83+
// Check if lock is acquired
84+
if (true === $stmt->fetchColumn()) {
85+
$key->markUnserializable();
86+
// release sharedLock in case of promotion
87+
$this->unlockShared($key);
88+
89+
$lockAcquired = true;
90+
91+
return;
92+
}
93+
} finally {
94+
if (!$lockAcquired) {
95+
$this->getInternalStore()->delete($key);
96+
}
8797
}
8898

8999
throw new LockConflictedException();
@@ -94,19 +104,29 @@ public function saveRead(Key $key)
94104
// prevent concurrency within the same connection
95105
$this->getInternalStore()->saveRead($key);
96106

97-
$sql = 'SELECT pg_try_advisory_lock_shared(:key)';
98-
$stmt = $this->getConnection()->prepare($sql);
107+
$lockAcquired = false;
99108

100-
$stmt->bindValue(':key', $this->getHashedKey($key));
101-
$result = $stmt->execute();
109+
try {
110+
$sql = 'SELECT pg_try_advisory_lock_shared(:key)';
111+
$stmt = $this->getConnection()->prepare($sql);
112+
113+
$stmt->bindValue(':key', $this->getHashedKey($key));
114+
$result = $stmt->execute();
102115

103-
// Check if lock is acquired
104-
if (true === $stmt->fetchColumn()) {
105-
$key->markUnserializable();
106-
// release lock in case of demotion
107-
$this->unlock($key);
116+
// Check if lock is acquired
117+
if (true === $stmt->fetchColumn()) {
118+
$key->markUnserializable();
119+
// release lock in case of demotion
120+
$this->unlock($key);
108121

109-
return;
122+
$lockAcquired = true;
123+
124+
return;
125+
}
126+
} finally {
127+
if (!$lockAcquired) {
128+
$this->getInternalStore()->delete($key);
129+
}
110130
}
111131

112132
throw new LockConflictedException();

Tests/Store/PostgreSqlStoreTest.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\Lock\Tests\Store;
1313

1414
use Symfony\Component\Lock\Exception\InvalidArgumentException;
15+
use Symfony\Component\Lock\Exception\LockConflictedException;
1516
use Symfony\Component\Lock\Key;
1617
use Symfony\Component\Lock\PersistingStoreInterface;
1718
use Symfony\Component\Lock\Store\PostgreSqlStore;
@@ -50,4 +51,31 @@ public function testInvalidDriver()
5051
$this->expectExceptionMessage('The adapter "Symfony\Component\Lock\Store\PostgreSqlStore" does not support');
5152
$store->exists(new Key('foo'));
5253
}
54+
55+
public function testSaveAfterConflict()
56+
{
57+
$store1 = $this->getStore();
58+
$store2 = $this->getStore();
59+
60+
$key = new Key(uniqid(__METHOD__, true));
61+
62+
$store1->save($key);
63+
$this->assertTrue($store1->exists($key));
64+
65+
$lockConflicted = false;
66+
67+
try {
68+
$store2->save($key);
69+
} catch (LockConflictedException $lockConflictedException) {
70+
$lockConflicted = true;
71+
}
72+
73+
$this->assertTrue($lockConflicted);
74+
$this->assertFalse($store2->exists($key));
75+
76+
$store1->delete($key);
77+
78+
$store2->save($key);
79+
$this->assertTrue($store2->exists($key));
80+
}
5381
}

0 commit comments

Comments
 (0)