-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Lazy load post meta #4216
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
base: trunk
Are you sure you want to change the base?
Lazy load post meta #4216
Changes from all commits
e77768b
a9e45a1
b5f297e
efcdbc7
85ad4ae
9f19cac
77fa22e
753379d
093b224
ef8e797
b2e72e1
657aebb
ee9e65e
14aec68
d6d9934
8f33b9a
e61d194
55b32c3
4330c69
4f90281
046cdf5
cbe16f1
dc7344a
a077f46
f4ec367
59a3aee
a6b8d34
4e3a8ec
79f93c1
434cb55
95df19a
ebf588e
7893aee
01f785d
34855d1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -660,6 +660,7 @@ public function fill_query_vars( $query_vars ) { | |||||||||
| * @since 5.3.0 Introduced the `$meta_type_key` parameter. | ||||||||||
| * @since 6.1.0 Introduced the `$update_menu_item_cache` parameter. | ||||||||||
| * @since 6.2.0 Introduced the `$search_columns` parameter. | ||||||||||
| * @since 6.8.0 Introduced the `$lazy_load_post_meta` parameter. | ||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This needs updating now. |
||||||||||
| * | ||||||||||
| * @param string|array $query { | ||||||||||
| * Optional. Array or string of Query parameters. | ||||||||||
|
|
@@ -796,6 +797,8 @@ public function fill_query_vars( $query_vars ) { | |||||||||
| * disable cache priming for term meta, so that each | ||||||||||
| * get_term_meta() call will hit the database. | ||||||||||
| * Defaults to the value of `$update_post_term_cache`. | ||||||||||
| * @type bool $lazy_load_post_meta Whether to lazy-load post meta. If set to false, post meta priming will | ||||||||||
| * fallback to the default behavior of priming post meta. | ||||||||||
|
Comment on lines
+800
to
+801
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the following changes better reflect the current state of the logic and resolves conversations here and here.
Suggested change
|
||||||||||
| * @type int $w The week number of the year. Default empty. Accepts numbers 0-53. | ||||||||||
| * @type int $year The four-digit year. Default empty. Accepts any four-digit year. | ||||||||||
| * } | ||||||||||
|
|
@@ -1291,7 +1294,7 @@ public function parse_tax_query( &$q ) { | |||||||||
| if ( ! empty( $q['category__not_in'] ) ) { | ||||||||||
| $q['category__not_in'] = array_map( 'absint', array_unique( (array) $q['category__not_in'] ) ); | ||||||||||
| sort( $q['category__not_in'] ); | ||||||||||
| $tax_query[] = array( | ||||||||||
| $tax_query[] = array( | ||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is one that is not applying because it was already fixed |
||||||||||
| 'taxonomy' => 'category', | ||||||||||
| 'terms' => $q['category__not_in'], | ||||||||||
| 'operator' => 'NOT IN', | ||||||||||
|
|
@@ -1360,7 +1363,7 @@ public function parse_tax_query( &$q ) { | |||||||||
| if ( ! empty( $q['tag__not_in'] ) ) { | ||||||||||
| $q['tag__not_in'] = array_map( 'absint', array_unique( (array) $q['tag__not_in'] ) ); | ||||||||||
| sort( $q['tag__not_in'] ); | ||||||||||
| $tax_query[] = array( | ||||||||||
| $tax_query[] = array( | ||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the second that is not applying |
||||||||||
| 'taxonomy' => 'post_tag', | ||||||||||
| 'terms' => $q['tag__not_in'], | ||||||||||
| 'operator' => 'NOT IN', | ||||||||||
|
|
@@ -1996,6 +1999,15 @@ public function get_posts() { | |||||||||
| $q['update_post_meta_cache'] = true; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| // Default lazy loading post meta to false, as this `update_post_meta_cache` defaults to true. | ||||||||||
| // To correctly use the lazy_load_post_meta parameter, you must set update_post_meta_cache to false first. | ||||||||||
| if ( ! isset( $q['lazy_load_post_meta'] ) ) { | ||||||||||
| $q['lazy_load_post_meta'] = false; | ||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Per the DocBlock, shouldn't this be the following?
Suggested change
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rather than just removing the docs about the default in 4e3a8ec, can it be updated to be accurate?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @joemcgill I am not sure what is being asked here. |
||||||||||
| } elseif ( $q['lazy_load_post_meta'] ) { | ||||||||||
| // Lazy loading post meta only works if post meta caches are not primed. | ||||||||||
| $q['update_post_meta_cache'] = false; | ||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For term meta, lazy loading requires term cache priming. Can you add an inline comment about why this is different? Also, the Docblock states...
...but that doesn't seem to be implemented.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @spacedmonkey it still doesn't seem that this comment was addressed:
Am I missing something?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @joemcgill I have added some inline comments. |
||||||||||
| } | ||||||||||
|
|
||||||||||
| if ( ! isset( $q['post_type'] ) ) { | ||||||||||
| if ( $this->is_search ) { | ||||||||||
| $q['post_type'] = 'any'; | ||||||||||
|
|
@@ -3295,6 +3307,10 @@ public function get_posts() { | |||||||||
| $this->post_count = count( $this->posts ); | ||||||||||
| $this->set_found_posts( $q, $limits ); | ||||||||||
|
|
||||||||||
| if ( $q['lazy_load_post_meta'] ) { | ||||||||||
| wp_lazyload_post_meta( $this->posts ); | ||||||||||
| } | ||||||||||
|
|
||||||||||
| if ( $q['cache_results'] && $id_query_is_cacheable ) { | ||||||||||
| $cache_value = array( | ||||||||||
| 'posts' => $this->posts, | ||||||||||
|
|
@@ -3333,6 +3349,10 @@ public function get_posts() { | |||||||||
| // Prime post parent caches, so that on second run, there is not another database query. | ||||||||||
| wp_cache_add_multiple( $post_parents_cache, 'posts' ); | ||||||||||
|
|
||||||||||
| if ( $q['lazy_load_post_meta'] ) { | ||||||||||
| wp_lazyload_post_meta( $post_ids ); | ||||||||||
| } | ||||||||||
|
|
||||||||||
| if ( $q['cache_results'] && $id_query_is_cacheable ) { | ||||||||||
| $cache_value = array( | ||||||||||
| 'posts' => $post_ids, | ||||||||||
|
|
@@ -3587,6 +3607,7 @@ public function get_posts() { | |||||||||
| 'update_post_meta_cache' => $q['update_post_meta_cache'], | ||||||||||
| 'update_post_term_cache' => $q['update_post_term_cache'], | ||||||||||
| 'lazy_load_term_meta' => $q['lazy_load_term_meta'], | ||||||||||
| 'lazy_load_post_meta' => $q['lazy_load_post_meta'], | ||||||||||
| ) | ||||||||||
| ); | ||||||||||
|
|
||||||||||
|
|
@@ -3644,6 +3665,11 @@ public function get_posts() { | |||||||||
| wp_queue_posts_for_term_meta_lazyload( $this->posts ); | ||||||||||
| } | ||||||||||
|
|
||||||||||
| if ( $q['lazy_load_post_meta'] ) { | ||||||||||
| $post_ids = wp_list_pluck( $this->posts, 'ID' ); | ||||||||||
| wp_lazyload_post_meta( $post_ids ); | ||||||||||
| } | ||||||||||
|
|
||||||||||
| return $this->posts; | ||||||||||
| } | ||||||||||
|
|
||||||||||
|
|
@@ -3744,6 +3770,9 @@ public function the_post() { | |||||||||
| $post_ids = array_filter( $post_ids ); | ||||||||||
| if ( $post_ids ) { | ||||||||||
| _prime_post_caches( $post_ids, $this->query_vars['update_post_term_cache'], $this->query_vars['update_post_meta_cache'] ); | ||||||||||
| if ( $this->query_vars['lazy_load_post_meta'] ) { | ||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This changeset [59993] brought major changes in this section. |
||||||||||
| wp_lazyload_post_meta( $post_ids ); | ||||||||||
| } | ||||||||||
| } | ||||||||||
| $post_objects = array_map( 'get_post', $this->posts ); | ||||||||||
| update_post_author_caches( $post_objects ); | ||||||||||
|
|
@@ -4935,6 +4964,7 @@ protected function generate_cache_key( array $args, $sql ) { | |||||||||
| $args['cache_results'], | ||||||||||
| $args['fields'], | ||||||||||
| $args['lazy_load_term_meta'], | ||||||||||
| $args['lazy_load_post_meta'], | ||||||||||
| $args['update_post_meta_cache'], | ||||||||||
| $args['update_post_term_cache'], | ||||||||||
| $args['update_menu_item_cache'], | ||||||||||
|
|
||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2665,6 +2665,21 @@ function get_post_meta( $post_id, $key = '', $single = false ) { | |
| return get_metadata( 'post', $post_id, $key, $single ); | ||
| } | ||
|
|
||
| /** | ||
| * Queue post meta for lazy-loading. | ||
| * | ||
| * @since 6.8.0 | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This needs updating now. |
||
| * | ||
| * @param array $post_ids List of post IDs. | ||
| */ | ||
| function wp_lazyload_post_meta( array $post_ids ) { | ||
| if ( empty( $post_ids ) ) { | ||
| return; | ||
| } | ||
| $lazyloader = wp_metadata_lazyloader(); | ||
| $lazyloader->queue_objects( 'post', $post_ids ); | ||
| } | ||
|
|
||
| /** | ||
| * Updates a post meta field based on the given post ID. | ||
| * | ||
|
|
@@ -7763,7 +7778,8 @@ function update_post_parent_caches( $posts ) { | |
| $parent_ids = array_unique( array_filter( $parent_ids ) ); | ||
|
|
||
| if ( ! empty( $parent_ids ) ) { | ||
| _prime_post_caches( $parent_ids, false ); | ||
| _prime_post_caches( $parent_ids, false, false ); | ||
| wp_lazyload_post_meta( $parent_ids ); | ||
| } | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| <?php | ||
|
|
||
| /** | ||
| * @group query | ||
| * @group meta | ||
| */ | ||
| class Tests_Lazy_Load_Post_Meta extends WP_UnitTestCase { | ||
| /** | ||
| * Post IDs. | ||
| * | ||
| * @var int[] | ||
| */ | ||
| private static $post_ids = array(); | ||
|
|
||
| public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) { | ||
| // Register CPT for use with shared fixtures. | ||
| register_post_type( 'wptests_pt' ); | ||
|
|
||
| self::$post_ids = $factory->post->create_many( 5, array( 'post_type' => 'wptests_pt' ) ); | ||
| foreach ( self::$post_ids as $post_id ) { | ||
| update_post_meta( $post_id, 'foo', 'bar' ); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * @dataProvider data_lazy_load_post_meta | ||
| * @ticket 57496 | ||
| */ | ||
| public function test_lazy_load_post_meta( $query_args ) { | ||
| wp_cache_delete_multiple( self::$post_ids, 'posts' ); | ||
| wp_cache_delete_multiple( self::$post_ids, 'post_meta' ); | ||
| $action1 = new MockAction(); | ||
| $action2 = new MockAction(); | ||
| add_filter( 'update_post_metadata_cache', array( $action1, 'filter' ), 10, 2 ); | ||
| add_action( 'metadata_lazyloader_queued_objects', array( $action2, 'action' ) ); | ||
|
|
||
| new WP_Query( $query_args ); | ||
|
|
||
| $args1 = $action1->get_args(); | ||
| $args2 = $action2->get_args(); | ||
| $last = end( $args2 ); | ||
| $this->assertSameSets( self::$post_ids, $last[0], 'wp_lazyload_post_meta() was not executed.' ); | ||
| $this->assertSameSets( array(), $args1, 'update_meta_cache() was executed.' ); | ||
| $num_queries = get_num_queries(); | ||
| get_post_meta( self::$post_ids[0], 'foo', true ); | ||
| $this->assertSame( $num_queries + 1, get_num_queries(), 'wp_lazyload_post_meta() was not executed.' ); | ||
| $args1 = $action1->get_args(); | ||
| $last = end( $args1 ); | ||
| $this->assertSameSets( self::$post_ids, $last[1], 'update_meta_cache() was not executed.' ); | ||
| } | ||
|
|
||
| /** | ||
| * Provides test data for lazy loading post metadata. | ||
| * | ||
| * @return array | ||
| */ | ||
| public function data_lazy_load_post_meta() { | ||
| return array( | ||
| 'lazy load post meta' => array( | ||
| array( | ||
| 'post_type' => 'wptests_pt', | ||
| 'lazy_load_post_meta' => true, | ||
| ), | ||
| ), | ||
| 'lazy load post meta fields id' => array( | ||
| array( | ||
| 'post_type' => 'wptests_pt', | ||
| 'fields' => 'ids', | ||
| 'lazy_load_post_meta' => true, | ||
| ), | ||
| ), | ||
| 'lazy load post meta fields id=>parent' => array( | ||
| array( | ||
| 'post_type' => 'wptests_pt', | ||
| 'fields' => 'id=>parent', | ||
| 'lazy_load_post_meta' => true, | ||
| ), | ||
| ), | ||
| 'lazy load post meta - update_post_meta_cache true' => array( | ||
| array( | ||
| 'post_type' => 'wptests_pt', | ||
| 'update_post_meta_cache' => true, | ||
| 'lazy_load_post_meta' => true, | ||
| ), | ||
| ), | ||
| 'lazy load post meta - update_post_meta_cache false' => array( | ||
| array( | ||
| 'post_type' => 'wptests_pt', | ||
| 'update_post_meta_cache' => false, | ||
| 'lazy_load_post_meta' => true, | ||
| ), | ||
| ), | ||
| 'lazy load post meta - cache_results false' => array( | ||
| array( | ||
| 'post_type' => 'wptests_pt', | ||
| 'cache_results' => false, | ||
| 'lazy_load_post_meta' => true, | ||
| ), | ||
| ), | ||
| ); | ||
| } | ||
| } |
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.
@spacedmonkey Re #4216 (comment), I think the code should simply be this to see if a database query is required. If not, it bypasses processing the queue, if so it adds the object ID and continues lazy loading.
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.
@peterwilsoncc This happens in here
wordpress-develop/src/wp-includes/meta.php
Lines 1168 to 1189 in bcb59bf
So if it first checks if the id is in cache, then if not, then it will do a database query.
Add this check, just repeats to the logic.
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.
It's not quite the same.
get_metadata( type, **cached** object ID ...)will process the queue, even though a database query is not required. This is because"get_{$meta_type}_metadata"fires prior to checking the objects cache.As you've been trying to avoid unnecessary database queries while getting post meta data, this acheives that by only processing the queue if a database query will be made.