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

Framework: build redux store from scratch if persisted data is too old #3271

Merged
merged 1 commit into from
Feb 15, 2016

Conversation

gwwar
Copy link
Contributor

@gwwar gwwar commented Feb 12, 2016

If persisted data for our redux store is too old ( > 7 days ) we build the redux store from scratch. This also adds missing tests for initial-state.js which also covers some initial server state behavior

Testing Instructions

In development.json set persist-redux to true
In the console set localStorage debug to 'calypso:state'
Start up Calypso and navigate. The persisted store should load correctly without issues.
Tests in client/state pass

cc @rralian @aduth @mtias @dmsnell @ockham @seear

@gwwar gwwar added Framework [Status] Needs Review The PR is ready for review. This also triggers e2e canary tests and wp-desktop tests automatically. labels Feb 12, 2016
@gwwar gwwar self-assigned this Feb 12, 2016
@@ -55,7 +72,7 @@ function loadInitialStateFailed( error ) {

function persistOnChange( reduxStore ) {
reduxStore.subscribe( function() {
localforage.setItem( 'redux-state', serialize( reduxStore.getState() ) )
localforage.setItem( 'redux-state', addTimestamp( serialize( reduxStore.getState() ) ) )
Copy link
Contributor

Choose a reason for hiding this comment

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

The addTimestamp/removeTimestamp calls could maybe be moved inside the serialize/deserialize functions, making this line a little simpler?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍 added in e57ad3f

@seear
Copy link
Contributor

seear commented Feb 12, 2016

Interested in how the 7 day figure was arrived at?

@seear
Copy link
Contributor

seear commented Feb 12, 2016

Bootstrapping is still working fine on this branch 👍

@@ -16,6 +17,8 @@ import config from 'config';
*/
const debug = debugModule( 'calypso:state' );

export const MAX_AGE = ms( '7 days' );
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm all for leveraging dependencies, but this seems a bit... overkill? 😄 Can't we just calculate this in advance and leave a comment // 7 days ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Perhaps something like this is clear enough?

const MAX_AGE = 7 * 24 * 60 * 60 * 1000;

Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps something like this is clear enough?

Not very clear to me 😄

I'd suggest:

const MAX_AGE = 604800000; // 7 days

Or if you think it's important to explain the conversion:

const MAX_AGE = 604800000; // 7 days = 7 * 24 * 60 * 60 * 1000

Copy link
Member

Choose a reason for hiding this comment

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

It's nice on the PHP side of things because we use constants that are easily searchable

const MAX_AGE = 7 * DAY_IN_HOURS * HOUR_IN_MS

or something like that. different here because of the s vs ms thing

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the suggestions! I'll update with some constants. The problem with simply adding a comment is that they can get out of sync with the value, which is why I added in the micro lib. I've used it in the past where folks were tired of redefining constants in separate files.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated in e57ad3f

@aduth
Copy link
Contributor

aduth commented Feb 12, 2016

I think an ideal mechanism would be for the expiration to apply to individual segments of the state tree, not the entire tree. It'll be a bit abrupt that if my next session happens to fall on the lapse date, everything known in the persisted store is forgotten. Especially concerning if we're relying on this behavior in the desktop app to provide an offline experience if a user launches it without network connectivity (correct me if this is not a goal of persistence).

Another preference might be towards the store initialization not managing the expiration of items, but rather the reducer perform its own clean-up in receiving new data. So rather than risk objects ever being deleted during startup, they'd only be cleaned up as new items are received.

That said, I think this would be a fine direction for a short-term solution to the problem.

@aduth aduth added [Status] Needs Author Reply and removed [Status] Needs Review The PR is ready for review. This also triggers e2e canary tests and wp-desktop tests automatically. labels Feb 12, 2016
@gwwar
Copy link
Contributor Author

gwwar commented Feb 12, 2016

Thanks for the reviews!

Interested in how the 7 day figure was arrived at?

Completely arbitrary. This is more of an interim solution to make sure we have some mechanism to avoid completely eating all available browser storage. The chosen time seems long enough that devs would be able to sniff out any issues. We can certainly tune this as needed or replace this mechanism as our needs change.

I think an ideal mechanism would be for the expiration to apply to individual segments of the state tree, not the entire tree.

No arguments here, we'll iterate on this. I'm also interested to see if it make sense to store subtrees in different keys as well. As our tree grows, I'd be concerned with serialization costs if we continue to use our current method.

Another preference might be towards the store initialization not managing the expiration of items, but rather the reducer perform its own clean-up in receiving new data.

Completely reasonable, though it does put additional burden on anyone implementing reducers. Initialization is a very convenient place to change our data handling strategies.

@gwwar gwwar force-pushed the add/redux-max-age branch from 5e1c700 to e57ad3f Compare February 12, 2016 19:00
@gwwar gwwar added this to the Calypso Core: Offline 4 milestone Feb 12, 2016
@gwwar gwwar added [Status] Needs Review The PR is ready for review. This also triggers e2e canary tests and wp-desktop tests automatically. and removed [Status] Needs Author Reply labels Feb 12, 2016
window.initialReduxState = serverState;
configStub = sinon.stub( config, 'isEnabled' );
configStub.withArgs( 'persist-redux' ).returns( false );
consoleSpy = sinon.spy( console, 'error' );
Copy link
Contributor

Choose a reason for hiding this comment

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

Definitely not necessary to change, though as an FYI, you don't need to assign the spy to a variable. Instead:

sinon.spy( console, 'error' );
expect( console.error.called ).to.equal( false );
console.error.restore();

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 bizarre thing was that at my last place we would sometimes see restore() fail 1 out of xx times when using this approach. It was probably due to some leaky test cleanup with a huge test suite, but I've gotten into the habit of storing it in a variable.

@aduth
Copy link
Contributor

aduth commented Feb 15, 2016

Future iterations notwithstanding, I think this is a good first step to address the immediate concern of stale / large data persistence 👍

@aduth aduth added [Status] Ready to Merge and removed [Status] Needs Review The PR is ready for review. This also triggers e2e canary tests and wp-desktop tests automatically. labels Feb 15, 2016
@gwwar
Copy link
Contributor Author

gwwar commented Feb 15, 2016

Thanks for the reviews! I'm squishing commits.

@gwwar gwwar force-pushed the add/redux-max-age branch from e57ad3f to e5d8fc5 Compare February 15, 2016 15:52
gwwar added a commit that referenced this pull request Feb 15, 2016
Framework: build redux store from scratch if persisted data is too old
@gwwar gwwar merged commit f83d11b into master Feb 15, 2016
@gwwar gwwar deleted the add/redux-max-age branch February 15, 2016 16:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants