Skip to content

[Lock] [MongoDB] Enforce readPreference=primary and writeConcern=majority #61091

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from

Conversation

notrix
Copy link

@notrix notrix commented Jul 10, 2025

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.

@notrix notrix requested a review from jderusse as a code owner July 10, 2025 09:12
@carsonbot carsonbot added this to the 6.4 milestone Jul 10, 2025
@carsonbot
Copy link

It looks like you unchecked the "Allow edits from maintainer" box. That is fine, but please note that if you have multiple commits, you'll need to squash your commits into one before this can be merged. Or, you can check the "Allow edits from maintainers" box and the maintainer can squash for you.

Cheers!

Carsonbot

@carsonbot carsonbot changed the title Allow changing readPreference for MongoDB lock store [Lock] Allow changing readPreference for MongoDB lock store Jul 10, 2025
@OskarStark
Copy link
Contributor

friendly ping @GromNaN

@GromNaN GromNaN self-requested a review July 10, 2025 11:42
Copy link
Member

@GromNaN GromNaN left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's a good idea to use anything other than readPreference=primary for the lock. Or you could use writeConcern={w:<total number of nodes>}, but that will cause an error as soon as one mongodb node goes down.

The bug fix is fine, but I believe we should not add the new "readPreference" option, instead we should always use "primary". In that case, we don't really use the replication, writeConcern can be always set to w=1 since we are only interested in writing to the primary node.

Adding an option is a new feature in Symfony, which can only be merged in the next minor version. But this bugfix need to be done in 6.4

@OskarStark OskarStark changed the title [Lock] Allow changing readPreference for MongoDB lock store [Lock][MongoDB] Allow changing readPreference Jul 10, 2025
@alcaeus
Copy link
Contributor

alcaeus commented Jul 10, 2025

This pull request addresses an issue where the MongoDbStore ignores the readPreference set on a MongoDB Collection, instead defaulting to the readPreference of the main Doctrine connection. This can cause a race condition when releasing a lock, leading to a failure exception.

I agree, this is not desirable. For something as critical as locking, this should always use a primary read preference. Alternatively, primaryPreferred would allow read operations even if no primary was available, but I'm not sure how relevant that use case is.

The changes in this PR ensure that the readPreference of the provided Collection is respected. Additionally, it introduces the ability to pass a readPreference option directly to the MongoDbStore constructor for more explicit control.

As @GromNaN already said, we shouldn't rely on anything other than a primary read preference for reads. That guarantees that we're always reading the latest data.

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.

There are a couple of problems I can see with this approach:

  • If the delete command succeeded, the only option for that particular document to still be there would be if either w=0 was used (unacknowledged writes are always reported as succeeded) or a write concern less than the majority of nodes was used and the delete was lost during a failover (unlikely but possible).
  • If you really want to check that the delete command succeeded, using a secondary read preference could always lead to issues unless you specified a write concern equal to the number of nodes in the cluster, which comes with its own problems.

With all that in mind, using a primary read preference is the best solution for the problem. If we really want to be on the safe side, we could also ensure a majority write concern for all writes concerning the lock. While the default write concern is already majority, the connection itself may be using a different write concern. Using a majority write concern makes the writes more durable in case of failovers.

@stof
Copy link
Member

stof commented Jul 10, 2025

The PR title and description (and the commit message) should be updated to reflect the new solution being implemented.

@notrix
Copy link
Author

notrix commented Jul 10, 2025

I agree that in order this not to be a new feature we should not introduce new options and only stick to the issue. I have updated fixed readPreference to be primary and and writeConcern to be majority.

@notrix notrix changed the title [Lock][MongoDB] Allow changing readPreference [Lock][MongoDB] Enforce readPreference=primary and writeConcern=majority Jul 10, 2025
@notrix notrix changed the title [Lock][MongoDB] Enforce readPreference=primary and writeConcern=majority [Lock][MongoDB] Enforce readPreference=primary and writeConcern=majority Jul 10, 2025
Copy link
Contributor

@alcaeus alcaeus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

writeConcern and readPreference usage LGTM.

@carsonbot carsonbot changed the title [Lock][MongoDB] Enforce readPreference=primary and writeConcern=majority [Lock] [MongoDB] Enforce readPreference=primary and writeConcern=majority Jul 10, 2025
@fabpot
Copy link
Member

fabpot commented Jul 12, 2025

Thank you @notrix.

fabpot added a commit that referenced this pull request Jul 12, 2025
…oncern=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
@fabpot
Copy link
Member

fabpot commented Jul 12, 2025

Merged

@fabpot fabpot closed this Jul 12, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy