{"action":"created","comment":{"url":"https://api.github.com/repos/Automattic/wp-calypso/pulls/comments/68485870","id":68485870,"diff_hunk":"@@ -24,25 +24,63 @@ export function isValidStateWithSchema( state, schema, checkForCycles = false, b\n \treturn result.valid;\n }\n \n-export function createReducer( initialState = null, handlers = {}, schema = null ) {\n-\tconst defaultHandlers = {\n-\t\t[SERIALIZE]: ( state ) => {\n-\t\t\tif ( schema !== null ) {\n-\t\t\t\treturn state;\n-\t\t\t}\n+/**\n+ * Returns a reducer function with state calculation determined by the result\n+ * of invoking the handler key corresponding with the dispatched action type,\n+ * passing both the current state and action object. Defines default\n+ * serialization (persistence) handlers based on the presence of a schema.\n+ *\n+ * @param  {*}        initialState    Initial state\n+ * @param  {Object}   definedHandlers Object mapping action types to state\n+ *                                    action handlers\n+ * @param  {?Object}  schema          JSON schema object for deserialization\n+ *                                    validation\n+ * @return {Function}                 Reducer function\n+ */\n+export function createReducer( initialState = null, definedHandlers = {}, schema = null ) {\n+\t// Define default handlers for serialization actions. If no schema is\n+\t// provided, always return the initial state. Otherwise, allow for\n+\t// serialization and validate on deserialize.\n+\tlet defaultHandlers;\n+\tif ( schema ) {\n+\t\tdefaultHandlers = {\n+\t\t\t[ SERIALIZE ]: ( state ) => state,\n+\t\t\t[ DESERIALIZE ]: ( state ) => {\n+\t\t\t\tif ( isValidStateWithSchema( state, schema ) ) {\n+\t\t\t\t\treturn state;\n+\t\t\t\t}\n \n-\t\t\treturn initialState;\n-\t\t},\n-\t\t[DESERIALIZE]: ( state ) => {\n-\t\t\tif ( schema !== null && isValidStateWithSchema( state, schema ) ) {\n-\t\t\t\treturn state;\n+\t\t\t\treturn initialState;\n \t\t\t}\n+\t\t};\n+\t} else {\n+\t\tdefaultHandlers = {\n+\t\t\t[ SERIALIZE ]: () => initialState,\n+\t\t\t[ DESERIALIZE ]: () => initialState\n+\t\t};\n+\t}\n \n-\t\t\treturn initialState;\n-\t\t}\n+\tconst handlers = {\n+\t\t...defaultHandlers,\n+\t\t...definedHandlers\n \t};\n \n-\thandlers = Object.assign( {}, defaultHandlers, handlers );\n+\t// When custom serialization behavior is provided, we assume that it may\n+\t// involve heavy logic (mapping, converting from Immutable instance), so\n+\t// we cache the result and only regenerate when state has changed.\n+\tif ( definedHandlers[ SERIALIZE ] ) {\n+\t\tlet lastState, lastSerialized;\n+\t\thandlers[ SERIALIZE ] = ( state, action ) => {","path":"client/state/utils.js","position":64,"original_position":64,"commit_id":"bd61c1f8c0bd19aa3379636e2652ae34212c486a","original_commit_id":"bd61c1f8c0bd19aa3379636e2652ae34212c486a","user":{"login":"gziolo","id":699132,"avatar_url":"https://avatars.githubusercontent.com/u/699132?v=3","gravatar_id":"","url":"https://api.github.com/users/gziolo","html_url":"https://github.com/gziolo","followers_url":"https://api.github.com/users/gziolo/followers","following_url":"https://api.github.com/users/gziolo/following{/other_user}","gists_url":"https://api.github.com/users/gziolo/gists{/gist_id}","starred_url":"https://api.github.com/users/gziolo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gziolo/subscriptions","organizations_url":"https://api.github.com/users/gziolo/orgs","repos_url":"https://api.github.com/users/gziolo/repos","events_url":"https://api.github.com/users/gziolo/events{/privacy}","received_events_url":"https://api.github.com/users/gziolo/received_events","type":"User","site_admin":false},"body":"Have you consider using 'memoize' from lodash? It's good as it is, but maybe we could shorten it :)","created_at":"2016-06-25T07:53:56Z","updated_at":"2016-06-25T07:53:56Z","html_url":"https://github.com/Automattic/wp-calypso/pull/6318#discussion_r68485870","pull_request_url":"https://api.github.com/repos/Automattic/wp-calypso/pulls/6318","_links":{"self":{"href":"https://api.github.com/repos/Automattic/wp-calypso/pulls/comments/68485870"},"html":{"href":"https://github.com/Automattic/wp-calypso/pull/6318#discussion_r68485870"},"pull_request":{"href":"https://api.github.com/repos/Automattic/wp-calypso/pulls/6318"}}},"pull_request":{"url":"https://api.github.com/repos/Automattic/wp-calypso/pulls/6318","id":75187506,"html_url":"https://github.com/Automattic/wp-calypso/pull/6318","diff_url":"https://github.com/Automattic/wp-calypso/pull/6318.diff","patch_url":"https://github.com/Automattic/wp-calypso/pull/6318.patch","issue_url":"https://api.github.com/repos/Automattic/wp-calypso/issues/6318","number":6318,"state":"open","locked":false,"title":"State: Cache serialization result when defining custom behavior","user":{"login":"aduth","id":1779930,"avatar_url":"https://avatars.githubusercontent.com/u/1779930?v=3","gravatar_id":"","url":"https://api.github.com/users/aduth","html_url":"https://github.com/aduth","followers_url":"https://api.github.com/users/aduth/followers","following_url":"https://api.github.com/users/aduth/following{/other_user}","gists_url":"https://api.github.com/users/aduth/gists{/gist_id}","starred_url":"https://api.github.com/users/aduth/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aduth/subscriptions","organizations_url":"https://api.github.com/users/aduth/orgs","repos_url":"https://api.github.com/users/aduth/repos","events_url":"https://api.github.com/users/aduth/events{/privacy}","received_events_url":"https://api.github.com/users/aduth/received_events","type":"User","site_admin":false},"body":"This pull request seeks to enhance `createReducer`, caching serialization results when a custom `SERIALIZE` handler is specified. The thinking here is that if a developer defines a custom handler for `SERIALIZE`, chances are the implementation involves some heavy computation. An example of this is the [reducer for `state.terms.queries`](https://github.com/Automattic/wp-calypso/blob/3adc20a3320635c4d2c16112dd0c1340837fd4ca/client/state/terms/reducer.js#L99-L105). Because [the entire tree is serialized any time state changes (with minor throttling)](https://github.com/Automattic/wp-calypso/blob/3adc20a3320635c4d2c16112dd0c1340837fd4ca/client/state/initial-state.js#L73-L85), it can become very wasteful to regenerate the serialized value of this reducer when no changes have been made to that part of the tree. Separately, we may consider optimizing the subscribe call to at a minimum only re-serialize the changed top-level keys of the tree.\r\n\r\n__Testing instructions:__\r\n\r\nEnsure Mocha tests pass:\r\n\r\n```\r\nnpm run test-client\r\n```\r\n\r\nThe example given, `state.terms.queries`, is not yet used in the UI, at least not until #5366 is merged. From what I can determine, there is no usage of `createReducer` where a `SERIALIZE` handler is defined (at least as far as it affects the UI).\r\n\r\n/cc @gziolo @gwwar @timmyc \n\nTest live: https://calypso.live/?branch=update/redux-state-serialize-perf","created_at":"2016-06-24T23:43:02Z","updated_at":"2016-06-25T07:53:56Z","closed_at":null,"merged_at":null,"merge_commit_sha":"6ae4fa3957db02a1297dd88f6dfb871fa10393a1","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/Automattic/wp-calypso/pulls/6318/commits","review_comments_url":"https://api.github.com/repos/Automattic/wp-calypso/pulls/6318/comments","review_comment_url":"https://api.github.com/repos/Automattic/wp-calypso/pulls/comments{/number}","comments_url":"https://api.github.com/repos/Automattic/wp-calypso/issues/6318/comments","statuses_url":"https://api.github.com/repos/Automattic/wp-calypso/statuses/bd61c1f8c0bd19aa3379636e2652ae34212c486a","head":{"label":"Automattic:update/redux-state-serialize-perf","ref":"update/redux-state-serialize-perf","sha":"bd61c1f8c0bd19aa3379636e2652ae34212c486a","user":{"login":"Automattic","id":887802,"avatar_url":"https://avatars.githubusercontent.com/u/887802?v=3","gravatar_id":"","url":"https://api.github.com/users/Automattic","html_url":"https://github.com/Automattic","followers_url":"https://api.github.com/users/Automattic/followers","following_url":"https://api.github.com/users/Automattic/following{/other_user}","gists_url":"https://api.github.com/users/Automattic/gists{/gist_id}","starred_url":"https://api.github.com/users/Automattic/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Automattic/subscriptions","organizations_url":"https://api.github.com/users/Automattic/orgs","repos_url":"https://api.github.com/users/Automattic/repos","events_url":"https://api.github.com/users/Automattic/events{/privacy}","received_events_url":"https://api.github.com/users/Automattic/received_events","type":"Organization","site_admin":false},"repo":{"id":45936895,"name":"wp-calypso","full_name":"Automattic/wp-calypso","owner":{"login":"Automattic","id":887802,"avatar_url":"https://avatars.githubusercontent.com/u/887802?v=3","gravatar_id":"","url":"https://api.github.com/users/Automattic","html_url":"https://github.com/Automattic","followers_url":"https://api.github.com/users/Automattic/followers","following_url":"https://api.github.com/users/Automattic/following{/other_user}","gists_url":"https://api.github.com/users/Automattic/gists{/gist_id}","starred_url":"https://api.github.com/users/Automattic/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Automattic/subscriptions","organizations_url":"https://api.github.com/users/Automattic/orgs","repos_url":"https://api.github.com/users/Automattic/repos","events_url":"https://api.github.com/users/Automattic/events{/privacy}","received_events_url":"https://api.github.com/users/Automattic/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Automattic/wp-calypso","description":"The new JavaScript- and API-powered WordPress.com","fork":false,"url":"https://api.github.com/repos/Automattic/wp-calypso","forks_url":"https://api.github.com/repos/Automattic/wp-calypso/forks","keys_url":"https://api.github.com/repos/Automattic/wp-calypso/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Automattic/wp-calypso/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Automattic/wp-calypso/teams","hooks_url":"https://api.github.com/repos/Automattic/wp-calypso/hooks","issue_events_url":"https://api.github.com/repos/Automattic/wp-calypso/issues/events{/number}","events_url":"https://api.github.com/repos/Automattic/wp-calypso/events","assignees_url":"https://api.github.com/repos/Automattic/wp-calypso/assignees{/user}","branches_url":"https://api.github.com/repos/Automattic/wp-calypso/branches{/branch}","tags_url":"https://api.github.com/repos/Automattic/wp-calypso/tags","blobs_url":"https://api.github.com/repos/Automattic/wp-calypso/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Automattic/wp-calypso/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Automattic/wp-calypso/git/refs{/sha}","trees_url":"https://api.github.com/repos/Automattic/wp-calypso/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Automattic/wp-calypso/statuses/{sha}","languages_url":"https://api.github.com/repos/Automattic/wp-calypso/languages","stargazers_url":"https://api.github.com/repos/Automattic/wp-calypso/stargazers","contributors_url":"https://api.github.com/repos/Automattic/wp-calypso/contributors","subscribers_url":"https://api.github.com/repos/Automattic/wp-calypso/subscribers","subscription_url":"https://api.github.com/repos/Automattic/wp-calypso/subscription","commits_url":"https://api.github.com/repos/Automattic/wp-calypso/commits{/sha}","git_commits_url":"https://api.github.com/repos/Automattic/wp-calypso/git/commits{/sha}","comments_url":"https://api.github.com/repos/Automattic/wp-calypso/comments{/number}","issue_comment_url":"https://api.github.com/repos/Automattic/wp-calypso/issues/comments{/number}","contents_url":"https://api.github.com/repos/Automattic/wp-calypso/contents/{+path}","compare_url":"https://api.github.com/repos/Automattic/wp-calypso/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Automattic/wp-calypso/merges","archive_url":"https://api.github.com/repos/Automattic/wp-calypso/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Automattic/wp-calypso/downloads","issues_url":"https://api.github.com/repos/Automattic/wp-calypso/issues{/number}","pulls_url":"https://api.github.com/repos/Automattic/wp-calypso/pulls{/number}","milestones_url":"https://api.github.com/repos/Automattic/wp-calypso/milestones{/number}","notifications_url":"https://api.github.com/repos/Automattic/wp-calypso/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Automattic/wp-calypso/labels{/name}","releases_url":"https://api.github.com/repos/Automattic/wp-calypso/releases{/id}","deployments_url":"https://api.github.com/repos/Automattic/wp-calypso/deployments","created_at":"2015-11-10T20:00:16Z","updated_at":"2016-06-25T01:37:56Z","pushed_at":"2016-06-25T03:03:15Z","git_url":"git://github.com/Automattic/wp-calypso.git","ssh_url":"git@github.com:Automattic/wp-calypso.git","clone_url":"https://github.com/Automattic/wp-calypso.git","svn_url":"https://github.com/Automattic/wp-calypso","homepage":"https://developer.wordpress.com/calypso/","size":79803,"stargazers_count":7494,"watchers_count":7494,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":922,"mirror_url":null,"open_issues_count":1311,"forks":922,"open_issues":1311,"watchers":7494,"default_branch":"master"}},"base":{"label":"Automattic:master","ref":"master","sha":"3adc20a3320635c4d2c16112dd0c1340837fd4ca","user":{"login":"Automattic","id":887802,"avatar_url":"https://avatars.githubusercontent.com/u/887802?v=3","gravatar_id":"","url":"https://api.github.com/users/Automattic","html_url":"https://github.com/Automattic","followers_url":"https://api.github.com/users/Automattic/followers","following_url":"https://api.github.com/users/Automattic/following{/other_user}","gists_url":"https://api.github.com/users/Automattic/gists{/gist_id}","starred_url":"https://api.github.com/users/Automattic/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Automattic/subscriptions","organizations_url":"https://api.github.com/users/Automattic/orgs","repos_url":"https://api.github.com/users/Automattic/repos","events_url":"https://api.github.com/users/Automattic/events{/privacy}","received_events_url":"https://api.github.com/users/Automattic/received_events","type":"Organization","site_admin":false},"repo":{"id":45936895,"name":"wp-calypso","full_name":"Automattic/wp-calypso","owner":{"login":"Automattic","id":887802,"avatar_url":"https://avatars.githubusercontent.com/u/887802?v=3","gravatar_id":"","url":"https://api.github.com/users/Automattic","html_url":"https://github.com/Automattic","followers_url":"https://api.github.com/users/Automattic/followers","following_url":"https://api.github.com/users/Automattic/following{/other_user}","gists_url":"https://api.github.com/users/Automattic/gists{/gist_id}","starred_url":"https://api.github.com/users/Automattic/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Automattic/subscriptions","organizations_url":"https://api.github.com/users/Automattic/orgs","repos_url":"https://api.github.com/users/Automattic/repos","events_url":"https://api.github.com/users/Automattic/events{/privacy}","received_events_url":"https://api.github.com/users/Automattic/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Automattic/wp-calypso","description":"The new JavaScript- and API-powered WordPress.com","fork":false,"url":"https://api.github.com/repos/Automattic/wp-calypso","forks_url":"https://api.github.com/repos/Automattic/wp-calypso/forks","keys_url":"https://api.github.com/repos/Automattic/wp-calypso/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Automattic/wp-calypso/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Automattic/wp-calypso/teams","hooks_url":"https://api.github.com/repos/Automattic/wp-calypso/hooks","issue_events_url":"https://api.github.com/repos/Automattic/wp-calypso/issues/events{/number}","events_url":"https://api.github.com/repos/Automattic/wp-calypso/events","assignees_url":"https://api.github.com/repos/Automattic/wp-calypso/assignees{/user}","branches_url":"https://api.github.com/repos/Automattic/wp-calypso/branches{/branch}","tags_url":"https://api.github.com/repos/Automattic/wp-calypso/tags","blobs_url":"https://api.github.com/repos/Automattic/wp-calypso/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Automattic/wp-calypso/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Automattic/wp-calypso/git/refs{/sha}","trees_url":"https://api.github.com/repos/Automattic/wp-calypso/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Automattic/wp-calypso/statuses/{sha}","languages_url":"https://api.github.com/repos/Automattic/wp-calypso/languages","stargazers_url":"https://api.github.com/repos/Automattic/wp-calypso/stargazers","contributors_url":"https://api.github.com/repos/Automattic/wp-calypso/contributors","subscribers_url":"https://api.github.com/repos/Automattic/wp-calypso/subscribers","subscription_url":"https://api.github.com/repos/Automattic/wp-calypso/subscription","commits_url":"https://api.github.com/repos/Automattic/wp-calypso/commits{/sha}","git_commits_url":"https://api.github.com/repos/Automattic/wp-calypso/git/commits{/sha}","comments_url":"https://api.github.com/repos/Automattic/wp-calypso/comments{/number}","issue_comment_url":"https://api.github.com/repos/Automattic/wp-calypso/issues/comments{/number}","contents_url":"https://api.github.com/repos/Automattic/wp-calypso/contents/{+path}","compare_url":"https://api.github.com/repos/Automattic/wp-calypso/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Automattic/wp-calypso/merges","archive_url":"https://api.github.com/repos/Automattic/wp-calypso/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Automattic/wp-calypso/downloads","issues_url":"https://api.github.com/repos/Automattic/wp-calypso/issues{/number}","pulls_url":"https://api.github.com/repos/Automattic/wp-calypso/pulls{/number}","milestones_url":"https://api.github.com/repos/Automattic/wp-calypso/milestones{/number}","notifications_url":"https://api.github.com/repos/Automattic/wp-calypso/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Automattic/wp-calypso/labels{/name}","releases_url":"https://api.github.com/repos/Automattic/wp-calypso/releases{/id}","deployments_url":"https://api.github.com/repos/Automattic/wp-calypso/deployments","created_at":"2015-11-10T20:00:16Z","updated_at":"2016-06-25T01:37:56Z","pushed_at":"2016-06-25T03:03:15Z","git_url":"git://github.com/Automattic/wp-calypso.git","ssh_url":"git@github.com:Automattic/wp-calypso.git","clone_url":"https://github.com/Automattic/wp-calypso.git","svn_url":"https://github.com/Automattic/wp-calypso","homepage":"https://developer.wordpress.com/calypso/","size":79803,"stargazers_count":7494,"watchers_count":7494,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":922,"mirror_url":null,"open_issues_count":1311,"forks":922,"open_issues":1311,"watchers":7494,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/Automattic/wp-calypso/pulls/6318"},"html":{"href":"https://github.com/Automattic/wp-calypso/pull/6318"},"issue":{"href":"https://api.github.com/repos/Automattic/wp-calypso/issues/6318"},"comments":{"href":"https://api.github.com/repos/Automattic/wp-calypso/issues/6318/comments"},"review_comments":{"href":"https://api.github.com/repos/Automattic/wp-calypso/pulls/6318/comments"},"review_comment":{"href":"https://api.github.com/repos/Automattic/wp-calypso/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/Automattic/wp-calypso/pulls/6318/commits"},"statuses":{"href":"https://api.github.com/repos/Automattic/wp-calypso/statuses/bd61c1f8c0bd19aa3379636e2652ae34212c486a"}}}}
{"actor":{"display_login":"gziolo"}}