Skip to content

Commit dbc600b

Browse files
Merge branch '5.3' into 5.4
* 5.3: 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 323dd01 + c2ce745 commit dbc600b

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
@@ -94,18 +94,28 @@ public function save(Key $key)
9494
// prevent concurrency within the same connection
9595
$this->getInternalStore()->save($key);
9696

97-
$sql = 'SELECT pg_try_advisory_lock(:key)';
98-
$stmt = $this->getConnection()->prepare($sql);
99-
$stmt->bindValue(':key', $this->getHashedKey($key));
100-
$result = $stmt->execute();
97+
$lockAcquired = false;
10198

102-
// Check if lock is acquired
103-
if (true === $stmt->fetchColumn()) {
104-
$key->markUnserializable();
105-
// release sharedLock in case of promotion
106-
$this->unlockShared($key);
99+
try {
100+
$sql = 'SELECT pg_try_advisory_lock(:key)';
101+
$stmt = $this->getConnection()->prepare($sql);
102+
$stmt->bindValue(':key', $this->getHashedKey($key));
103+
$result = $stmt->execute();
107104

108-
return;
105+
// Check if lock is acquired
106+
if (true === $stmt->fetchColumn()) {
107+
$key->markUnserializable();
108+
// release sharedLock in case of promotion
109+
$this->unlockShared($key);
110+
111+
$lockAcquired = true;
112+
113+
return;
114+
}
115+
} finally {
116+
if (!$lockAcquired) {
117+
$this->getInternalStore()->delete($key);
118+
}
109119
}
110120

111121
throw new LockConflictedException();
@@ -122,19 +132,29 @@ public function saveRead(Key $key)
122132
// prevent concurrency within the same connection
123133
$this->getInternalStore()->saveRead($key);
124134

125-
$sql = 'SELECT pg_try_advisory_lock_shared(:key)';
126-
$stmt = $this->getConnection()->prepare($sql);
135+
$lockAcquired = false;
127136

128-
$stmt->bindValue(':key', $this->getHashedKey($key));
129-
$result = $stmt->execute();
137+
try {
138+
$sql = 'SELECT pg_try_advisory_lock_shared(:key)';
139+
$stmt = $this->getConnection()->prepare($sql);
140+
141+
$stmt->bindValue(':key', $this->getHashedKey($key));
142+
$result = $stmt->execute();
130143

131-
// Check if lock is acquired
132-
if (true === $stmt->fetchColumn()) {
133-
$key->markUnserializable();
134-
// release lock in case of demotion
135-
$this->unlock($key);
144+
// Check if lock is acquired
145+
if (true === $stmt->fetchColumn()) {
146+
$key->markUnserializable();
147+
// release lock in case of demotion
148+
$this->unlock($key);
136149

137-
return;
150+
$lockAcquired = true;
151+
152+
return;
153+
}
154+
} finally {
155+
if (!$lockAcquired) {
156+
$this->getInternalStore()->delete($key);
157+
}
138158
}
139159

140160
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)