-
Notifications
You must be signed in to change notification settings - Fork 136
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
Up Next Queue Syncing: Attempt to merge the local and remote device changes to prevent items from the queue being removed or cleared #661
Up Next Queue Syncing: Attempt to merge the local and remote device changes to prevent items from the queue being removed or cleared #661
Conversation
…nges to the sync task
// to us, and we will attempt to merge the changes in the `applyServerChanges` call below | ||
// | ||
if ServerSettings.syncReason != .login { | ||
// replace action |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code block here is the same as it was before, it's just been wrapped in the if check
podcasts/PlaybackQueue.swift
Outdated
startSyncTimer() | ||
|
||
// Persist the copy on the server immediately. | ||
RefreshManager.shared.syncUpNext() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Normally this would fire a sync after a delay, however since this is only used while we're already syncing I think we should trigger it immediately.
podcasts/AuthenticationHelper.swift
Outdated
@@ -56,6 +56,7 @@ class AuthenticationHelper { | |||
// we've signed in, set all our existing podcasts to be non synced | |||
DataManager.sharedManager.markAllPodcastsUnsynced() | |||
|
|||
ServerSettings.syncReason = .login |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will need to update this for SSO new accounts / logged in accounts as well.
// To prevent this, during a login we no longer send any local changes to the server, instead we pull the latest sync'd | ||
// up next queue and attempt to merge the changes later in the "applyServerChanges" call. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
...we no longer send any local changes to the server, instead we pull the latest sync'd up next queue and attempt to merge the changes
FWIW, it looks like Android already wasn't sending the local changes to the server until after it merged the queues, so this aligns well (Android's problem was that it was "merging" the server and local queues by removing any locally queued episodes that weren't in the server queue 😬 ).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@emilylaguna I have a concern regarding the known issues. When we think about data loss, it indeed pays off. But what if those issues start happening much more than the current data loss issue?
I believe there's no way to know that and we'll need to test and see how it goes. In the meantime, it would be interesting to give support all this context beforehand.
If we start receiving complaints about those issues we might need to rethink this approach.
public enum SyncingReason: String { | ||
case accountCreated | ||
case login | ||
} |
There was a problem hiding this 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 this belongs to ServerConstants
. This is used only by the client, right?
This induces me to think that the sync reason is also given to the server, which is not true.
I believe we can declare that outside of the ServerConstants
and stating that this is for internal use.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I moved it into the SyncManager here: 9ecdec1
I figured this was a better choice since contextually it goes hand in hand, and it already has a isFirstSyncInProgress
helper function.
This is a a very valid point. I tried to mitigate this by reducing the instances where the merging takes place to just a login action. However like you said, it is impossible to know before hand how many people will encounter this and if it's more than the people who were losing their data. Once this is merged in I'll write a P2 describing the issue, the fix, and make sure that support is also aware of this.
100% agree. |
Part of #24
Description
This attempts to solve the instances where a users up next queue can be incorrectly cleared, or replaced with the contents of an outdated account. For more info on the scenarios that this could occur see this comment.
In order to prevent a users queue from being removed we now apply different logic based on the context ("reason") that a sync is occurring.
Account Creation
If we are syncing because due to a new account being created, we treat the local queue as the source of truth and it is then persisted to the server.
Logging In
If we are syncing because the user is logging into an existing account we apply a non-destructive merge:
Everything else
We apply the same logic as we did before.
Known issues with this approach
Removed episodes reappearing
Since during a login we only add items to the queue, and never remove them a user who has previously removed episodes from their queue may have them added back in if they login on a device that is not up to date.
However, I think this is a worthy trade off to deleting or replacing users queues entirely.
Sort order not persisting for logged out users
During a login the latest server changes are applied to the episodes in the queue which means any local episodes that were added may appear out of their original order.
Again, I think this is an okay trade off.
Demo Videos
Installing the app from scratch and logging into an existing account that has a queue
new-install-logged-in.mov
Logged out user with queued items, logging into existing account with a queue
logged-out-to-in.mov
Logged out user with queued items, logging into an account that has no queue
logged-in-empty.mov
Logged out user with items that were removed on the other device
issue-logged-out-removed.mov
To test
Account Creation
Installing the app from scratch and logging into an existing account that has a queue
Being a logged out user with items added to the up next, and logging into an account that has no items in the queue
Being a logged out user with items added to the up next, and logging into an account that has existing items in the queue
Being a logged out user who removed items from their queue, and logging into an account where those changes weren't persisted
Being a logged in user both devices and syncing changes
Checklist
CHANGELOG.md
if necessary.