Skip to content

Conversation

timmyc
Copy link
Contributor

@timmyc timmyc commented Dec 30, 2016

Fixes #9529

Today @jblz did some troubleshooting with his local state tree that was causing calypso to crash in Chrome. At the end of the troubleshooting, he discovered the issue to be caused by a massive array in the statsStreak data that was persisted in indexDB.

A screen grab of the malformed data in Jeff's persisted state tree:

screen_shot_2016-12-29_at_1_10_47_pm_png_and_stats__prevent___merge_from_crashing_reducer__by_timmyc_ _pull_request__10326_ _automattic_wp-calypso

Steps to Recreate

  • Visit a stats insights page, and note the site.ID for the site you are using
  • Then using the site.ID enter the following in the console, this simulates the same massive array we saw in Jeff's indexDB
// for site.ID of 121720032
var badArray = new Array(121720032);
// set the site.ID - 1 element to 1
badArray[121720031] = 1;
indexedDB.open('calypso').onsuccess = (e) => { 
	const db = e.target.result; const transaction = db.transaction( 'calypso_store', "readwrite" );
	const store = transaction.objectStore( 'calypso_store' ); store.get( 'redux-state' ).onsuccess = (ee) => { 
		const state = ee.target.result;
		state.stats.lists.items['121720032'].statsStreak['[["endDate","2016-12-31"],["gmtOffset",0],["max",3000],["startDate","2015-12-01"]]'].data = badArray;
		store.put( state, 'redux-state' );
	};
};
  • Refresh the insights page, and wait for the 💥

With the ability to reproduce the bug locally, I was able to find the crash was happening when _.merge is called against the persisted statsStreak data, and the latest data from the API.

This _.merge crashes the browser tab, and subsequently, the "bad" data is still in indexDb. Additionally, the query params for statsStreak data do not change but once per year, as the dates are based upon the calendar year... as such this problem will continually happen until the calypso indexDB is purged manually, or if the persisted data is too old.

The question still remains of how did this malformed array get created in the first place. @jblz tested the api response via the developer console, and in other browsers/incognito tabs and we could not re-create the massive array. I plan on investigating a bit more on the API side of things to see if I can reproduce the issue there.

The solution in this PR is to create a clone of the existing stats.list.items state tree, and _.unset the existing value before calling _.merge. I'm open to other suggestions so feel free to comment with other ideas!

To Test
Repeat the steps above locally, and verify the browser tab no longer crashes when using this branch.

@timmyc timmyc added [Feature] Stats Everything related to our analytics product at /stats/ [Status] Needs Review The PR is ready for review. This also triggers e2e canary tests and wp-desktop tests automatically. [Type] Bug When a feature is broken and / or not performing as intended labels Dec 30, 2016
@timmyc timmyc requested a review from jblz December 30, 2016 00:09
@matticbot
Copy link
Contributor

Copy link
Member

@jblz jblz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To clarify RE: that screenshot, it looks like the array is actually the size of a UNIX timestamp (🙀) & not the siteId -- and the index containing the 1 is that timestamp minus one.

So, here's what I did to reproduce:

const badArray = new Array(1482340821);
badArray[1482340820] = 1;
indexedDB.open('calypso').onsuccess = (e) => { 
    const db = e.target.result;
    const transaction = db.transaction( 'calypso_store', 'readwrite' );
    const store = transaction.objectStore( 'calypso_store' ); store.get( 'redux-state' ).onsuccess = (ee) => { 
        const state = ee.target.result;
        state.stats.lists.items[siteId].statsStreak['[["endDate","2016-12-31"],["gmtOffset",0],["max",3000],["startDate","2015-12-01"]]'].data = badArray;
        store.put( state, 'redux-state' );
    };
};

Maybe that will help figure out what might have happened vis-a-vis the API.

When I tested this, it took a couple / few times reloading to clear out the bad array from the persisted state & stop crashing, but it does eventually clear up the issue.

I'm going to go ahead and click "Approve" because this is definitely an improvement!

Thanks 🥇

@timmyc timmyc merged commit ff232c2 into master Dec 30, 2016
@timmyc timmyc deleted the fix/stats/reducer branch December 30, 2016 19:41
@lancewillett lancewillett removed the [Status] Needs Review The PR is ready for review. This also triggers e2e canary tests and wp-desktop tests automatically. label Jan 18, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Stats Everything related to our analytics product at /stats/ [Type] Bug When a feature is broken and / or not performing as intended
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants