Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
e77768b
Lazy load post meta
spacedmonkey Feb 14, 2023
a9e45a1
Merge branch 'trunk' into fix/lazy-load-post-meta
spacedmonkey Mar 9, 2023
b5f297e
Merge branch 'trunk' into fix/lazy-load-post-meta
spacedmonkey Mar 10, 2023
efcdbc7
Merge branch 'trunk' into fix/lazy-load-post-meta
spacedmonkey Mar 29, 2023
85ad4ae
Rebase
spacedmonkey Mar 29, 2023
9f19cac
Merge branch 'trunk' into fix/lazy-load-post-meta
spacedmonkey Apr 21, 2023
77fa22e
Fix
spacedmonkey Apr 21, 2023
753379d
Merge branch 'trunk' into fix/lazy-load-post-meta
spacedmonkey May 23, 2023
093b224
Merge branch 'trunk' into fix/lazy-load-post-meta
spacedmonkey Jul 7, 2023
ef8e797
Merge branch 'trunk' into fix/lazy-load-post-meta
spacedmonkey Jul 13, 2023
b2e72e1
Merge branch 'trunk' into fix/lazy-load-post-meta
spacedmonkey Jun 12, 2024
657aebb
Update callback name and implement lazyload_post_meta function
spacedmonkey Jun 12, 2024
ee9e65e
Update expected database queries in tests
spacedmonkey Jun 12, 2024
14aec68
Merge branch 'trunk' into fix/lazy-load-post-meta
spacedmonkey Oct 9, 2024
d6d9934
Add filter for REST API menu read access check
spacedmonkey Oct 9, 2024
8f33b9a
Update post meta cache function call
spacedmonkey Oct 9, 2024
e61d194
Merge branch 'trunk' into fix/lazy-load-post-meta
spacedmonkey Nov 17, 2024
55b32c3
Revert these changes.
spacedmonkey Nov 17, 2024
4330c69
Apply suggestions from code review
spacedmonkey Nov 17, 2024
4f90281
Merge branch 'trunk' into fix/lazy-load-post-meta
spacedmonkey Dec 3, 2024
046cdf5
Add $lazy_load_post_meta parameter to WP_Query and use it in post con…
spacedmonkey Dec 3, 2024
cbe16f1
Add $lazy_load_post_meta parameter in wp_get_post_revisions.
spacedmonkey Dec 3, 2024
dc7344a
Fix tests.
spacedmonkey Dec 4, 2024
a077f46
Improve tests.
spacedmonkey Dec 4, 2024
f4ec367
Fix tests again.
spacedmonkey Dec 4, 2024
59a3aee
Add tests.
spacedmonkey Dec 4, 2024
a6b8d34
wp_dashboard_recent_posts lazy load post meta.
spacedmonkey Dec 4, 2024
4e3a8ec
Apply suggestions from code review
spacedmonkey Jan 12, 2025
79f93c1
Apply suggestions from code review
spacedmonkey Jan 31, 2025
434cb55
Merge branch 'trunk' into fix/lazy-load-post-meta
spacedmonkey Jan 31, 2025
95df19a
Merge branch 'trunk' into fix/lazy-load-post-meta
spacedmonkey Feb 22, 2025
ebf588e
Refactor lazy-loading to unify metadata callback.
spacedmonkey Feb 22, 2025
7893aee
Simplify post meta priming behavior and adjust formatting.
spacedmonkey Feb 22, 2025
01f785d
Set default lazy loading for post meta to false
spacedmonkey Feb 22, 2025
34855d1
Fix alignment in lazy load post meta test array.
spacedmonkey Feb 22, 2025
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
41 changes: 5 additions & 36 deletions src/wp-includes/class-wp-metadata-lazyloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public function __construct() {
),
'post' => array(
'filter' => 'get_post_metadata',
'callback' => array( $this, 'lazyload_post_meta' ),
'callback' => array( $this, 'lazyload_meta_callback' ),
),
'blog' => array(
'filter' => 'get_blog_metadata',
Expand Down Expand Up @@ -167,41 +167,6 @@ public function lazyload_comment_meta( $check ) {
return $this->lazyload_meta_callback( $check, 0, '', false, 'comment' );
}

/**
* Lazy-loads post meta for queued posts.
*
* This method is public so that it can be used as a filter callback. As a rule, there
* is no need to invoke it directly.
*
* @since 6.8.0
*
* @param mixed $check The `$check` param passed from the 'get_*_metadata' hook.
* @param int $object_id ID of the object metadata is for.
* @param string $meta_key Unused.
* @param bool $single Unused.
* @param string $meta_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
* or any other object type with an associated meta table.
* @return mixed In order not to short-circuit `get_metadata()`. Generally, this is `null`, but it could be
* another value if filtered by a plugin.
*/
public function lazyload_post_meta( $check, $object_id, $meta_key, $single, $meta_type ) {
if ( empty( $this->pending_objects[ $meta_type ] ) ) {
return $check;
}

$object_ids = array_keys( $this->pending_objects[ $meta_type ] );
if ( $object_id && ! in_array( $object_id, $object_ids, true ) ) {
return $check;
}

update_meta_cache( $meta_type, $object_ids );

// No need to run again for this set of objects.
$this->reset_queue( $meta_type );

return $check;
}

/**
* Lazy-loads meta for queued objects.
*
Expand All @@ -226,6 +191,10 @@ public function lazyload_meta_callback( $check, $object_id, $meta_key, $single,

$object_ids = array_keys( $this->pending_objects[ $meta_type ] );
if ( $object_id && ! in_array( $object_id, $object_ids, true ) ) {
// Only load in the post meta value is in the queue.
if ( 'post' === $meta_type ) {
return $check;
}
Comment on lines +194 to +197
Copy link
Contributor

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.

Suggested change
// Only load in the post meta value is in the queue.
if ( 'post' === $meta_type ) {
return $check;
}
if ( false !== wp_cache_get( $object_id, $meta_type . '_meta' ) ) {
// Object already in cache, no database query will be made.
return $check;
}

Copy link
Member Author

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

$cache_group = $meta_type . '_meta';
$non_cached_ids = array();
$cache = array();
$cache_values = wp_cache_get_multiple( $object_ids, $cache_group );
foreach ( $cache_values as $id => $cached_object ) {
if ( false === $cached_object ) {
$non_cached_ids[] = $id;
} else {
$cache[ $id ] = $cached_object;
}
}
if ( empty( $non_cached_ids ) ) {
return $cache;
}
// Get meta info.
$id_list = implode( ',', $non_cached_ids );
$id_column = ( 'user' === $meta_type ) ? 'umeta_id' : 'meta_id';
$meta_list = $wpdb->get_results( "SELECT $column, meta_key, meta_value FROM $table WHERE $column IN ($id_list) ORDER BY $id_column ASC", ARRAY_A );

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.

Copy link
Contributor

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.

$object_ids[] = $object_id;
}

Expand Down
12 changes: 7 additions & 5 deletions src/wp-includes/class-wp-query.php
Original file line number Diff line number Diff line change
Expand Up @@ -797,9 +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. Setting to false will
* disable cache priming for post meta, so that each
* get_post_meta() call will hit the database.
* @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
Copy link
Member

Choose a reason for hiding this comment

The 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 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.
* @type bool $lazy_load_post_meta Whether to lazy-load post meta. When set to true, post meta priming will
* be disabled. Default false.

* @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.
* }
Expand Down Expand Up @@ -1295,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(
Copy link
Member

Choose a reason for hiding this comment

The 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',
Expand Down Expand Up @@ -1364,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(
Copy link
Member

Choose a reason for hiding this comment

The 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',
Expand Down Expand Up @@ -2000,9 +1999,12 @@ 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;
Copy link
Member

Choose a reason for hiding this comment

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

Per the DocBlock, shouldn't this be the following?

Suggested change
$q['lazy_load_post_meta'] = false;
$q['lazy_load_post_meta'] = $q['update_post_meta_cache'];

Copy link
Member

Choose a reason for hiding this comment

The 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?

Copy link
Member Author

Choose a reason for hiding this comment

The 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;
Copy link
Member

Choose a reason for hiding this comment

The 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...

Setting to false will disable cache priming for post meta, so that each get_post_meta() call will hit the database.

...but that doesn't seem to be implemented.

Copy link
Member

Choose a reason for hiding this comment

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

@spacedmonkey it still doesn't seem that this comment was addressed:

Also, the Docblock states...

Setting to false will disable cache priming for post meta, so that each get_post_meta() call will hit the database.

...but that doesn't seem to be implemented.

Am I missing something?

Copy link
Member Author

Choose a reason for hiding this comment

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

@joemcgill I have added some inline comments.

}

Expand Down
2 changes: 1 addition & 1 deletion tests/phpunit/tests/query/cacheResults.php
Original file line number Diff line number Diff line change
Expand Up @@ -720,7 +720,7 @@ public function data_query_cache_duplicate() {
'update_menu_item_cache' => false,
),
),
'lazy load post meta' => array(
'lazy load post meta' => array(
'query_vars1' => array( 'lazy_load_post_meta' => true ),
'query_vars2' => array( 'lazy_load_post_meta' => false ),
),
Expand Down
Loading