Closed Bug 862385 Opened 11 years ago Closed 11 years ago

Cache contact names for the call log

Categories

(Firefox OS Graveyard :: Gaia::Dialer, defect, P2)

ARM
Gonk (Firefox OS)
defect

Tracking

(blocking-b2g:leo+, b2g18+ fixed, b2g-v1.1hd fixed)

RESOLVED FIXED
1.1 QE4 (15jul)
blocking-b2g leo+
Tracking Status
b2g18 + fixed
b2g-v1.1hd --- fixed

People

(Reporter: gwagner, Assigned: ferjm)

References

Details

(Keywords: perf, Whiteboard: u= c= , [u=commsapps-user c=dialer p=0])

Attachments

(1 file, 10 obsolete files)

With bug 847406 we see call log entries much quicker but the actual contact matching can take a long time depending on the size of the log.
We should cache the names or put them into the DB as well.
Blocks: 847406
Blocks a blocker, so leo?
Assignee: nobody → ferjmoreno
blocking-b2g: --- → leo?
blocking-b2g: leo? → leo+
Assignee: ferjmoreno → alberto.pastor
Assignee: alberto.pastor → ferjmoreno
Blocks: 847399
No longer blocks: 847406
OS: Mac OS X → Gonk (Firefox OS)
Hardware: x86 → ARM
Attached patch WIP (obsolete) — Splinter Review
Depends on: 879698
Attached patch wip (obsolete) — Splinter Review
Almost there...
Attachment #757909 - Attachment is obsolete: true
Attached patch WIP (obsolete) — Splinter Review
I still need to review and clean the patch, fix tests, add more tests, file bugs for the TODO comments and test some edge cases, but this patch contains most of what I'd like to have in the final patch. Etienne, could you start taking a look at it, please?

I am also asking f? to Alberto and German, since the patch is kind of risky and they are also familiar with this code.

Sorry for the huge patch :\...

Thanks!
Attachment #758668 - Attachment is obsolete: true
Attachment #759238 - Flags: feedback?(gtorodelvalle)
Attachment #759238 - Flags: feedback?(etienne)
Attachment #759238 - Flags: feedback?(alberto.pastor)
Comment on attachment 759238 [details] [diff] [review]
WIP

I am clearing the feedback flags cause I need to change the patch considerably.

With the current approach, while invalidating the contacts cache, we will show the old version of the cache until the sync with the contacts API data is done and the cache is properly updated. During that time, the user might click on an deleted contact triggering unexpected behaviors. I am afraid that we will need to query the Contacts API db while rendering (as we currently do) if we notice that the contacts cache is not valid. That way, we will always be showing valid information.

Sorry for the noise and the inconvenience. This code was needing some attention.
Attachment #759238 - Flags: feedback?(gtorodelvalle)
Attachment #759238 - Flags: feedback?(etienne)
Attachment #759238 - Flags: feedback?(alberto.pastor)
Keywords: perf
Whiteboard: c=
Attached patch wip (obsolete) — Splinter Review
Again, sorry for the huge patch.
Attachment #759238 - Attachment is obsolete: true
Attachment #760823 - Flags: feedback?(gtorodelvalle)
Attachment #760823 - Flags: feedback?(etienne)
Attached patch wip (obsolete) — Splinter Review
Attachment #760823 - Attachment is obsolete: true
Attachment #760823 - Flags: feedback?(gtorodelvalle)
Attachment #760823 - Flags: feedback?(etienne)
Attachment #761072 - Flags: feedback?(gtorodelvalle)
Attachment #761072 - Flags: feedback?(etienne)
No longer depends on: 879698
Status: NEW → ASSIGNED
Attached patch v1 (obsolete) — Splinter Review
Attachment #761072 - Attachment is obsolete: true
Attachment #761072 - Flags: feedback?(gtorodelvalle)
Attachment #761072 - Flags: feedback?(etienne)
Attachment #763470 - Flags: feedback?(etienne)
Whiteboard: c= → c= ,
Whiteboard: c= , → u=1.1 c= ,
Priority: -- → P2
No longer blocking a blocker.
blocking-b2g: leo+ → -
tracking-b2g18: --- → +
Whiteboard: u=1.1 c= , → u= c= ,
We decided to split the work required for bug 847406 to ease the review process and lower the regression risk, that's why we removed the dependency (1 month ago) but we kept working on this and didn't nominate it again for triage as we still considered this as a blocker for the performance improvements required for the call log.

As it is no longer possible to ask for approval for uplift to 1.1, I would like to ask you to reconsider this for leo+ again.

Please, note that apart from introducing the contacts cache for the call log, the attached patch fixes some other issues that would be hard and time consuming to identify and fix again.
blocking-b2g: - → leo?
needsinfo on mlee/:ferjm to understand if the performance improvements on contacts cache are in scope for 1.1  ?
Flags: needinfo?(mlee)
Triage - leaving as is waiting for mlee's response to make decision.
Comment on attachment 763470 [details] [diff] [review]
v1

Review of attachment 763470 [details] [diff] [review]:
-----------------------------------------------------------------

With the comments addressed we should be in good shape to start the review!
Given the size of the patch I think it's worth having both German and me as reviewers :)

::: apps/communications/dialer/js/call_log.js
@@ +51,5 @@
> +          });
> +          self._contactCache = false;
> +        } else {
> +          self._contactCache = true;
> +        }

will look better with 2 early returns :)

@@ +443,5 @@
> +    if (contact && contact.matchingTel) {
> +      var phoneNumberAdditionalInfo =
> +        Utils.getPhoneNumberAdditionalInfo(contact.matchingTel);
> +      if (phoneNumberAdditionalInfo && phoneNumberAdditionalInfo.length) {
> +        var additInfo = document.createElement('p');

nit -> |addInfo| looks better :)

@@ +689,5 @@
> +                                                    phoneNumbers, target) {
> +    var self = this;
> +
> +    // We need these aux functions to keep the correct references to the log
> +    // DOM element.

should'nt we make those methods on the CallLog singleton?

@@ +727,5 @@
>  
> +    function _removeContact(log, contactId, updateDb) {
> +      // If the cache is valid, we also need to remove the contact from the
> +      // cache
> +      if (CallLog._contactCache && updateDb) {

it won't look like you're accessing a private var on CallLog if _removeContact is a method on CallLog :)

@@ +755,5 @@
> +        logs = container.querySelectorAll('li[class="log-item"]');
> +        break;
> +    }
> +
> +    for (var i = 0, l = logs.length; i < l; i++) {

|l| is indeed better than |j| :)

@@ +780,5 @@
> +   * param matchingTel
> +   *        Object containing the phone number associated with the group of
> +   *        calls. It contains 'type', 'carrier' and 'value' parameters.
> +   *
> +   */

I think we could get some pretty decent coverage for this method (and we can probably focus on this one).

What to you think?

(I know it's dom-heavy but I think it's worth it.)

@@ +785,5 @@
> +  updateContactInfo: function cl_updateContactInfo(element, contact,
> +                                                   matchingTel) {
> +    var primInfoCont = element.getElementsByClassName('primary-info-main')[0];
> +    var contactPhoto = element.querySelector('.call-log-contact-photo');
> +    var additInfo = element.getElementsByClassName('call-additional-info');

same, `addInfo` or `addlInfo` (like the additional review on bugzilla :))

@@ +867,5 @@
> +  var options = {
> +    filterBy: ['id'],
> +    filterOp: 'equals',
> +    filterValue: event.contactID
> +  };

out of the scope of the patch, but I wonder if it would make sense to get the contact object back from the API on the event.

::: apps/communications/dialer/js/call_log_db.js
@@ +21,5 @@
> +
> +  /**
> +   * Add a observer of the 'upgradedone' event, which is fired as soon as we
> +   * push the latest upgraded record into the upgraded object stores.
> +   */

it may be a tiny bit overkill (since we don't have the use case for multiple observers).
but if we add unit-tests for it it's fine :)

@@ +69,5 @@
>        callback(null, this._db);
>        return;
>      }
>  
> +    LazyLoader.load(['/dialer/js/utils.js', '/dialer/js/contacts.js']);

note sure I get it... no callback?

@@ +367,5 @@
> +          groupCount++;
> +        }
> +        // Once we built all the group of calls we can push them to the
> +        // groups object store and notify the UI about it.
> +        if (cursorDone && !waitForAsyncCall) {

isn't it technically possible that the last contact request comes in before the last cursor onsuccess (where we set cursorDone to true)?

maybe we should extract this in a function and call it in each mozContact request callback _and_ in the last cursor tick.
since it will start with
```
if (!cursorDone || waitForAsyncCall) {
  return;
}
```
it won't cost much to be safe :)

@@ +715,5 @@
>     *                        error message if needed.
>     */
> +  _getList: function getList(storeName, callback, sortedBy, prev,
> +                             getCursor, limit) {
> +    if (!callback || !callback instanceof Function) {

idem, precedence question

@@ +954,5 @@
>                   function(error, txn, store) {
> +      if (error) {
> +        self._asyncReturn(callback, error);
> +        return;
> +      } else if (!contact) {

we're early returning just before, no need for the else

::: apps/communications/dialer/js/contacts.js
@@ +186,5 @@
>      };
>    },
>  
> +  _mergeFbContacts: function _mergeFbContacts(contacts, callback) {
> +    if (!callback || !callback instanceof Function) {

not sure, but I think |!| may have a higher precedence than |instanceof|.

Anyway, parenthesis probably won't hurt :)

@@ +201,5 @@
> +        if (fb.isFbLinked(contacts[i])) {
> +          var fbReq = fb.contacts.get(fb.getFriendUid(contacts[i]));
> +          fbReq.onsuccess = function() {
> +            contacts[i] = fb.mergeContact(contacts[i], fbReq.result);
> +            if (i === j - 1) {

yeah this one works, but parenthesis won't hurt either :)

@@ +209,5 @@
> +          fbReq.onerror = function() {
> +            console.error('Could not merge Facebook data');
> +            callback(contacts);
> +          };
> +        } else if (i === j - 1) {

same.

while nit picking, we could probably rename `j` into `length` or something like that.

::: apps/communications/dialer/js/utils.js
@@ +56,5 @@
> +   * phone number subject of the call consists in the type and carrier
> +   * associated with this phone number.
> +   *
> +   * Each call is associated with an *unique number* and this phone number can
> +   * belong to an specific contact(s). We don't care about the contact having

to n specific contact(s) maybe?
Attachment #763470 - Flags: feedback?(etienne) → feedback+
Triage- Agree to minus for now. Please renom when landed on Master and showing low or no risk for uplifting.
blocking-b2g: leo? → ---
(In reply to Fernando Jiménez Moreno [:ferjm] (needinfo instead of CC, please) from comment #11)
>
> ...
> 
> Please, note that apart from introducing the contacts cache for the call
> log, the attached patch fixes some other issues that would be hard and time
> consuming to identify and fix again.

Fernando,

What's the performance timing impact of not uplifting this patch to 1.1? How slow is the call log without your patch and how much improvement (in ms/s) do we see with it?

Also, what're the "other issues that would be hard and consuming to identify and fix"?
Flags: needinfo?(mlee) → needinfo?(ferjmoreno)
Thanks for the feedback Etienne! It'll take a few days more for me to have a new patch since this got leo-'ed and I have a few other leo+ to attend first.

(In reply to Mike Lee [:mlee] from comment #16)
> (In reply to Fernando Jiménez Moreno [:ferjm] (needinfo instead of CC,
> please) from comment #11)
> >
> > ...
> > 
> > Please, note that apart from introducing the contacts cache for the call
> > log, the attached patch fixes some other issues that would be hard and time
> > consuming to identify and fix again.
> 
> Fernando,
> 
> What's the performance timing impact of not uplifting this patch to 1.1? How
> slow is the call log without your patch and how much improvement (in ms/s)
> do we see with it?

Unfortunately, I don't have any numeric measures :(

Without this patch, the call log is rendered pretty fast thanks to bug 847406 *but* only the number list, once it is first rendered, the user can notice how the list is traversed to add the contact names (and other info like pictures) one by one. This makes scrolling slow if the call log is big and there are many contacts associated to the numbers in the list.

> Also, what're the "other issues that would be hard and consuming to identify
> and fix"?

I am afraid that I can't say the whole list of small (and not that small) issues that I found while working on this patch, but IIRC some of them were:

- The time of the calls were always 12:00
- Some use cases for contacts updates, like a contact deletion or a contact with different numbers which primary number is deleted that didn't trigger a proper call log update.
- The additional information were shown as ", <number>" instead of "<type>, <number> if there were no type associated to the number.

I don't know if any of these issues have already been fixed in other bugs though.

Sorry for not been able to write a more detailed list of issues, but this was supposed to be leo+ (it was for a month at least) as a complement of the complete call log rewrite for bug 847406. That's why I didn't filed separated bugs for these issues that I found on my way to fix this bug.

In any case, I'm ok with comment 15 and I'll work based on that :)
Flags: needinfo?(ferjmoreno)
Blocks: 889724
Attached patch v1 (obsolete) — Splinter Review
I've only rebased the patch. I'll be addressing Etienne's feedback next week.
Attachment #763470 - Attachment is obsolete: true
Attached patch v1 (obsolete) — Splinter Review
This patch should address Etienne's feedback.

I'd like to improve the tests for the call log UI (there were 0 before this patch :(...), but I really have not much time to enjoy that task right now, so I'll file another bug for it.

Sorry again for the 2.6K lines patch :(
Attachment #771610 - Attachment is obsolete: true
Attachment #772767 - Flags: review?(gtorodelvalle)
Attachment #772767 - Flags: review?(etienne)
Comment on attachment 772767 [details] [diff] [review]
v1

Review of attachment 772767 [details] [diff] [review]:
-----------------------------------------------------------------

Actually, I'd like to do a few more local testing before asking for a real review :) Sorry for the noise.
Attachment #772767 - Flags: review?(gtorodelvalle)
Attachment #772767 - Flags: review?(etienne)
Attached patch v1 (obsolete) — Splinter Review
Attachment #772767 - Attachment is obsolete: true
Attachment #773373 - Flags: review?(gtorodelvalle)
Attachment #773373 - Flags: review?(etienne)
Blocking a blocker, again.
blocking-b2g: --- → leo?
Based on erroneous testing, we've flipped to minus on bug 889724.

So minusing this one for now.

Given the test scenario and 1.5s requirement on bug 889724, can you please test with 250 calls, and ensure load time is under 1.5s?

If it's greater than 1.5s, please renominate this bug for blocking. Thanks!
blocking-b2g: leo? → -
Blocking a leo+ blocker. Set to leo+
blocking-b2g: leo? → leo+
Whiteboard: u= c= , → [u=commsapps-user c=dialer p=0] ,u= c=
Whiteboard: [u=commsapps-user c=dialer p=0] ,u= c= → u= c= , [u=commsapps-user c=dialer p=0]
Comment on attachment 773373 [details] [diff] [review]
v1

Review of attachment 773373 [details] [diff] [review]:
-----------------------------------------------------------------

Boom, when the call log goes boom,
everything is here, boom,
no weird rendering glitches...

To the tune of: http://www.youtube.com/watch?v=dYzEOaqazdM#t=00m17s

r=me with the "upgrading" label and the unit tests nits.
Great great work!

I played with it a lot and didn't find any issue.
Wasn't set up to go through the bluetooth redial scenario though, but we could mitigate this by adding a test for the getLastCall method ;)

::: apps/communications/dialer/js/call_log.js
@@ +112,5 @@
> +
> +    // Listen for database upgrade events.
> +    CallLogDBManager.onupgradeneeded = function onupgradeneeded() {
> +      // TODO: Show UI letting the user know that the database is being
> +      //       upgraded or whatever. Bug XXXXXX

After testing it a bit, I think it's worth displaying a simple "upgrading..." string for this patch.

::: apps/communications/dialer/js/call_log_db.js
@@ +984,5 @@
> +   *        needed.
> +   *
> +   * return (via callback) the last call or an error message if needed.
> +   */
> +  getLastCall: function getLastCall(callback) {

looks like we don't have tests for this method.

::: apps/communications/dialer/test/unit/calllog_test.js
@@ +19,5 @@
> +      get: function get(cb) {
> +        cb(function l10n_get(key) {
> +          return key;
> +        });
> +      }

note: we actually already have a mock ready for LazyL10n.
Attachment #773373 - Flags: review?(etienne) → review+
(In reply to Etienne Segonzac (:etienne) from comment #27)
> Comment on attachment 773373 [details] [diff] [review]
> v1
> 
> Review of attachment 773373 [details] [diff] [review]:
> -----------------------------------------------------------------
> 
> Boom, when the call log goes boom,
> everything is here, boom,
> no weird rendering glitches...
> 
> To the tune of: http://www.youtube.com/watch?v=dYzEOaqazdM#t=00m17s

lol :D

> 
> r=me with the "upgrading" label and the unit tests nits.
> Great great work!
> 

Thanks! :)

> I played with it a lot and didn't find any issue.
> Wasn't set up to go through the bluetooth redial scenario though, but we
> could mitigate this by adding a test for the getLastCall method ;)
> 
> ::: apps/communications/dialer/js/call_log.js
> @@ +112,5 @@
> > +
> > +    // Listen for database upgrade events.
> > +    CallLogDBManager.onupgradeneeded = function onupgradeneeded() {
> > +      // TODO: Show UI letting the user know that the database is being
> > +      //       upgraded or whatever. Bug XXXXXX
> 
> After testing it a bit, I think it's worth displaying a simple
> "upgrading..." string for this patch.
> 

I'm not sure that adding a new string to v1-train is still allowed :(... Axel, is it still possible?
Flags: needinfo?(l10n)
Please ask triage about schedule and approvals, https://groups.google.com/forum/#!topic/mozilla.dev.gaia/_T_BTvJ4fJk.

That said, we're way past string-freeze.
Flags: needinfo?(l10n)
(In reply to Axel Hecht [:Pike] from comment #29)
> Please ask triage about schedule and approvals,
> https://groups.google.com/forum/#!topic/mozilla.dev.gaia/_T_BTvJ4fJk.
> 

This bug already has the leo+ approval.

> That said, we're way past string-freeze.

I'll take that as a "no".
Attached patch v2 (obsolete) — Splinter Review
This patch includes the tests suggestions and a progress bar for the upgrade process that includes a percentage so we avoid adding new strings.
Attachment #773373 - Attachment is obsolete: true
Attachment #773373 - Flags: review?(gtorodelvalle)
Attachment #776499 - Flags: review?(gtorodelvalle)
Attachment #776499 - Flags: review?(etienne)
Target Milestone: --- → 1.1 QE4 (15jul)
Comment on attachment 776499 [details] [diff] [review]
v2

\o/
Attachment #776499 - Flags: review?(etienne) → review+
Hi guys! Sorry for the delay, many bugs in the oven :-p

OK, I think I found a misbehavior which may be related to this bug and more concretely to call_log.js's updateContactInfo(). I cannot assure it since we may had it from the past. To reproduce it:
1.- Have or create a contact for a phone number you may be able to call your DuT back to. Let's say 666666666.
1.- With no entries in the the Call Log (at least that was my case), from the DuT make an outgoing call to 666666666.
2.- Make a couple of calls from 666666666 to the DuT. At this point you'll have 2 entries in your Call Log with contacts associated: 1 including the 2 incoming (missed in my case) calls and 1 including the outgoing call.
3. Delete the contact.
Expected result:
  - The entries in the Call Log have no contact associated but maintain the number of calls in the group, this is (2) for the incoming (missed) calls.
Observed result:
  - The entries in the Call Log have no contact associated but the number of calls in the group is lost. No (2) in the third row of the group including the 2 incoming (missed) calls just made.

BTW, updating the contact seems to work fine. For example, deleting the image in case it had one.

Do you reproduce it, Fernando? Has it something to do with your patch? Thanks!
Flags: needinfo?(ferjmoreno)
Attached patch v3Splinter Review
Thanks Germán! Nice catch!
Attachment #776499 - Attachment is obsolete: true
Attachment #776499 - Flags: review?(gtorodelvalle)
Attachment #777675 - Flags: review?(gtorodelvalle)
Flags: needinfo?(ferjmoreno)
Comment on attachment 777675 [details] [diff] [review]
v3

r=etienne from comment 32
Attachment #777675 - Flags: review+
Comment on attachment 777675 [details] [diff] [review]
v3

If this is the same patch you sent to me via Skype, I r+ it after testing that the previous problem is solved and everything seems to work just fine... Although bug will come... :-p Thanks Fernando! Awesome patch! ;-)
Attachment #777675 - Flags: review?(gtorodelvalle) → review+
Thanks Germán!

https://github.com/mozilla-b2g/gaia/commit/fc7a7cd5a593bea612706eee9449400374da4b39
Status: ASSIGNED → RESOLVED
Closed: 11 years ago
Resolution: --- → FIXED
I was not able to uplift this bug to v1-train.  If this bug has dependencies which are not marked in this bug, please comment on this bug.  If this bug depends on patches that aren't approved for v1-train, we need to re-evaluate the approval.  Otherwise, if this is just a merge conflict, you might be able to resolve it with:

  git checkout v1-train
  git cherry-pick -x  fc7a7cd5a593bea612706eee9449400374da4b39
  <RESOLVE MERGE CONFLICTS>
  git commit
Flags: needinfo?(ferjmoreno)
v1.1.0hd: 41d10fb10be6916e6554eb440d9a97130ef23ce0
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: