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

Core data: batch actions in all resolvers #60604

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 80 additions & 70 deletions packages/core-data/src/resolvers.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export const getCurrentUser =
*/
export const getEntityRecord =
( kind, name, key = '', query ) =>
async ( { select, dispatch } ) => {
async ( { select, dispatch, registry } ) => {
const configs = await dispatch( getOrLoadEntitiesConfig( kind, name ) );
const entityConfig = configs.find(
( config ) => config.name === name && config.kind === kind
Expand Down Expand Up @@ -166,9 +166,12 @@ export const getEntityRecord =
}

const record = await apiFetch( { path } );
dispatch.receiveEntityRecords( kind, name, record, query );
registry.batch( () => {
dispatch.receiveEntityRecords( kind, name, record, query );
dispatch.__unstableReleaseStoreLock( lock );
} );
}
} finally {
} catch ( e ) {
Copy link
Member

Choose a reason for hiding this comment

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

Probably same as #60591 (comment).

dispatch.__unstableReleaseStoreLock( lock );
}
};
Expand Down Expand Up @@ -414,12 +417,14 @@ export const canUser =
permissions[ actionName ] = allowedMethods.includes( methodName );
}

for ( const action of retrievedActions ) {
dispatch.receiveUserPermission(
`${ action }/${ resourcePath }`,
permissions[ action ]
);
}
registry.batch( () => {
for ( const action of retrievedActions ) {
dispatch.receiveUserPermission(
`${ action }/${ resourcePath }`,
permissions[ action ]
);
}
} );
};

/**
Expand Down Expand Up @@ -668,7 +673,7 @@ export const getUserPatternCategories =

export const getNavigationFallbackId =
() =>
async ( { dispatch, select } ) => {
async ( { dispatch, select, registry } ) => {
const fallback = await apiFetch( {
path: addQueryArgs( '/wp-block-editor/v1/navigation-fallback', {
_embed: true,
Expand All @@ -677,33 +682,36 @@ export const getNavigationFallbackId =

const record = fallback?._embedded?.self;

dispatch.receiveNavigationFallbackId( fallback?.id );

if ( record ) {
// If the fallback is already in the store, don't invalidate navigation queries.
// Otherwise, invalidate the cache for the scenario where there were no Navigation
// posts in the state and the fallback created one.
const existingFallbackEntityRecord = select.getEntityRecord(
'postType',
'wp_navigation',
fallback.id
);
const invalidateNavigationQueries = ! existingFallbackEntityRecord;
dispatch.receiveEntityRecords(
'postType',
'wp_navigation',
record,
undefined,
invalidateNavigationQueries
);
registry.batch( () => {
dispatch.receiveNavigationFallbackId( fallback?.id );

if ( record ) {
Copy link
Member

Choose a reason for hiding this comment

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

Nit: Should we bail out early and reduce nesting?

// If the fallback is already in the store, don't invalidate navigation queries.
// Otherwise, invalidate the cache for the scenario where there were no Navigation
// posts in the state and the fallback created one.
const existingFallbackEntityRecord = select.getEntityRecord(
'postType',
'wp_navigation',
fallback.id
);
const invalidateNavigationQueries =
! existingFallbackEntityRecord;
dispatch.receiveEntityRecords(
'postType',
'wp_navigation',
record,
undefined,
invalidateNavigationQueries
);

// Resolve to avoid further network requests.
dispatch.finishResolution( 'getEntityRecord', [
'postType',
'wp_navigation',
fallback.id,
] );
}
// Resolve to avoid further network requests.
dispatch.finishResolution( 'getEntityRecord', [
'postType',
'wp_navigation',
fallback.id,
] );
}
} );
};

export const getDefaultTemplateId =
Expand All @@ -730,7 +738,7 @@ export const getDefaultTemplateId =
*/
export const getRevisions =
( kind, name, recordKey, query = {} ) =>
async ( { dispatch } ) => {
async ( { dispatch, registry } ) => {
const configs = await dispatch( getOrLoadEntitiesConfig( kind, name ) );
const entityConfig = configs.find(
( config ) => config.name === name && config.kind === kind
Expand Down Expand Up @@ -797,40 +805,42 @@ export const getRevisions =
} );
}

dispatch.receiveRevisions(
kind,
name,
recordKey,
records,
query,
false,
meta
);
registry.batch( () => {
dispatch.receiveRevisions(
kind,
name,
recordKey,
records,
query,
false,
meta
);

// When requesting all fields, the list of results can be used to
// resolve the `getRevision` selector in addition to `getRevisions`.
if ( ! query?._fields && ! query.context ) {
const key = entityConfig.key || DEFAULT_ENTITY_KEY;
const resolutionsArgs = records
.filter( ( record ) => record[ key ] )
.map( ( record ) => [
kind,
name,
recordKey,
record[ key ],
] );

dispatch( {
type: 'START_RESOLUTIONS',
selectorName: 'getRevision',
args: resolutionsArgs,
} );
dispatch( {
type: 'FINISH_RESOLUTIONS',
selectorName: 'getRevision',
args: resolutionsArgs,
} );
}
// When requesting all fields, the list of results can be used to
// resolve the `getRevision` selector in addition to `getRevisions`.
if ( ! query?._fields && ! query.context ) {
const key = entityConfig.key || DEFAULT_ENTITY_KEY;
const resolutionsArgs = records
.filter( ( record ) => record[ key ] )
.map( ( record ) => [
kind,
name,
recordKey,
record[ key ],
] );

dispatch( {
type: 'START_RESOLUTIONS',
selectorName: 'getRevision',
args: resolutionsArgs,
} );
dispatch( {
type: 'FINISH_RESOLUTIONS',
selectorName: 'getRevision',
args: resolutionsArgs,
} );
}
} );
}
};

Expand Down
13 changes: 11 additions & 2 deletions packages/core-data/src/test/resolvers.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ describe( 'getEntityRecord', () => {
baseURLParams: { context: 'edit' },
},
];
const registry = { batch: ( callback ) => callback() };

beforeEach( async () => {
triggerFetch.mockReset();
Expand All @@ -44,7 +45,11 @@ describe( 'getEntityRecord', () => {
// Provide response
triggerFetch.mockImplementation( () => POST_TYPE );

await getEntityRecord( 'root', 'postType', 'post' )( { dispatch } );
await getEntityRecord(
'root',
'postType',
'post'
)( { dispatch, registry } );

// Fetch request should have been issued.
expect( triggerFetch ).toHaveBeenCalledWith( {
Expand Down Expand Up @@ -92,7 +97,7 @@ describe( 'getEntityRecord', () => {
'postType',
'post',
query
)( { dispatch, select } );
)( { dispatch, select, registry } );

// Check resolution cache for an existing entity that fulfills the request with query.
expect( select.hasEntityRecords ).toHaveBeenCalledWith(
Expand Down Expand Up @@ -289,6 +294,7 @@ describe( 'canUser', () => {
select: jest.fn( () => ( {
hasStartedResolution: () => false,
} ) ),
batch: ( callback ) => callback(),
};
triggerFetch.mockReset();
} );
Expand Down Expand Up @@ -391,6 +397,7 @@ describe( 'canUser', () => {
select: () => ( {
hasStartedResolution: ( _, [ action ] ) => action === 'read',
} ),
batch: ( callback ) => callback(),
};

triggerFetch.mockImplementation( () => ( {
Expand Down Expand Up @@ -421,6 +428,7 @@ describe( 'canUser', () => {
select: () => ( {
hasStartedResolution: ( _, [ action ] ) => action === 'read',
} ),
batch: ( callback ) => callback(),
};

triggerFetch.mockImplementation( () => ( {
Expand Down Expand Up @@ -459,6 +467,7 @@ describe( 'canUser', () => {
select: () => ( {
hasStartedResolution: ( _, [ action ] ) => action === 'create',
} ),
batch: ( callback ) => callback(),
};

triggerFetch.mockImplementation( () => ( {
Expand Down
Loading