Skip to content
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

Fix a race condition that leads to a CouchDB conflict #4158

Merged
merged 1 commit into from
Oct 11, 2023

Conversation

nono
Copy link
Member

@nono nono commented Oct 11, 2023

If Alice and Bob shares a file within a Cozy to Cozy sharing. The file is present on both cozy instances, and the two users make a change on this file concurrently. For example, Alice adds the file to a photo album, and Bob renames it. A race condition may happen when Bob's instance sends its update to Alice's instance. The CouchDB document will then been saved in CouchDB with a conflict (two leaf revisions).

+----------------------------------+----------------------------------+
| Goroutine A                      | Goroutine B                      |
| Add the file to an album         | Share-replicate sends the rename |
+----------------------------------+----------------------------------+
|                                  | 1. Load the file from CouchDB    |
| 2. Load the file from CouchDB    |                                  |
| 3. Get the VFS lock              |                                  |
| 4. Save the file with rev 2-aaa  |                                  |
| 5. Release the VFS lock          |                                  |
|                                  | 6. Get the VFS lock              |
|                                  | 7. Save the file with rev 2-bbb  |
|                                  | 8. Release the VFS lock          |
+----------------------------------+----------------------------------+

In general, it is not possible to save a document with a revision 2-bbb, when the document is already at revision 2-aaa: CouchDB responds with a 409 Conflict. But, the share-track is doing a bulk update with the option new_edit: false. This is done because the replication process needs to force the same revision on Alice's Cozy that it is on Bob's Cozy. But, it also enable to create a conflict in CouchDB.

The fix is to reload the file between the steps 6 and 7 (when the VFS lock has been acquired), and check that the revision has not changed. It would be nice to load the document when the VFS lock is acquired, but it is not possible currently because of how the code is organized.

If Alice and Bob shares a file within a Cozy to Cozy sharing. The file
is present on both cozy instances, and the two users make a change on
this file concurrently. For example, Alice adds the file to a photo
album, and Bob renames it. A race condition may happen when Bob's
instance sends its update to Alice's instance. The CouchDB document will
then been saved in CouchDB with a conflict (two leaf revisions).

+----------------------------------+----------------------------------+
| Goroutine A                      | Goroutine B                      |
| Add the file to an album         | Share-replicate sends the rename |
+----------------------------------+----------------------------------+
|                                  | 1. Load the file from CouchDB    |
| 2. Load the file from CouchDB    |                                  |
| 3. Get the VFS lock              |                                  |
| 4. Save the file with rev 2-aaa  |                                  |
| 5. Release the VFS lock          |                                  |
|                                  | 6. Get the VFS lock              |
|                                  | 7. Save the file with rev 2-bbb  |
|                                  | 8. Release the VFS lock          |
+----------------------------------+----------------------------------+

In general, it is not possible to save a document with a revision 2-bbb,
when the document is already at revision 2-aaa: CouchDB responds with a
409 Conflict. But, the share-track is doing a bulk update with the option
new_edit: false. This is done because the replication process needs to
force the same revision on Alice's Cozy that it is on Bob's Cozy. But,
it also enable to create a conflict in CouchDB.

The fix is to reload the file between the steps 6 and 7 (when the VFS
lock has been acquired), and check that the revision has not changed.
It would be nice to load the document when the VFS lock is acquired, but
it is not possible currently because of how the code is organized.
@nono nono requested a review from a team as a code owner October 11, 2023 15:21
@nono nono merged commit afe48f0 into master Oct 11, 2023
4 checks passed
@nono nono deleted the fix-couch-conflict branch October 11, 2023 16:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants