-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Gutenberg: Reset core resolvers on site change #29445
Gutenberg: Reset core resolvers on site change #29445
Conversation
@@ -34,26 +34,24 @@ const addResetToRegistry = registry => { | |||
window.gutenbergState = () => mapValues( registry.stores, ( { store } ) => store.getState() ); | |||
} | |||
|
|||
const resettableStores = [ 'core/editor', 'core/notices' ]; | |||
|
|||
const stores = []; | |||
return { | |||
registerStore( namespace, options ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@aduth @jsnajdr
This part here that extends all the stores with a reset
method, is not applied to core/data
(aka the store in the data
package) as well.
It's easily testable by adding a console.log( namespace )
here, and observe that it "traverses" all expected stores, except core/data
.
I'm not sure why, and I always get lost in the logic behind the Gutenberg data module.
In other words, this function here allows me to reset core
(aka the store in the core-data
package) but not core/data
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason why the core/data
ignores the call to reset()
is that it's created and registered very early as part of the createRegistry
function.
At that time, the registerStore
function is not yet extended with the use( addResetToRegistry )
plugin and the registered reducer is not wrapped with the HoR that reacts to the GUTENLYPSO_RESET
action.
I don't think that being able to fully reset the core/data
store is even wanted. The core/data
store is a bit special: it maintains the resolution flag for all other stores' selectors. We only ever want to reset the resolution flags for one store at a time, not for all of them.
Fortunately, some support for resetting core/data
state was added in WordPress/gutenberg#10089 and we can use it for our purposes. Inspired by the resolvers cache middleware, we can implement a function that resets all resolution state for one store:
function resetStoreResolutions( registry, reducerKey ) {
const resolvers = registry.select( 'core/data' ).getCachedResolvers( reducerKey );
Object.entries( resolvers ).forEach( ( [ selectorName, resolversByArgs ] ) => {
resolversByArgs.forEach( ( _, args ) => {
registry.dispatch( 'core/data' ).invalidateResolution( reducerKey, selectorName, args );
} );
} );
}
Then we can add a call to this new function to the reset
function:
reset() {
resettableStores.forEach( reducerKey => {
registry.stores[ reducerKey ].dispatch( { type: 'GUTENLYPSO_RESET' } );
resetStoreResolutions( registry, reducerKey );
} );
}
This should reset everything on site change. There is just one race condition bug that remains: if a request for entities from site ID=1 is in flight, and we switch to site ID=2, then the response from site ID=2 will be received into store with site ID=2!
The cache invalidation code in WordPress/gutenberg#10089 probably has a similar bug: it won't invalidate resolution for selector whose request is in flight. There can be "get a list" and "add to list" requests happening at the same time, and if their "issue request from client", "perform request on server" and "receive response on client" are performed in a certain order, the resulting state will miss the just-added entity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Created an issue for tracking at WordPress/gutenberg#12984
5d12168
to
dbdad45
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This tests well for me. Good work @Copons!
The code also looks good to me, but I'd prefer if someone else can confirm it since I'm not feeling confidence enough yet with the data layer (especially with the complexity we're handling here) and I might miss something :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tests well for me!
// Only reset core/data on site change | ||
const previousGutenbergSiteId = select( 'gutenberg/calypso' ).getSelectedSiteId(); | ||
|
||
if ( !! previousGutenbergSiteId && previousGutenbergSiteId !== selectedSiteId ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Neat. :)
…sh-2019 * origin/master: change "expert" to "support" in page route and title (#29459) Add note to concierge upsell page about sessions only being offered in English. (#29461) Jetpack Blocks: Fix webpack warnings due to dynamic import (#29509) Gutenberg: Reset core resolvers on site change (#29445) Signup: Remove Masterbar from Signup (#28886) Fix missing bumpStat call (#29504) Gutenberg Jetpack Preset: Generate imports dynamically from index.json (#29435) Fix the clean:public script to do a better job cleaning public/ folder (#29354) Tiled gallery: Add alignWide support (#29493) Tiled Gallery: Add noResize to block save (#29496) Show G Suite user fields by default (#29458) ColorThemes: Add GA and bumpStat events for scheme picking (#29413) Remove legacy mock for extensions reducer (#29397) Antispam promo card: tweak copy to make it clearer (#29440) prevent 0 as street number for ebanx checkouts (#29487) Gutenberg: Update Related Posts to use the posts endpoint (#29439) remove override on payment methods name in India (#29406) Add a space to separate "the" from the holiday name placeholder. (#29479) Revert "Migrate my-sites/sharing to webpack css pipeline (#28607)" (#29463) Gutenpack Subscription Block (Take two) (#28887)
Changes proposed in this Pull Request
core
resolvers on site change in order to avoid accidentally sending REST request to the previously selected site.To manage to do this, I've introduced:
A new
gutenberg/calypso
store (name can be changed: I don't have any preferences compared tocalypso/gutenberg
, and even simplycalypso
) with a singleselectedSiteId
attribute.It keeps track of the most recent selected site ID on the last Gutenberg editor load.
This is needed so that, when we open Gutenberg again, we can check if meanwhile we changed the site.
A more granular way of resetting single Gutenberg stores.
Before:
registry.reset()
knew by itself which stores to reset.After:
registry.reset( 'core/foobar' )
, the store name needs to be provided explicitly.A resolver invalidation function inspired by Core Gutenberg (props to @jsnajdr) called when navigating to Gutenberg, if the selected site has changed since last time Gutenberg was loaded.
Context: #28302 (review)
Testing instructions
localStorage.debug = 'calypso:gutenberg'
(a reload is required). Filter the console for "reset" to remove the noise./block-editor
.core/editor
andcore/notices
are reset:core/editor
,core/notices
, and thecore
resolvers are reset:core/editor
andcore/notices
are reset.Regression check 1:
^
+⌥
+H
to open the keyboard shortcuts modal.Regression check 2:
sending api
.Fixes #29369