All: Fixes #13611: Fix missing conflict scenario #13624
Open
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
As per my comment at #13611 (comment)
It is possible in a certain scenario for the conflict mechanism to be bypassed, creating no conflict when conflicting changes are synced. This results in data loss unless the user notices the missing changes and checks for them in the note history. This scenario is not dependent on there being time drift between devices running the Joplin client, but is simply dependent on the timing of which the sync runs when using multiple Joplin clients. The problem is most likely to affect users that use multiple Joplin clients concurrently, or frequently switch between clients.
Reproduction steps:
The issue occurs because the upload step of sync relies on a comparison of if (remoteContent.updated_time > local.sync_time), where the sync time may be greater than the remoteContent.updated_time if the sync has since been run on another client with a new change to the note for that client.
This PR resolves the issue, by setting the sync_time to the remote item updated_time when the sync downloads a remote change (in the delta step and in conflict resolution), similar to when the sync uploads changes, which sets sync_time to the local item updated_time. However, as the remote item updated_time will originate from the local time of other devices in most cases, the setting of the sync_time also caps the value at the current device time. This is to prevent potential sync issues, in cases where there is time drift between devices.
This fixes #13611
Testing
See video:
fix.missing.conflict.scenario.mp4
This demonstrates normal sync working correctly and the conflict resolution working correctly when applying the reproduction steps, using 3 Joplin clients (simulated by switching between profiles) and additionally making a conflict again on the same note, when syncing an un-synced change which was made before the first conflict occurred. I have also tested that note deletion and conflict resolution when a note is deleted on one client is working correctly, and verified the behaviour matches existing, when enabling encryption and syncing the encrypted notes with an existing client.