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

Skip to content

Commit 758082a

Browse files
committed
bug #61091 [Lock] [MongoDB] Enforce readPreference=primary and writeConcern=majority (notrix)
This PR was squashed before being merged into the 6.4 branch. Discussion ---------- [Lock] [MongoDB] Enforce readPreference=primary and writeConcern=majority | Q | A | ------------- | --- | Branch? | 6.4 | Bug fix? | yes | New feature? | no | Deprecations? | no | Issues | Fix #58397 | License | MIT ### The Problem A scenario was identified, similar to issue #58397, where a lock cannot be successfully released. This occurs when the application: 1. Provides a MongoDB Collection to the `MongoDbStore` with `readPreference` set to `primary`. 2. Has a default `readPreference` of `nearest` configured on the MongoDB manager. When `release()` is called on a lock, the component first issues a `DELETE` command to the primary MongoDB node. Immediately after, it sends a query to verify the deletion. However, this verification query incorrectly uses the `nearest` read preference from the Doctrine connection, often hitting a secondary node. If replication to the secondary has not yet completed, the verification fails, and an exception is thrown, incorrectly reporting that the lock release failed. ### The Solution This update enforces `readPreference`=`primary` for and `writeConcern`=`majority`. This ensures that read and write operations related to the lock are consistently routed, preventing the race condition and ensuring reliable lock releases. Commits ------- f0c00db [Lock] [MongoDB] Enforce readPreference=primary and writeConcern=majority
2 parents 3edb596 + f0c00db commit 758082a

File tree

1 file changed

+22
-8
lines changed

1 file changed

+22
-8
lines changed

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

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
use MongoDB\Driver\Exception\BulkWriteException;
2121
use MongoDB\Driver\Manager;
2222
use MongoDB\Driver\Query;
23+
use MongoDB\Driver\ReadPreference;
24+
use MongoDB\Driver\WriteConcern;
2325
use MongoDB\Exception\DriverRuntimeException;
2426
use MongoDB\Exception\InvalidArgumentException as MongoInvalidArgumentException;
2527
use MongoDB\Exception\UnsupportedException;
@@ -61,9 +63,9 @@ class MongoDbStore implements PersistingStoreInterface
6163
private float $initialTtl;
6264

6365
/**
64-
* @param Collection|Client|Manager|string $mongo An instance of a Collection or Client or URI @see https://docs.mongodb.com/manual/reference/connection-string/
65-
* @param array $options See below
66-
* @param float $initialTtl The expiration delay of locks in seconds
66+
* @param Collection|Database|Client|Manager|string $mongo An instance of a Collection or Client or URI @see https://docs.mongodb.com/manual/reference/connection-string/
67+
* @param array $options See below
68+
* @param float $initialTtl The expiration delay of locks in seconds
6769
*
6870
* @throws InvalidArgumentException If required options are not provided
6971
* @throws InvalidTtlException When the initial ttl is not valid
@@ -89,8 +91,10 @@ class MongoDbStore implements PersistingStoreInterface
8991
* to 0.0 and optionally leverage
9092
* self::createTtlIndex(int $expireAfterSeconds = 0).
9193
*
92-
* writeConcern and readConcern are not specified by MongoDbStore meaning the connection's settings will take effect.
93-
* readPreference is primary for all queries.
94+
* readConcern is not specified by MongoDbStore meaning the connection's settings will take effect.
95+
* writeConcern is majority for all update queries.
96+
* readPreference is primary for all read queries.
97+
*
9498
* @see https://docs.mongodb.com/manual/applications/replication/
9599
*/
96100
public function __construct(Collection|Database|Client|Manager|string $mongo, array $options = [], float $initialTtl = 300.0)
@@ -286,7 +290,11 @@ public function delete(Key $key)
286290
['limit' => 1]
287291
);
288292

289-
$this->getManager()->executeBulkWrite($this->namespace, $write);
293+
$this->getManager()->executeBulkWrite(
294+
$this->namespace,
295+
$write,
296+
['writeConcern' => new WriteConcern(WriteConcern::MAJORITY)]
297+
);
290298
}
291299

292300
public function exists(Key $key): bool
@@ -303,7 +311,9 @@ public function exists(Key $key): bool
303311
'limit' => 1,
304312
'projection' => ['_id' => 1],
305313
]
306-
));
314+
), [
315+
'readPreference' => new ReadPreference(ReadPreference::PRIMARY)
316+
]);
307317

308318
return [] !== $cursor->toArray();
309319
}
@@ -345,7 +355,11 @@ private function upsert(Key $key, float $ttl): void
345355
]
346356
);
347357

348-
$this->getManager()->executeBulkWrite($this->namespace, $write);
358+
$this->getManager()->executeBulkWrite(
359+
$this->namespace,
360+
$write,
361+
['writeConcern' => new WriteConcern(WriteConcern::MAJORITY)]
362+
);
349363
}
350364

351365
private function isDuplicateKeyException(BulkWriteException $e): bool

0 commit comments

Comments
 (0)