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

Up Next Queue Syncing: Attempt to merge the local and remote device changes to prevent items from the queue being removed or cleared #661

Merged
merged 23 commits into from
Jan 25, 2023

Conversation

emilylaguna
Copy link
Contributor

@emilylaguna emilylaguna commented Jan 21, 2023

Part of #24

Note: The majority of the line changes are actually me adding a ton of documentation and logging.

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:

  • Retrieve the latest up next queue from the server
  • Add all the remote items to the users local queue
  • Ensure any local episodes that were not on the server are not removed
  • Persist the "merged" changes to the server

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


Expectation: The existing users queued will be persisted on the new installation.


new-install-logged-in.mov

Logged out user with queued items, logging into existing account with a queue


Expectation: The logged out and existing queued items will be merged.


logged-out-to-in.mov

Logged out user with queued items, logging into an account that has no queue


Expectation: The logged out queued items will appear on the account


logged-in-empty.mov

Logged out user with items that were removed on the other device


Expectation: The deleted items will be restored when the logged out device logs back in


issue-logged-out-removed.mov

To test

Account Creation

  1. Reinstall the app
  2. Dismiss the login prompt
  3. Add some items to your up next queue
  4. Create a new account
  5. ✅ Verify your local queue remains the same as it was
  6. Sign into the new account on another device
  7. ✅ Verify the correct queue is sync'd

Installing the app from scratch and logging into an existing account that has a queue

  1. Sign into an account on device 1
  2. Add some items to your up next queue and sync them
  3. Reinstall the app on device 2
  4. When prompted tap login
  5. Sign into the device 1 account
  6. ✅ Verify the correct queue is added to your device
  7. Go to Device 1, and perform a sync
  8. ✅ Verify the queue remains the same

Being a logged out user with items added to the up next, and logging into an account that has no items in the queue

  1. Sign into an account on device 1
  2. Clear your queue
  3. Reinstall the app on device 2
  4. Dismiss the login prompt
  5. Add some items to the queue
  6. Sign into the device 1 account
  7. ✅ Verify your local queue remains the same
  8. Go to Device 1, and perform a sync
  9. ✅ Verify the device 2 queue is moved over

Being a logged out user with items added to the up next, and logging into an account that has existing items in the queue

  1. Sign into an account on device 1
  2. Add some items to your up next queue and sync them
  3. Reinstall the app on device 2
  4. Dismiss the login prompt
  5. Add some items to the queue
  6. Sign into the device 1 account
  7. ✅ Verify the queue consists of the items you added and the items from device 1
  8. Go to Device 1, and perform a sync
  9. ✅ Verify you see both device 1 and 2's queue

Being a logged out user who removed items from their queue, and logging into an account where those changes weren't persisted

  1. Sign into an account on device 1
  2. Add some items to your up next queue and sync them
  3. Reinstall the app on device 2
  4. Sign into device 1's account
  5. Then sign out
  6. Remove some items from the queue
  7. Sign back into device 1's account
  8. ⚠️ The items that you removed will be added back to device 2 (See known issues above)

Being a logged in user both devices and syncing changes

  1. Sign into an account on device 1
  2. Add some items to your up next queue and sync them
  3. On Device 2, Sign into device 1's account
  4. On Device 1, make some changes to the queue (add, remove, move, etc)
  5. Sync the changes
  6. On device 2, refresh
  7. ✅ The queue is updated correctly
  8. On device 2, make some changes to the queue.
  9. Sync them
  10. On device 1, refresh
  11. ✅ Verify the changes are sync'd back correctly.

Checklist

  • I have considered if this change warrants user-facing release notes and have added them to CHANGELOG.md if necessary.
  • I have considered adding unit tests for my changes.
  • I have updated (or requested that someone edit) the spreadsheet to reflect any new or changed analytics.

@emilylaguna emilylaguna added [Type] Bug Used for issues where something is not functioning as intended. Up Next issues related to the Up Next feature sync Issues related to sync between platforms labels Jan 21, 2023
@emilylaguna emilylaguna requested a review from a team as a code owner January 21, 2023 01:44
@emilylaguna emilylaguna changed the title Change how the up next queue Up Next Queue Syncing: Attempt to merge the local and remote device changes to prevent items from the queue being removed or cleared Jan 21, 2023
// to us, and we will attempt to merge the changes in the `applyServerChanges` call below
//
if ServerSettings.syncReason != .login {
// replace action
Copy link
Contributor Author

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

startSyncTimer()

// Persist the copy on the server immediately.
RefreshManager.shared.syncUpNext()
Copy link
Contributor Author

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.

@@ -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
Copy link
Contributor Author

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.

@emilylaguna emilylaguna added this to the 7.31 milestone Jan 21, 2023
Comment on lines +65 to +66
// 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.
Copy link
Contributor

@mchowning mchowning Jan 23, 2023

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 😬 ).

Copy link
Member

@leandroalonso leandroalonso left a 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.

Comment on lines 149 to 152
public enum SyncingReason: String {
case accountCreated
case login
}
Copy link
Member

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.

Copy link
Contributor Author

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.

@emilylaguna emilylaguna changed the base branch from trunk to release/7.31 January 24, 2023 00:31
@emilylaguna
Copy link
Contributor Author

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?

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.

If we start receiving complaints about those issues we might need to rethink this approach.

100% agree.

@emilylaguna emilylaguna merged commit f7e3cc4 into release/7.31 Jan 25, 2023
@emilylaguna emilylaguna deleted the issue/24-fix-up-next-queue-clearing branch January 25, 2023 00:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
sync Issues related to sync between platforms [Type] Bug Used for issues where something is not functioning as intended. Up Next issues related to the Up Next feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Up Next: Queue Emptied Unexpectedly
3 participants