-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
Permit unbounded per_page=-1 requests for Pages and Shared Blocks #6657
Conversation
Test failure was unrelated; I cleared cache and restarted. |
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.
@danielbachhuber I don't think I'm the best person to review this PR.
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 doesn't seem to answer UX questions around large lists or how to approach this, and returning an unbounded list of authors/block types (or really, anything) is dangerous.
The trac issue linked to in this code also mentions that unbounded requests can cause performance issues. I don't see how the proposed patch in Core (https://core.trac.wordpress.org/ticket/43998) or this patch prevent DOS issues from unbounded queries. Aside from straight-up DOS (exhausting the DB, whatever else), this could result in slow load times which would negatively impact Gutenberg UX.
This solution seems to hope that:
100000
is enough for$prepared_args['posts_per_page']
–https://github.com/WordPress/gutenberg/pull/6657/files#diff-d0c65e7ac505d44d8571ddaffc510d98R494- We don't need to worry about the performance impact this will have
I understand the existing discussion around this issue has been ongoing for awhile and it's quite a frustrating bug, but I'm not sure this addresses many of the issues raised.
$post_types = array( 'page', 'wp_block' ); | ||
if ( in_array( $post_type->name, $post_types, true ) | ||
&& isset( $query_params['per_page'] ) ) { | ||
// Change from '1' to '-1', which means unlimited. |
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.
I don't quite understand this comment; where is '1'
being checked for?
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.
where is
'1'
being checked for?
It doesn't need to be checked for. '1'
is the default value: https://github.com/WordPress/WordPress/blob/2f792d442bf771a3aade170cc9cae459f024c57b/wp-includes/rest-api/endpoints/class-wp-rest-controller.php#L321
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.
I don't see any checks at all for minimum
though.
Maybe I just don't get the query params variable here but it looks like it's a dictionary and here you're just checking for $query_params['per_page']
, not $query_params['per_page']['minimum']
.
It would be at least handy to say // Change from default value '1' to '-1', which means unlimited.
That said this code strikes me as assuming minimum is set to the default if set at all which I can't tell from here.
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.
I'm not sure I follow. Can you create a PR against this PR with your suggested changes?
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.
Oh wait, I understand the code now but it was not obvious at first. I'd suggest changing this function to add a few more comments for context:
function gutenberg_filter_post_collection_parameters( $query_params, $post_type ) {
$post_types = array( 'page', 'wp_block' );
// HACK: If 'per_page' is set, ignore it and change the items returned
// per-page to be '-1'.
// See: https://github.com/WordPress/gutenberg/issues/6180#issuecomment-384511059
if ( in_array( $post_type->name, $post_types, true )
&& isset( $query_params['per_page'] ) ) {
// Change from '1' (default) to '-1', which means unlimited.
$query_params['per_page']['minimum'] = -1;
// Default sanitize callback is 'absint', which won't work in our case.
$query_params['per_page']['sanitize_callback'] = 'rest_sanitize_request_arg';
}
return $query_params;
}
That seems to be the intent of the code, right?
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.
I don't think that comment is right. This is adjusting the collection params schema, not the actual request arguments. The schema ( per_page
) is validated by WordPress itself in WP_REST_Request
using rest_validate_value_from_schema
.
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.
Ah, gotcha; the structure of these filters is unclear to me as I'm new to the project. Thanks for the explanation 👍
// Avoid triggering 'rest_post_invalid_page_number' error | ||
// which will need to be addressed in https://core.trac.wordpress.org/ticket/43998. | ||
if ( -1 === $prepared_args['posts_per_page'] ) { | ||
$prepared_args['posts_per_page'] = 100000; |
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 looks like a hack that will be hard to debug as there isn't any logging around it.
Also: it seems unbounded requests are only allowed for authorised users... seems like they need edit_posts
to be able to use this feature but just wanted to make sure that's also a requirement to use Gutenberg (sorry, I'm new here!) or this will have unpredictable results.
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 looks like a hack that will be hard to debug as there isn't any logging around it.
Yes. It's a hack that will only exist until the patch I've yet to prepare for https://core.trac.wordpress.org/ticket/43998 lands in WP 4.9.7
Also: it seems unbounded requests are only allowed for authorised users... seems like they need
edit_posts
to be able to use this feature but just wanted to make sure that's also a requirement to use Gutenberg (sorry, I'm new here!) or this will have unpredictable results.
Correct. edit_posts
is a reasonable minimum capability assumption for Gutenberg.
Correct, this is intentional. See conversation in #6180 (comment) |
I read through the issues linked and I think I accidentally skimmed that comment, my bad. I guess right now this is broken for anyone with lists over So it is a definite improvement, good point. There are a few code things I don't quite grok that I think could at least use some comments but I'll withdraw my "no unbounded results" request 😄 |
@danielbachhuber I'm still concerned here around scalability. Does this still work if the site has 2,000 pages? what is memory footprint client/server wise to fulfill these large request? |
Do your scalability concerns with this pull request differ from those with the
Yes, it works in my testing. The REST API request takes ~7s to fulfill.
Is memory utilization a limiting factor here? |
yes, I'm concerned about the additional client side memory requirements added by keeping all of the records in the app memory/state.
good to hear. i hesitate to ask about 20,000 or 200,000. |
How much additional memory is this, over the data that's already present in |
> How much additional memory is this, over the data that's already present in <select>? twice as much vs a select? i'm comparing this to a more search/request based solution that never loads the full set
no idea what the percentage is, certainly the total number is not insignificant. For these users, a dropdown may be unusable.
I'm not sure if its a concern we should ignore. If we do take this approach, I'd still love to work on a more scalable search based selector. Since this pattern of selecting from a (potentially very large) list is something we are likely to repeat in different contexts across Gutenberg, I'd love to see it solved in a way that worked very well for all cases. My hope is that something similar to the searchable select i suggested in #5921 does. |
Just to clarify, is this a hypothetical concern, or something you've tested and have data / methodology for?
This is an incorrect characterization of my perspective. Rather, I'm suggesting that:
None of this precludes producing a "better" solution in the future, particularly if new information presents itself. As I mentioned in #5921, changing the UI/UX of these components will need design first, and then be validated for accessibility. This work should be done before development. |
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.
Just a minor strict code issue. I think the approach is fine. For core, this should obviously become part of the respective REST API controllers.
lib/rest-api.php
Outdated
'/wp/v2/pages', | ||
'/wp/v2/users', | ||
); | ||
if ( in_array( $request->get_route(), $routes ) ) { |
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 should perform a strict check.
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.
Feedback was addressed
Going ahead and landing this. We can iterate on the UX as solutions become available. |
@danielbachhuber rather than this "unlimited but not really unlimited" approach that uses -1 as a special value, I think it would be better to set a higher limit for users who have |
I meant to update this PR to say I approve of the changes after seeing my comments addressed, so retroactive 👍 from me, sorry about that! 😄 |
@nylen Can you open new issue with the specifics of your proposal? |
Description
Permits requests of
per_page=-1
to/wp/v2/pages
and/wp/v2/blocks
in order to fetch all available items; updates corresponding Gutenberg components to fetch all items.Fixes #6487
Fixes #4632
Related #6627
See #6180 (comment)
How has this been tested?
I generated 200 pages with:
When I access the Page editor, I can see all items in the dropdown:
Similarly, I created more than 10 shared blocks and can see all of them in the inserter UI:
Checklist: