Closed Bug 1350442 Opened 7 years ago Closed 7 years ago

Desktop bookmark is not syncing on Android mobile on Aurora 54

Categories

(Firefox for Android Graveyard :: Android Sync, defect, P1)

Firefox 54
defect

Tracking

(firefox52 unaffected, firefox53+ unaffected, firefox54+ verified, firefox55+ verified)

VERIFIED FIXED
Firefox 55
Tracking Status
firefox52 --- unaffected
firefox53 + unaffected
firefox54 + verified
firefox55 + verified

People

(Reporter: kkumari, Assigned: Grisha)

References

Details

Attachments

(6 files)

STR:
1. Launch 54.0a2 (Build ID 	20170324004022)
2. Sign in to Sync with a new or existing Firefox Account on Windows desktop
3. Add a bookmark
4. Trigger sync
5. Sign in to Sync with same Firefox Account on Android mobile
5. Wait for sync to be finish

Expected: Bookmarks from Desktop should appear in Desktop folder on Android mobile

Actual: Desktop bookmark is not on Android mobile on Aurora 54

Note: Bookmarks are syncing properly in following scenarios:
1. From Android to Desktop
2. Desktop to ios
3. Across Desktop platforms (Windows, Linux, Mac)
4. On Nightly channels (Syncing properly from Desktop to Android mobile)
Ouch, that's not good. None of the desktop bookmarks sync to Android 54? Grisha, can you think of anything that might have caused this?
Flags: needinfo?(gkruglov)
No none of them are syncing. I performed this test with fresh profile and new Fx account, so I have only a few bookmarks. I am adding bookmark one by one on Desktop, syncing and verifying on Android mobile.  It's syncing perfectly fine from Android mobile to Desktop or on nightly channel. Essentially, I encountered this issue in process of Mobile bookmark folder (on Desktop) testing:)
Update: I'm getting the mentioned behavior on Nightly as well. My changes from Android to Desktop are synced correctly, but my 
 latest changes on Desktop to Android are not synced.
Changing tracking flag based on comment 3.
Looking into it. Could you attach android device logs while sync is in progress? Dump of `adb logcat` should be sufficient.
Flags: needinfo?(gkruglov) → needinfo?(kkumari)
Attached file nexuxlog
Hope this helps.
Assignee: nobody → kkumari
Flags: needinfo?(kkumari)
Attached file Logfile
What I'm seeing locally:
- desktop changes to bookmarks _are_ downloaded (i see new and changed bookmarks flow through the buffering middleware), but don't seem to be applied. Perhaps something is off with the buffer application logic. If that's the case, we should see the same problem for every collection (excluding history)
- the first log file above seems to indicate that no changes are present on the server. The second log file doesn't cover actual sync unfortunately

I'm going to take a better look at what's going on, something is certainly amiss here.
Component: Sync → Android Sync
Product: Firefox → Android Background Services
Version: 54 Branch → Firefox 54
Assignee: kkumari → gkruglov
Status: NEW → ASSIGNED
Priority: -- → P1
Well, this is frustrating. As I suspected, we're simply not calling the right storeDone method on the BookmarksSession - or rather, not overriding the right storeDone method if one looks at it the other way around. The upside is that the patch is very simple.
This wasn't caught by any of the tests we have for this code, because for the most part they use mock repositories and mock sessions when testing how various bits glue together, and so tests will take a bit more effort to write.

Neither was this caught by my evidently rather insufficient manual testing :-(

At the very least, here's a patch which fixes this issue for me locally and can be easily uplifted to 54.
A better patch is to kill off storeDone(long end) method entirely and simplify a few things. Sessions often build up buffers which they need to flush on this call, and so passing in a timestamp doesn't make sense in a lot of cases.
I can reproduce this with Beta 53b7. With Beta on Desktop as well as Android.
Can you describe in more details what you're seeing, and confirm that you're seeing it specifically on Firefox for Android 53?
- changing/adding bookmarks on desktop isn't reflected on android?
- changing/adding bookmarks on android isn't reflected on desktop?
- something else..?
Flags: needinfo?(gwimberly)
Comment on attachment 8852318 [details]
Bug 1350442 - Remove redundant storeDone from the RepositorySession class

https://reviewboard.mozilla.org/r/124572/#review127828

It seems that a simpler and safer solution is to remove `storeDone()`, ensuring that `storeDone(long)` implements the same behavior, and replace the three uses of the no-argument form in the codebase with uses of `storeDone(long)`, no?

I'm particularly disquieted by the idea of potentially screwing up completion scheduling.

::: commit-message-272ce:4
(Diff revision 2)
> +Bug 1350442 - Remove redundant storeDone from the RepositorySession class r=rnewman
> +
> +Confusion between storeDone() and storeDone(long end) resulted in certain sessions (bookmarks
> +and form history) not overriding the corrent method. As a result, their final "flush the queue"

s/corrent/current

::: mobile/android/services/src/main/java/org/mozilla/gecko/sync/repositories/RepositorySession.java:135
(Diff revision 2)
> -    storeDone(now());
> -  }
> +    // Sessions may override this behaviour if the above assumption is incorrect.
> +    // For example, a session may choose to built up buffers which will need to be flushed in

s/built/build

I'm totally fine with using US or international English throughout a codebase, but ideally not in the same comment, so please use 'behavior' here.

::: mobile/android/services/src/main/java/org/mozilla/gecko/sync/repositories/RepositorySession.java:139
(Diff revision 2)
>      // our end timestamp can just be… now.
> -    storeDone(now());
> -  }
> -
> -  public void storeDone(final long end) {
> +    // Sessions may override this behaviour if the above assumption is incorrect.
> +    // For example, a session may choose to built up buffers which will need to be flushed in
> +    // storeDone, and so it will need to call onStoreComplete with the end timestamp after those
> +    // operations complete.
> +    final long end = System.currentTimeMillis();

Use `now()`.

::: mobile/android/services/src/main/java/org/mozilla/gecko/sync/repositories/android/AndroidBrowserHistoryRepositorySession.java:223
(Diff revision 2)
>              flushNewRecords();
>            } catch (Exception e) {
>              Logger.warn(LOG_TAG, "Error flushing records to database.", e);
>            }
>          }
> -        AndroidBrowserHistoryRepositorySession.super.storeDone(end);
> +        storeDelegate.onStoreCompleted(now());

Same.

::: mobile/android/services/src/main/java/org/mozilla/gecko/sync/repositories/uploaders/BatchingUploader.java:214
(Diff revision 2)
> +    /**
> +     * Must be called on the {@link this#executor }.
> +     * In the current implementation, this call only happens from the PayloadDispatcher.
> +     */
>      /* package-local */ void finished(AtomicLong lastModifiedTimestamp) {
> -        repositorySession.storeDone(lastModifiedTimestamp.get());
> +        sessionStoreDelegate.onStoreCompleted(lastModifiedTimestamp.get());

I have a really hard time thinking this is correct. Consider the definition of `RepositorySession.storeDone(long)`:

```java
138-  public void storeDone(final long end) {
139:    Logger.debug(LOG_TAG, "Scheduling onStoreCompleted for after storing is done: " + end);
140-    Runnable command = new Runnable() {
141-      @Override
142-      public void run() {
143:        storeDelegate.onStoreCompleted(end);
144-      }
145-    };
146-    storeWorkQueue.execute(command);
147-  }
```

`session.storeDone` and `delegate.onStoreCompleted` are *not* interchangeable.
Attachment #8852318 - Flags: review?(rnewman) → review-
Comment on attachment 8852318 [details]
Bug 1350442 - Remove redundant storeDone from the RepositorySession class

https://reviewboard.mozilla.org/r/124572/#review127918

::: mobile/android/services/src/main/java/org/mozilla/gecko/sync/repositories/uploaders/BatchingUploader.java:214
(Diff revision 2)
> +    /**
> +     * Must be called on the {@link this#executor }.
> +     * In the current implementation, this call only happens from the PayloadDispatcher.
> +     */
>      /* package-local */ void finished(AtomicLong lastModifiedTimestamp) {
> -        repositorySession.storeDone(lastModifiedTimestamp.get());
> +        sessionStoreDelegate.onStoreCompleted(lastModifiedTimestamp.get());

Well. It's _doing_ the same thing, no? We run runnables on `storeWorkQueue`, which is a single thread executor. This change avoids posting another runnable to the executor, instead performing `onStoreCompleted` at the tail end of the final "store" runnable. This `finished` method is only ever called from the tasks running on the `storeWorkQueue`.
Comment on attachment 8852318 [details]
Bug 1350442 - Remove redundant storeDone from the RepositorySession class

https://reviewboard.mozilla.org/r/124572/#review127918

> Well. It's _doing_ the same thing, no? We run runnables on `storeWorkQueue`, which is a single thread executor. This change avoids posting another runnable to the executor, instead performing `onStoreCompleted` at the tail end of the final "store" runnable. This `finished` method is only ever called from the tasks running on the `storeWorkQueue`.

The point of the runnable post is to make sure it's the last thing to run. Are you 100% confident that `finished` is always the last runnable to run? A quick skim suggests we call finished <- lastPayloadFailed <- handleRequestError; I haven't checked where our request handling occurs…
Comment on attachment 8852318 [details]
Bug 1350442 - Remove redundant storeDone from the RepositorySession class

https://reviewboard.mozilla.org/r/124572/#review127918

> The point of the runnable post is to make sure it's the last thing to run. Are you 100% confident that `finished` is always the last runnable to run? A quick skim suggests we call finished <- lastPayloadFailed <- handleRequestError; I haven't checked where our request handling occurs…

Also runnables are really really cheap, particularly if we're already the last item on the same queue. I'm not sure it's worth trying to optimize out a runnable if there's _any_ loss of regularity or risk of miscomprehension, which is why I suggested what I feel is a less risky approach: use the existing adjacent, more explicit code path and remove the problematic one.
(In reply to :Grisha Kruglov from comment #15)
> Can you describe in more details what you're seeing, and confirm that you're
> seeing it specifically on Firefox for Android 53?
> - changing/adding bookmarks on desktop isn't reflected on android?
> - changing/adding bookmarks on android isn't reflected on desktop?
> - something else..?

It syncs from Mobile to Desktop.
It does not sync from Desktop to Mobile.

Apologies for the lack of clarification.
Flags: needinfo?(gwimberly)
Comment on attachment 8852318 [details]
Bug 1350442 - Remove redundant storeDone from the RepositorySession class

https://reviewboard.mozilla.org/r/124572/#review127828

Rehashing what I've said on IRC: While I don't feel strongly about this (of course!), I do think the current approach is a little cleaner (no need to call `super` implementations of the methods), and embraces the fact that the completion timestamp might be dictated by the session itself (see the commit comment...) - which of course could be achieved either way...

I've switched to calling onStoreCompleted via deferred delegates, which should ensure our scheduling is the same as before. While we don't actually use these timestamps for anything at the moment, they will be used as part of sync ping.

Anyway, let me know if you feel that this change could actually change something about the ordering of things.

> I have a really hard time thinking this is correct. Consider the definition of `RepositorySession.storeDone(long)`:
> 
> ```java
> 138-  public void storeDone(final long end) {
> 139:    Logger.debug(LOG_TAG, "Scheduling onStoreCompleted for after storing is done: " + end);
> 140-    Runnable command = new Runnable() {
> 141-      @Override
> 142-      public void run() {
> 143:        storeDelegate.onStoreCompleted(end);
> 144-      }
> 145-    };
> 146-    storeWorkQueue.execute(command);
> 147-  }
> ```
> 
> `session.storeDone` and `delegate.onStoreCompleted` are *not* interchangeable.

Using deferred delegate now, which posts a runnable, which should achieve the same goal.
(In reply to Grover Wimberly IV [:Grover-QA] from comment #20)
> It syncs from Mobile to Desktop.
> It does not sync from Desktop to Mobile.

This is a different issue from what the patch above is addressing (since that's a regression in 54, and you're talking about 53). Could you please upload logs while the device is syncing? Output of `adb logcat` should be fine, but in case that's too noisy due to your device, you can filter it: `adb logcat | grep FxAccounts`
Flags: needinfo?(gwimberly)
(In reply to :Grisha Kruglov from comment #23)
> Output of `adb logcat` should be
> fine, but in case that's too noisy due to your device, you can filter it:
> `adb logcat | grep FxAccounts`

Actually, a better filter would be: adb logcat | grep "FxAccounts\|GeckoLogger"
What I've posted initially might omit a bunch of stuff.
Does this mean bookmarks aren't syncing for 53? That may make this a release blocker. 
Andrei, can your team give this some extra testing for 53 if we still aren't sure?
Flags: needinfo?(gkruglov)
Flags: needinfo?(andrei.vaida)
See Also: → 1349450
Attached file Logcat File
Tried again today and it seems to have synced fine. Attached is the logcat file just in case.
Flags: needinfo?(gwimberly)
I expect 54+ to have problems (hence the patch for this bug), but not 53. There were significant changes in 54 and we're seeing those regressions now, but IIRC nothing in 53 changed for sync (batching uploads landed in 51, batching downloads in 52).
Flags: needinfo?(gkruglov)
Comment on attachment 8852318 [details]
Bug 1350442 - Remove redundant storeDone from the RepositorySession class

https://reviewboard.mozilla.org/r/124572/#review128778

::: mobile/android/services/src/main/java/org/mozilla/gecko/sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java:979
(Diff revision 3)
>        @Override
>        public void run() {
>          try {
>            finishUp();
>          } finally {
> -          AndroidBrowserBookmarksRepositorySession.super.storeDone();
> +          storeDelegate.deferredStoreDelegate(storeWorkQueue).onStoreCompleted(now());

I'm slightly worried about

```
  public RepositorySessionFetchRecordsDelegate deferredFetchDelegate(ExecutorService newExecutor) {
    if (newExecutor == executor) {
      return this;
    }
    throw new IllegalArgumentException("Can't re-defer this delegate.");
  }

```

— that is, we rely on `storeDelegate.deferredStoreDelegate` always being called with the same `ExecutorService` everywhere. Please convince yourself that this is true.
Attachment #8852318 - Flags: review?(rnewman) → review+
Comment on attachment 8852318 [details]
Bug 1350442 - Remove redundant storeDone from the RepositorySession class

https://reviewboard.mozilla.org/r/124572/#review128778

> I'm slightly worried about
> 
> ```
>   public RepositorySessionFetchRecordsDelegate deferredFetchDelegate(ExecutorService newExecutor) {
>     if (newExecutor == executor) {
>       return this;
>     }
>     throw new IllegalArgumentException("Can't re-defer this delegate.");
>   }
> 
> ```
> 
> — that is, we rely on `storeDelegate.deferredStoreDelegate` always being called with the same `ExecutorService` everywhere. Please convince yourself that this is true.

I went through what I think were all of the uses, and all of them seem to use the same `ExecutorService`. Except for the Buffering middleware, which actually created its own queue for use in a very narrow case. See another patch which fixes that.
Comment on attachment 8854592 [details]
Bug 1350442 - Use the main storeWorkQueue for failures in the buffering middleware

https://reviewboard.mozilla.org/r/126548/#review129092
Attachment #8854592 - Flags: review?(rnewman) → review+
Pushed by gkruglov@mozilla.com:
https://hg.mozilla.org/integration/autoland/rev/75f204b4d7d3
Use the main storeWorkQueue for failures in the buffering middleware r=rnewman
https://hg.mozilla.org/integration/autoland/rev/45aae5dc504b
Remove redundant storeDone from the RepositorySession class r=rnewman
https://hg.mozilla.org/mozilla-central/rev/75f204b4d7d3
https://hg.mozilla.org/mozilla-central/rev/45aae5dc504b
Status: ASSIGNED → RESOLVED
Closed: 7 years ago
Resolution: --- → FIXED
Target Milestone: --- → Firefox 55
[Feature/Bug causing the regression]: Bug 1291821, landed in 54.

[User impact if declined]: Changes to bookmarks made on desktop are not reflected in fennec.

[Is this code covered by automated tests?]: Yes

[Has the fix been verified in Nightly?]: Not yet; just landed on m-c at the time of writing.

[Needs manual test from QE? If yes, steps to reproduce]: Yes. Ensure that bookmark sync works both ways, fennec>desktop and desktop>fennec. This includes any changes to individual bookmarks or folders.

[List of other uplifts needed for the feature/fix]: n/a

[Is the change risky?]: Not really.

[Why is the change risky/not risky?]: Simple change; it reduces number of possible code paths, removing a problematic one. Execution ordering or flow of data should not have changed.

[String changes made/needed]: N/A.
Attachment #8855003 - Flags: approval-mozilla-aurora?
Hi Kanchan,
Can you help verify if this is fixed as expected in a latest nightly?
Flags: needinfo?(kkumari)
I tested this bug on the latest nightly (Build ID 20170406030206) and found it to be working fine.
Status: RESOLVED → VERIFIED
Flags: needinfo?(kkumari)
Comment on attachment 8855003 [details] [diff] [review]
desktop-bookmarks-sync-aurora.patch

Fix an issue that desktop bookmark is not syncing on Android mobile and was verified. Aurora54+.
Attachment #8855003 - Flags: approval-mozilla-aurora? → approval-mozilla-aurora+
Bookmark syncing from Desktop to Mobile is working fine on Aurora 54.0a2 (Build ID 20170407004017)
Flags: needinfo?(andrei.vaida)
Product: Android Background Services → Firefox for Android
Product: Firefox for Android → Firefox for Android Graveyard
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: