Closed Bug 1141850 Opened 10 years ago Closed 9 years ago

Implement synchronization for structured cross-device records (bookmarks)

Categories

(Firefox for iOS :: Sync, defect)

All
iOS
defect
Not set
normal

Tracking

()

RESOLVED FIXED
Tracking Status
fxios 3.0+ ---

People

(Reporter: rnewman, Assigned: rnewman)

References

(Blocks 1 open bug)

Details

Attachments

(2 files)

48 bytes, text/x-github-pull-request
nalexander
: review+
bnicholson
: review+
fluffyemily
: review+
Details | Review
26.66 KB, application/zip
Details
Basically this means "bookmarks". These records are unique in that they normally cannot be independently added to, modified, or deleted; even deleting or reordering a leaf bookmark requires modifying its parent record and atomically applying that change. Moves require modifying three records. And so on. This is a complication in two areas of iOS Sync: 1. Our judgment about when the server mirror can be applied -- that is, our assessment of whether it is *complete* (fully downloaded) and *consistent* (=> fully uploaded by another client) becomes important and non-trivial. 2. Record reconciling is a structural operation. Desktop uses a computed map for this; it would be unwise to follow the same approach. The difficulty of correctly handling local changes here is enough motivation that we might use a replayable transaction log to limit the possibility of hard-to-resolve conflicts. I intend to solve this problem last, and very likely in stages of limited scope (e.g., read-only server bookmarks, unsorted list of local bookmarks that are easy to reconcile). Decisions elsewhere have made that kind of decomposition difficult -- e.g., desktop's "Unsorted bookmarks" aren't unsorted and can contain folders! -- but we'll do the best we can.
Depends on: 1201110
Assignee: nobody → rnewman
Status: NEW → ASSIGNED
Depends on: 1201104, 1201103, 1201108
OS: iOS 8 → iOS
Blocks: 1196238
Here's the raw work stream. Careful, it's big. It works, and it has tests. https://github.com/mozilla/firefox-ios/compare/rnewman/bm-merge-review?expand=1 I'm flattening this into a more manageable (hah!) set of commits in a separate branch; that's the PR I'll submit for review.
My existing to-do list: * Make sure we set a parentName when inserting new bookmarks. This isn't ordinarily an issue, because we'll override the stored parentName when it's a special folder. * Multi-part upload timestamps are utterly wrong: every uploaded record gets the timestamp of the last part. This is non-trivial. * We batch uploads in chunks of 50. Often this is too small, and sometimes it's too large. We should use size-based upload. * Outgoing invalid records -- that is, serialization failures into BookmarkBasePayload -- don't seem to abort the sync. Quietly dropping those records on the floor is wrong. * Don't try a merge if the mirrorer aborts. * Test multi-depth folder deletion. * Test moving between roots. * Implement true three-way merge for values, and see if there's anything more we can do for folders. * In a value-based reconcile lookup, do we/should we limit the search to New local items? * My logs tell me that we sometimes prefetch duplicates in the same request (A, A, B, B). Why? * Make sure that prefetching never does redundant work. * Make sure we prefetch as much as we might need. * Check code for TODOs. * Make sure we have all the indices we need.
Attached file Pull req.
Believe it or not, this is the flattened one.
Attachment #8721110 - Flags: review?(sleroux)
Attachment #8721110 - Flags: review?(nalexander)
Attachment #8721110 - Flags: review?(etoop)
Attachment #8721110 - Flags: review?(bnicholson)
(In reply to Richard Newman [:rnewman] from comment #3) > * Multi-part upload timestamps are utterly wrong: every uploaded record gets > the timestamp of the last part. This is non-trivial. Consequence: should be none of note, but it makes me uneasy, so we should fix it. > * We batch uploads in chunks of 50. Often this is too small, and sometimes > it's too large. We should use size-based upload. Consequence: uploading a very large record, or a certain combination of large records, will cause the upload to fail and your bookmarks to never sync. That's not good. > * Outgoing invalid records -- that is, serialization failures into > BookmarkBasePayload -- don't seem to abort the sync. Quietly dropping those > records on the floor is wrong. Consequence: potential missing records on the server, propagating inconsistency. Not good. Most of the others are improvements or perf. These I'd want to fix before shipping.
(In reply to Richard Newman [:rnewman] from comment #3) > My existing to-do list: One more: * Handling detected wipes and storage format changes in BookmarksDownloader.
> * Multi-part upload timestamps are utterly wrong: every uploaded record gets > the timestamp of the last part. This is non-trivial. Done (but not tested; I'm on a plane) in Part 7. We accrue timestamps directly into the local completion op, and can replay them into the mirror once the uploads are done.
Performance: download + merge + upload on ~1600 bookmarks takes 9 seconds on my 6S. Download alone takes 5 seconds. In this case about 300msec went on upload. I'm happy with that. I expect a fair amount of the time goes to logging, which we can ramp down over time.
Attached file Logs.zip
I'm sorry, but this doesn't seem to work for me. First I just deployed this version overriding my existing dev version that had no account attached at that time. added my account and waited for sync (which took a really tiny amount of time). I did not see either my dekstop bookmarks or see my mobile bookmarks on desktop. I also did not see my history synced over. I then deleted my app and tried from a fresh install. This is the log I'm attaching here. I added 3 sites to my bookmarks (bbc.co.uk, slashdot.org & theguardian.co.uk), then connected my FxA. Again, after a super quick sync time, I see my synced tabs, but no desktop history or bookmarks synced over.
Blocks: 1251306
Comment on attachment 8721110 [details] [review] Pull req. As a reviewer I tend to review such that I can address issues that may arise. In this case, I don't think that's possible -- it's rnewman in the next two months, and after that nobody.
Attachment #8721110 - Flags: review?(nalexander) → review+
(In reply to Emily Toop (:fluffyemily) from comment #9) > I then deleted my app and tried from a fresh install. This is the log I'm > attaching here. I added 3 sites to my bookmarks (bbc.co.uk, slashdot.org & > theguardian.co.uk), then connected my FxA. Again, after a super quick sync > time, I see my synced tabs, but no desktop history or bookmarks synced over. It synced (in 600msec!), but your bookmarks weren't consistent. 13:39:19.141 [BookmarksDownloader.swift:93] go(_:greenLight:) > Downloading up to 100 records. 13:39:19.142 [Downloader.swift:127] go(_:limit:) > Modified: 1455796035270; last 0. 13:39:19.143 [Downloader.swift:152] downloadNextBatchWithLimit(_:infoModified:) > Fetching newer=0, offset=nil. 13:39:19.145 [StorageClient.swift:699] getSince(_:sort:limit:offset:) > Issuing GET with newer = 0. 13:39:19.497 [StorageClient.swift:330] failFromResponse > Status code: 200. 13:39:19.670 [Downloader.swift:170] handleSuccess > Handling success. 13:39:19.673 [Downloader.swift:204] handleSuccess > Got success response with Optional(83) records. 13:39:19.674 [BookmarksDownloader.swift:102] go(_:greenLight:) > Done with batched mirroring. 13:39:19.701 [BookmarksDownloader.swift:83] applyRecordsFromBatcher() > Applying 83 downloaded bookmarks. 13:39:19.740 [SQLiteBookmarksSyncing.swift:469] applyRecords(_:withMaxVars:) > 9 folders and 15 deleted maybe-folders to drop from buffer structure table. 13:39:19.740 [SQLiteBookmarksSyncing.swift:344] deleteStructureForGUIDs(_:fromTable:connection:withMaxVars:) > Deleting 24 parents from bookmarksBufferStructure. 13:39:19.741 [SQLiteBookmarksSyncing.swift:477] applyRecords(_:withMaxVars:) > Inserting 62 children. 13:39:19.742 [SQLiteBookmarksSyncing.swift:372] insertStructureIntoTable(_:connection:children:maxVars:) > Inserting 62 records (out of 62). 13:39:19.753 [Downloader.swift:187] handleSuccess > Advancing baseTimestamp to 1455796035270 - 1 13:39:19.755 [Downloader.swift:199] handleSuccess > Advancing lastModified to Optional(1455796035270) ?? 1455796035270. 13:39:19.757 [BrowserDB.swift:287] checkpoint() > Checkpointing a BrowserDB. 13:39:19.757 [SwiftData.swift:531] checkpoint > Running WAL checkpoint on /private/var/mobile/Containers/Shared/AppGroup/AFDA9BA5-C0A9-4EFA-8A3E-DE82F9B7FBEA/profile.profile/browser.db on thread <NSThread: 0x14865e5a0>{number = 10, name = (null)}. 13:39:19.758 [SwiftData.swift:533] checkpoint > WAL checkpoint done on /private/var/mobile/Containers/Shared/AppGroup/AFDA9BA5-C0A9-4EFA-8A3E-DE82F9B7FBEA/profile.profile/browser.db. 13:39:19.781 [ThreeWayTreeMerger.swift:994] produceMergedTree() > Remote bookmarks not fully rooted when overlayed on mirror. Partial read or write in buffer? 13:39:19.782 [BookmarksSynchronizer.swift:124] synchronizeBookmarksToStorage(_:usingBuffer:withServer:info:greenLight:) > Bookmark sync took 644118µs. But fallback mode behaves correctly: <fluffyemily> rnewman: you'll be happy to know that once that crasher is removed, my bookmarks behave as expected (in fallback readonly mode)
Attachment #8721110 - Flags: review?(etoop) → review+
09b923a
Status: ASSIGNED → RESOLVED
Closed: 9 years ago
Resolution: --- → FIXED
Target Milestone: --- → 3.0
Comment on attachment 8721110 [details] [review] Pull req. Only reviewed (or more accurately, skimmed) 1/3rd of the PR, but finally tried syncing my account and it works flawlessly. Excellent job!
Attachment #8721110 - Flags: review?(bnicholson) → review+
Attachment #8721110 - Flags: review?(sleroux)
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: