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: Add __experimentalBatch() #28210

Merged
merged 1 commit into from
Jan 28, 2021
Merged

Conversation

noisysocks
Copy link
Member

@noisysocks noisysocks commented Jan 15, 2021

Fixes #27173.
Fixes #28186.
Alternative to #27241.

  • Replaces the batch-processing data store with a stripped back API based on https://github.com/WordPress/gutenberg/pull/27241/files#r555573124 that doesn't use any persistence.

    const batch = createBatch();
    const dunePromise = batch.add( {
      path: '/v1/books',
      method: 'POST',
      data: { title: 'Dune' }
    } );
    const lotrPromise = batch.add( {
      path: '/v1/books',
      method: 'POST',
      data: { title: 'Lord of the Rings' }
    } );
    const isSuccess = await batch.run(); // Sends one POST to /v1/batch.
    if ( isSuccess ) {
      console.log(
        'Saved two books:',
        await dunePromise,
        await lotrPromise
      );
    }
  • Adds __experimentalBatch() to core-data.

    const [ savedRecord, updatedRecord, deletedRecord ] =
      await dispatch( 'core' ).__experimentalBatch( [
        ( { saveEntityRecord } ) => saveEntityRecord( 'root', 'widget', widget ),
        ( { saveEditedEntityRecord } ) => saveEntityRecord( 'root', 'widget', 123 ),
        ( { deleteEntityRecord } ) => deleteEntityRecord( 'root', 'widget', 123, null ),
      ] );
  • Changes saveWidgetArea() to use __experimentalBatch().

  • Properly fixes Widgets editor: "There was an error. object Object" on save #27173 by ensuring that batch.run() waits for all inputs to be added before proceeding.

@youknowriad @TimothyBJacobs @kevin940726 @talldan

A ✅ should be sufficient for testing as until tests are included and adding-widgets.test.js includes a test for saving widgets.

@noisysocks noisysocks added REST API Interaction Related to REST API [Feature] Widgets Screen The block-based screen that replaced widgets.php. labels Jan 15, 2021
@github-actions
Copy link

github-actions bot commented Jan 15, 2021

Size Change: -1.64 kB (0%)

Total Size: 1.37 MB

Filename Size Change
build/a11y/index.js 1.14 kB +1 B (0%)
build/annotations/index.js 3.77 kB -1 B (0%)
build/api-fetch/index.js 3.4 kB -1 B (0%)
build/block-directory/index.js 9.07 kB -3 B (0%)
build/block-editor/index.js 123 kB +24 B (0%)
build/block-library/index.js 143 kB +29 B (0%)
build/block-serialization-default-parser/index.js 1.88 kB +1 B (0%)
build/blocks/index.js 48.3 kB +3 B (0%)
build/components/index.js 275 kB +6 B (0%)
build/compose/index.js 11.2 kB +15 B (0%)
build/core-data/index.js 16.8 kB +1.59 kB (+10%) ⚠️
build/data/index.js 8.96 kB -4 B (0%)
build/date/index.js 31.8 kB -1 B (0%)
build/deprecated/index.js 768 B -1 B (0%)
build/edit-navigation/index.js 11.1 kB +22 B (0%)
build/edit-post/index.js 306 kB +29 B (0%)
build/edit-site/index.js 24.1 kB +30 B (0%)
build/edit-widgets/index.js 20 kB -3.44 kB (-15%) 👏
build/editor/index.js 41.8 kB +11 B (0%)
build/format-library/index.js 6.76 kB -3 B (0%)
build/i18n/index.js 3.57 kB +1 B (0%)
build/keyboard-shortcuts/index.js 2.54 kB -1 B (0%)
build/list-reusable-blocks/index.js 3.15 kB +10 B (0%)
build/media-utils/index.js 5.33 kB +16 B (0%)
build/notices/index.js 1.85 kB +1 B (0%)
build/nux/index.js 3.41 kB -1 B (0%)
build/plugins/index.js 2.54 kB +9 B (0%)
build/primitives/index.js 1.42 kB -1 B (0%)
build/priority-queue/index.js 790 B +1 B (0%)
build/redux-routine/index.js 2.84 kB -2 B (0%)
build/rich-text/index.js 13.4 kB -1 B (0%)
build/server-side-render/index.js 2.77 kB +11 B (0%)
build/url/index.js 3.02 kB -1 B (0%)
build/wordcount/index.js 1.22 kB +1 B (0%)
ℹ️ View Unchanged
Filename Size Change
build/autop/index.js 2.84 kB 0 B
build/blob/index.js 665 B 0 B
build/block-directory/style-rtl.css 1.01 kB 0 B
build/block-directory/style.css 1.01 kB 0 B
build/block-editor/style-rtl.css 11.9 kB 0 B
build/block-editor/style.css 11.9 kB 0 B
build/block-library/blocks/archives/editor-rtl.css 61 B 0 B
build/block-library/blocks/archives/editor.css 60 B 0 B
build/block-library/blocks/audio/editor-rtl.css 58 B 0 B
build/block-library/blocks/audio/editor.css 58 B 0 B
build/block-library/blocks/audio/style-rtl.css 103 B 0 B
build/block-library/blocks/audio/style.css 103 B 0 B
build/block-library/blocks/block/editor-rtl.css 161 B 0 B
build/block-library/blocks/block/editor.css 161 B 0 B
build/block-library/blocks/button/editor-rtl.css 475 B 0 B
build/block-library/blocks/button/editor.css 474 B 0 B
build/block-library/blocks/button/style-rtl.css 453 B 0 B
build/block-library/blocks/button/style.css 451 B 0 B
build/block-library/blocks/buttons/editor-rtl.css 227 B 0 B
build/block-library/blocks/buttons/editor.css 227 B 0 B
build/block-library/blocks/buttons/style-rtl.css 297 B 0 B
build/block-library/blocks/buttons/style.css 297 B 0 B
build/block-library/blocks/calendar/style-rtl.css 208 B 0 B
build/block-library/blocks/calendar/style.css 208 B 0 B
build/block-library/blocks/categories/editor-rtl.css 84 B 0 B
build/block-library/blocks/categories/editor.css 83 B 0 B
build/block-library/blocks/categories/style-rtl.css 79 B 0 B
build/block-library/blocks/categories/style.css 79 B 0 B
build/block-library/blocks/code/style-rtl.css 90 B 0 B
build/block-library/blocks/code/style.css 90 B 0 B
build/block-library/blocks/columns/editor-rtl.css 190 B 0 B
build/block-library/blocks/columns/editor.css 190 B 0 B
build/block-library/blocks/columns/style-rtl.css 421 B 0 B
build/block-library/blocks/columns/style.css 421 B 0 B
build/block-library/blocks/cover/editor-rtl.css 392 B 0 B
build/block-library/blocks/cover/editor.css 393 B 0 B
build/block-library/blocks/cover/style-rtl.css 1.25 kB 0 B
build/block-library/blocks/cover/style.css 1.25 kB 0 B
build/block-library/blocks/embed/editor-rtl.css 486 B 0 B
build/block-library/blocks/embed/editor.css 486 B 0 B
build/block-library/blocks/embed/style-rtl.css 375 B 0 B
build/block-library/blocks/embed/style.css 375 B 0 B
build/block-library/blocks/file/editor-rtl.css 199 B 0 B
build/block-library/blocks/file/editor.css 198 B 0 B
build/block-library/blocks/file/style-rtl.css 248 B 0 B
build/block-library/blocks/file/style.css 248 B 0 B
build/block-library/blocks/freeform/editor-rtl.css 2.45 kB 0 B
build/block-library/blocks/freeform/editor.css 2.45 kB 0 B
build/block-library/blocks/gallery/editor-rtl.css 679 B 0 B
build/block-library/blocks/gallery/editor.css 679 B 0 B
build/block-library/blocks/gallery/style-rtl.css 1.07 kB 0 B
build/block-library/blocks/gallery/style.css 1.06 kB 0 B
build/block-library/blocks/group/editor-rtl.css 318 B 0 B
build/block-library/blocks/group/editor.css 317 B 0 B
build/block-library/blocks/group/style-rtl.css 57 B 0 B
build/block-library/blocks/group/style.css 57 B 0 B
build/block-library/blocks/heading/editor-rtl.css 129 B 0 B
build/block-library/blocks/heading/editor.css 129 B 0 B
build/block-library/blocks/heading/style-rtl.css 76 B 0 B
build/block-library/blocks/heading/style.css 76 B 0 B
build/block-library/blocks/html/editor-rtl.css 281 B 0 B
build/block-library/blocks/html/editor.css 281 B 0 B
build/block-library/blocks/image/editor-rtl.css 717 B 0 B
build/block-library/blocks/image/editor.css 716 B 0 B
build/block-library/blocks/image/style-rtl.css 477 B 0 B
build/block-library/blocks/image/style.css 478 B 0 B
build/block-library/blocks/latest-comments/editor-rtl.css 159 B 0 B
build/block-library/blocks/latest-comments/editor.css 158 B 0 B
build/block-library/blocks/latest-comments/style-rtl.css 269 B 0 B
build/block-library/blocks/latest-comments/style.css 269 B 0 B
build/block-library/blocks/latest-posts/editor-rtl.css 137 B 0 B
build/block-library/blocks/latest-posts/editor.css 137 B 0 B
build/block-library/blocks/latest-posts/style-rtl.css 523 B 0 B
build/block-library/blocks/latest-posts/style.css 522 B 0 B
build/block-library/blocks/list/editor-rtl.css 65 B 0 B
build/block-library/blocks/list/editor.css 65 B 0 B
build/block-library/blocks/list/style-rtl.css 63 B 0 B
build/block-library/blocks/list/style.css 63 B 0 B
build/block-library/blocks/media-text/editor-rtl.css 191 B 0 B
build/block-library/blocks/media-text/editor.css 191 B 0 B
build/block-library/blocks/media-text/style-rtl.css 535 B 0 B
build/block-library/blocks/media-text/style.css 532 B 0 B
build/block-library/blocks/more/editor-rtl.css 434 B 0 B
build/block-library/blocks/more/editor.css 434 B 0 B
build/block-library/blocks/navigation-link/editor-rtl.css 392 B 0 B
build/block-library/blocks/navigation-link/editor.css 394 B 0 B
build/block-library/blocks/navigation-link/style-rtl.css 704 B 0 B
build/block-library/blocks/navigation-link/style.css 702 B 0 B
build/block-library/blocks/navigation/editor-rtl.css 1.38 kB 0 B
build/block-library/blocks/navigation/editor.css 1.37 kB 0 B
build/block-library/blocks/navigation/style-rtl.css 171 B 0 B
build/block-library/blocks/navigation/style.css 171 B 0 B
build/block-library/blocks/nextpage/editor-rtl.css 395 B 0 B
build/block-library/blocks/nextpage/editor.css 395 B 0 B
build/block-library/blocks/paragraph/editor-rtl.css 109 B 0 B
build/block-library/blocks/paragraph/editor.css 109 B 0 B
build/block-library/blocks/paragraph/style-rtl.css 273 B 0 B
build/block-library/blocks/paragraph/style.css 273 B 0 B
build/block-library/blocks/post-author/editor-rtl.css 209 B 0 B
build/block-library/blocks/post-author/editor.css 209 B 0 B
build/block-library/blocks/post-author/style-rtl.css 183 B 0 B
build/block-library/blocks/post-author/style.css 184 B 0 B
build/block-library/blocks/post-comments-form/style-rtl.css 249 B 0 B
build/block-library/blocks/post-comments-form/style.css 249 B 0 B
build/block-library/blocks/post-content/editor-rtl.css 139 B 0 B
build/block-library/blocks/post-content/editor.css 139 B 0 B
build/block-library/blocks/post-excerpt/editor-rtl.css 73 B 0 B
build/block-library/blocks/post-excerpt/editor.css 73 B 0 B
build/block-library/blocks/post-featured-image/editor-rtl.css 338 B 0 B
build/block-library/blocks/post-featured-image/editor.css 338 B 0 B
build/block-library/blocks/post-featured-image/style-rtl.css 100 B 0 B
build/block-library/blocks/post-featured-image/style.css 100 B 0 B
build/block-library/blocks/preformatted/style-rtl.css 63 B 0 B
build/block-library/blocks/preformatted/style.css 63 B 0 B
build/block-library/blocks/pullquote/editor-rtl.css 183 B 0 B
build/block-library/blocks/pullquote/editor.css 183 B 0 B
build/block-library/blocks/pullquote/style-rtl.css 316 B 0 B
build/block-library/blocks/pullquote/style.css 316 B 0 B
build/block-library/blocks/query-loop/editor-rtl.css 90 B 0 B
build/block-library/blocks/query-loop/editor.css 89 B 0 B
build/block-library/blocks/query-loop/style-rtl.css 315 B 0 B
build/block-library/blocks/query-loop/style.css 317 B 0 B
build/block-library/blocks/query-pagination-numbers/editor-rtl.css 122 B 0 B
build/block-library/blocks/query-pagination-numbers/editor.css 121 B 0 B
build/block-library/blocks/query-pagination/editor-rtl.css 270 B 0 B
build/block-library/blocks/query-pagination/editor.css 262 B 0 B
build/block-library/blocks/query-pagination/style-rtl.css 168 B 0 B
build/block-library/blocks/query-pagination/style.css 168 B 0 B
build/block-library/blocks/query/editor-rtl.css 159 B 0 B
build/block-library/blocks/query/editor.css 160 B 0 B
build/block-library/blocks/quote/editor-rtl.css 61 B 0 B
build/block-library/blocks/quote/editor.css 61 B 0 B
build/block-library/blocks/quote/style-rtl.css 169 B 0 B
build/block-library/blocks/quote/style.css 169 B 0 B
build/block-library/blocks/rss/editor-rtl.css 201 B 0 B
build/block-library/blocks/rss/editor.css 202 B 0 B
build/block-library/blocks/rss/style-rtl.css 290 B 0 B
build/block-library/blocks/rss/style.css 290 B 0 B
build/block-library/blocks/search/editor-rtl.css 165 B 0 B
build/block-library/blocks/search/editor.css 165 B 0 B
build/block-library/blocks/search/style-rtl.css 342 B 0 B
build/block-library/blocks/search/style.css 344 B 0 B
build/block-library/blocks/separator/editor-rtl.css 99 B 0 B
build/block-library/blocks/separator/editor.css 99 B 0 B
build/block-library/blocks/separator/style-rtl.css 236 B 0 B
build/block-library/blocks/separator/style.css 236 B 0 B
build/block-library/blocks/shortcode/editor-rtl.css 504 B 0 B
build/block-library/blocks/shortcode/editor.css 504 B 0 B
build/block-library/blocks/site-logo/editor-rtl.css 201 B 0 B
build/block-library/blocks/site-logo/editor.css 201 B 0 B
build/block-library/blocks/site-logo/style-rtl.css 117 B 0 B
build/block-library/blocks/site-logo/style.css 117 B 0 B
build/block-library/blocks/social-link/editor-rtl.css 164 B 0 B
build/block-library/blocks/social-link/editor.css 165 B 0 B
build/block-library/blocks/social-links/editor-rtl.css 711 B 0 B
build/block-library/blocks/social-links/editor.css 712 B 0 B
build/block-library/blocks/social-links/style-rtl.css 1.37 kB 0 B
build/block-library/blocks/social-links/style.css 1.37 kB 0 B
build/block-library/blocks/spacer/editor-rtl.css 302 B 0 B
build/block-library/blocks/spacer/editor.css 302 B 0 B
build/block-library/blocks/spacer/style-rtl.css 48 B 0 B
build/block-library/blocks/spacer/style.css 48 B 0 B
build/block-library/blocks/subhead/editor-rtl.css 99 B 0 B
build/block-library/blocks/subhead/editor.css 99 B 0 B
build/block-library/blocks/subhead/style-rtl.css 80 B 0 B
build/block-library/blocks/subhead/style.css 80 B 0 B
build/block-library/blocks/table/editor-rtl.css 489 B 0 B
build/block-library/blocks/table/editor.css 489 B 0 B
build/block-library/blocks/table/style-rtl.css 386 B 0 B
build/block-library/blocks/table/style.css 386 B 0 B
build/block-library/blocks/tag-cloud/editor-rtl.css 118 B 0 B
build/block-library/blocks/tag-cloud/editor.css 118 B 0 B
build/block-library/blocks/tag-cloud/style-rtl.css 94 B 0 B
build/block-library/blocks/tag-cloud/style.css 94 B 0 B
build/block-library/blocks/template-part/editor-rtl.css 680 B 0 B
build/block-library/blocks/template-part/editor.css 679 B 0 B
build/block-library/blocks/text-columns/editor-rtl.css 95 B 0 B
build/block-library/blocks/text-columns/editor.css 95 B 0 B
build/block-library/blocks/text-columns/style-rtl.css 166 B 0 B
build/block-library/blocks/text-columns/style.css 166 B 0 B
build/block-library/blocks/verse/editor-rtl.css 62 B 0 B
build/block-library/blocks/verse/editor.css 62 B 0 B
build/block-library/blocks/verse/style-rtl.css 87 B 0 B
build/block-library/blocks/verse/style.css 87 B 0 B
build/block-library/blocks/video/editor-rtl.css 504 B 0 B
build/block-library/blocks/video/editor.css 503 B 0 B
build/block-library/blocks/video/style-rtl.css 193 B 0 B
build/block-library/blocks/video/style.css 193 B 0 B
build/block-library/common-rtl.css 1.01 kB 0 B
build/block-library/common.css 1.01 kB 0 B
build/block-library/editor-rtl.css 9.06 kB 0 B
build/block-library/editor.css 9.05 kB 0 B
build/block-library/style-rtl.css 8.61 kB 0 B
build/block-library/style.css 8.61 kB 0 B
build/block-library/theme-rtl.css 748 B 0 B
build/block-library/theme.css 748 B 0 B
build/block-serialization-spec-parser/index.js 3.06 kB 0 B
build/components/style-rtl.css 15.5 kB 0 B
build/components/style.css 15.5 kB 0 B
build/data-controls/index.js 830 B 0 B
build/dom-ready/index.js 571 B 0 B
build/dom/index.js 4.93 kB 0 B
build/edit-navigation/style-rtl.css 938 B 0 B
build/edit-navigation/style.css 944 B 0 B
build/edit-post/style-rtl.css 6.53 kB 0 B
build/edit-post/style.css 6.52 kB 0 B
build/edit-site/style-rtl.css 4.04 kB 0 B
build/edit-site/style.css 4.04 kB 0 B
build/edit-widgets/style-rtl.css 3.2 kB 0 B
build/edit-widgets/style.css 3.2 kB 0 B
build/editor/editor-styles-rtl.css 543 B 0 B
build/editor/editor-styles.css 545 B 0 B
build/editor/style-rtl.css 3.89 kB 0 B
build/editor/style.css 3.89 kB 0 B
build/element/index.js 4.62 kB 0 B
build/escape-html/index.js 735 B 0 B
build/format-library/style-rtl.css 637 B 0 B
build/format-library/style.css 639 B 0 B
build/hooks/index.js 2.27 kB 0 B
build/html-entities/index.js 623 B 0 B
build/is-shallow-equal/index.js 699 B 0 B
build/keycodes/index.js 1.93 kB 0 B
build/list-reusable-blocks/style-rtl.css 629 B 0 B
build/list-reusable-blocks/style.css 628 B 0 B
build/nux/style-rtl.css 731 B 0 B
build/nux/style.css 727 B 0 B
build/reusable-blocks/index.js 2.92 kB 0 B
build/shortcode/index.js 1.7 kB 0 B
build/token-list/index.js 1.27 kB 0 B
build/viewport/index.js 1.86 kB 0 B
build/warning/index.js 1.14 kB 0 B

compressed-size-action

packages/edit-widgets/src/store/actions.js Outdated Show resolved Hide resolved
packages/core-data/src/actions.js Outdated Show resolved Hide resolved
packages/data/src/batch.js Outdated Show resolved Hide resolved
} ) );
}

return batchResponse.responses.map( ( response ) => {
Copy link
Member

Choose a reason for hiding this comment

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

It'd be nice if those also checked against request.parse and when false created the full response object.

Copy link
Member Author

Choose a reason for hiding this comment

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

Sorry not sure what you mean here?

@adamziel
Copy link
Contributor

I like how it's more succinct, it's much easier to follow without going through the store for data. What I don't like is that we're losing the power of redux devtools. Maybe it could dispatch redux actions without any reducers as a compromise solution? There would be at least some visibility as to what's happening.

@noisysocks
Copy link
Member Author

Not sure that it makes sense to dispatch an action if there's no reducer or control that does anything with it?

I agree with you though that this stuff is a pain to debug. It's because rungen adds a lot of indirection to the call stack which makes it difficult to use DevTools. I'd probably prefer that we fix that by moving away from rungen/controls to async functions i.e. #27276.

@noisysocks
Copy link
Member Author

noisysocks commented Jan 19, 2021

I'm fairly happy with this. Just working on tests and documentation now and then I'll un-draft the PR.

I don't really like the __unstableAwaitPromise and getDispatch controls that I'm using in __experimentalBatch:

export function* __experimentalBatch( tasks ) {
	const batch = createBatch();
	const dispatch = yield getDispatch();
	const api = { ... };
	const results = tasks.map( ( task ) => task( api ) );
	yield __unstableAwaitPromise( batch.run() );
	return yield __unstableAwaitPromise( Promise.all( results ) );
}

But I'm hopeful that something will come of #27276 which will let us remove both of those:

export const __experimentalBatch = ( tasks ) => async ( { dispatch } ) => {
	const batch = createBatch();
	const api = { ... };
	const results = tasks.map( ( task ) => task( api ) );
	await batch.run();
	return await Promise.all( results );
};

@noisysocks noisysocks force-pushed the try/simpler-batch-processing branch from 9167ac8 to 0a96262 Compare January 19, 2021 05:45
@noisysocks noisysocks marked this pull request as ready for review January 19, 2021 06:34
@noisysocks noisysocks changed the title WIP: Replace batch processing store with a simpler API Core Data: Add __experimentalBatch() Jan 19, 2021
@noisysocks
Copy link
Member Author

All ready! I added tests, wrote some docs, and updated the PR description.

@noisysocks noisysocks added the [Package] Core data /packages/core-data label Jan 19, 2021
@kevin940726
Copy link
Member

Haven't looked into the diff yet, but after testing locally, seems like this PR fixes #28186 as well! 🎉

@noisysocks noisysocks force-pushed the try/simpler-batch-processing branch from c3e67b3 to 5a9c126 Compare January 20, 2021 00:38
Copy link
Member

@kevin940726 kevin940726 left a comment

Choose a reason for hiding this comment

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

Great work! Just some tiny code suggestions for now.

packages/core-data/src/batch/create-batch.js Outdated Show resolved Hide resolved
packages/core-data/src/batch/create-batch.js Show resolved Hide resolved
packages/core-data/src/batch/create-batch.js Outdated Show resolved Hide resolved
packages/core-data/src/batch/test/create-batch.js Outdated Show resolved Hide resolved
Copy link
Member

@kevin940726 kevin940726 left a comment

Choose a reason for hiding this comment

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

LGTM 👍. Thanks a lot!

@noisysocks noisysocks added the [Type] New API New API to be used by plugin developers or package users. label Jan 27, 2021
- Replaces the batch-processing data store with a stripped back API that
  doesn't use any persistence.
- Adds __experimentalBatch() to core-data.
- Changes edit-widgets to use __experimentalBatch().
- Fixes batch processing race condition by using batch.add( thunk ).
@noisysocks noisysocks force-pushed the try/simpler-batch-processing branch from 34db07a to 90535c1 Compare January 28, 2021 00:08
@noisysocks noisysocks merged commit 12d81cd into master Jan 28, 2021
@noisysocks noisysocks deleted the try/simpler-batch-processing branch January 28, 2021 01:42
@github-actions github-actions bot added this to the Gutenberg 9.9 milestone Jan 28, 2021
@TimothyBJacobs
Copy link
Member

Is this respecting the batch size limit? See https://make.wordpress.org/core/2020/11/20/rest-api-batch-framework-in-wordpress-5-6/

@noisysocks
Copy link
Member Author

No, oops. I'll turn your comment into an issue.

*
* - The thunk calls its `add` argument, or;
* - The thunk returns a promise and that promise resolves, or;
* - The thunk returns a non-promise.
Copy link
Member

Choose a reason for hiding this comment

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

@noisysocks can you clarify the intention of the second and third options here? it seems to suggest that we can do this…

batch.add( () => Promise.resolve({ path: '/v1/books', ... }) );

or this…

batch.add( () => ({ path: '/v1/books', ... }) );

…however, if we do that, then Promise.resolve(fetchOptionsProducer( queueForResolution)) will return the API request description and not the data requested in the batch operation.

  • Am I misunderstanding the comment?
  • Did we intend on eventually providing this functionality?
  • Is this an un-noticed bug in the code?

I'm working on the types for this module and got stuck trying to understand the purpose here. I'm inclined to remove the second and third options since the only examples and existing core code only demonstrate the first.

Copy link
Member Author

@noisysocks noisysocks Mar 25, 2022

Choose a reason for hiding this comment

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

…however, if we do that, then Promise.resolve(fetchOptionsProducer( queueForResolution)) will return the API request description and not the data requested in the batch operation.

I'm not sure what you mean here. What's fetchOptionsProducer?


From memory this was all about preventing run() from pausing infinitely if add() is called with a thunk and that thunk never calls the function passed to it.

The comment is describing the effect of this code below:

return Promise.resolve( inputOrThunk( add ) ).finally( () => {
	pending.delete( id );
} );
  • The thunk calls its add argument, or;
const batch = createBatch();
batch.add( ( add ) => async {
	await sleep( 100 );
	add( {} ); // run() will resume here
	await sleep( 100 );
} );
batch.run(); // will pause for 100 ms
  • The thunk returns a promise and that promise resolves, or;
const batch = createBatch();
batch.add( ( add ) => async {
	await sleep( 100 );
	await sleep( 100 );
	// run() will resume here when promise resolves
} );
batch.run(); // will pause for 200 ms
  • The thunk returns a non-promise.
const batch = createBatch();
batch.add( ( add ) => {
	// run() will resume here as a non-promise is returned
} );
batch.run(); // will pause for 0 ms

I'm working on the types for this module

I think it'd be something like this.

interface Batch<TInput, TOutput> {
    add<TThunkResult>( inputOrThunk: TInput|( ( add: ( input: TInput ) => Promise<TOutput> ) => TThunkResult|Promise<TThunkResult> ) ): Promise<TOutput>|Promise<TThunkResult>;
}

function createBatch<TInput, TOutput>( processor: ( inputs: TInput[] ) => Promise<{output?: TOutput, error?: any}[]> ): Batch<TInput, TOutput> {
}

I'm inclined to remove the second and third options since the only examples and existing core code only demonstrate the first.

Feel free to simplify! It's __experimental so should be okay to change. I believe the unit tests and usage in @wordpress/core-data cover everything we need createBatch to do.

reject( result.error );
isSuccess = false;
} else {
resolve( result?.output ?? result );
Copy link
Member

Choose a reason for hiding this comment

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

this seems to be a violation of the contract we provide for the output Promise. It seems possible that we added this so we could write tests that violate the input contract.

I noticed that the tests pass values like 1 and 2 and we test processors that return non-object. Are these intentionally valid use-cases of the function? if so, what are the reasons for allowing that? should we require that alternative processors conform to the { output } | { error } structure?

Do we know of any alternative processors in use (apart from the core tests here)?

Copy link
Member Author

@noisysocks noisysocks Mar 25, 2022

Choose a reason for hiding this comment

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

Good catch, this is an undocumented shorthand for specifying a result.

I'm fine with updating the tests and removing the shorthand so that this is simply resolve( result.output ).

Alternatively, processor could have a type of ( inputs: TInput[] ) => Promise<({output: TOutput}|{error: any}|TOutput)[]>. Why make it hard for ourselves though? 😀

Do we know of any alternative processors in use (apart from the core tests here)?

I believe only the default processor is used by Gutenberg. I'd be surprised if third parties have used this API as it's pretty niche.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Widgets Screen The block-based screen that replaced widgets.php. [Package] Core data /packages/core-data REST API Interaction Related to REST API [Type] New API New API to be used by plugin developers or package users.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Error when saving widgets Widgets editor: "There was an error. object Object" on save
8 participants