Skip to content

Commit 790e52e

Browse files
committed
Users: Lazy-load user meta.
In [36566], a framework for lazily loading metadata was introduced, initially supporting term and comment meta. This commit extends that support to user meta. User meta can contain a large amount of data that is not always needed, particularly on the front end. To address this, cache_users() now calls the new function wp_lazyload_user_meta(). This function accepts an array of user IDs and adds them to the queue of metadata to be lazily loaded. Follows on from [55671], [55747]. Props spacedmonkey, westonruter. Fixes #63021. git-svn-id: https://develop.svn.wordpress.org/trunk@60989 602fd350-edb4-49c9-b593-d223f7449a82
1 parent 1dff73d commit 790e52e

File tree

8 files changed

+121
-9
lines changed

8 files changed

+121
-9
lines changed

src/wp-includes/class-wp-metadata-lazyloader.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ public function __construct() {
6565
'filter' => 'get_blog_metadata',
6666
'callback' => array( $this, 'lazyload_meta_callback' ),
6767
),
68+
'user' => array(
69+
'filter' => 'get_user_metadata',
70+
'callback' => array( $this, 'lazyload_meta_callback' ),
71+
),
6872
);
6973
}
7074

src/wp-includes/pluggable.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,8 @@ function get_user_by( $field, $value ) {
125125
function cache_users( $user_ids ) {
126126
global $wpdb;
127127

128-
update_meta_cache( 'user', $user_ids );
128+
$user_ids = array_unique( array_map( 'intval', $user_ids ), SORT_NUMERIC );
129+
wp_lazyload_user_meta( $user_ids );
129130

130131
$clean = _get_non_cached_ids( $user_ids, 'users' );
131132

src/wp-includes/user.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1320,6 +1320,21 @@ function update_user_meta( $user_id, $meta_key, $meta_value, $prev_value = '' )
13201320
return update_metadata( 'user', $user_id, $meta_key, $meta_value, $prev_value );
13211321
}
13221322

1323+
/**
1324+
* Queue user meta for lazy-loading.
1325+
*
1326+
* @since 6.9.0
1327+
*
1328+
* @param int[] $user_ids List of user IDs.
1329+
*/
1330+
function wp_lazyload_user_meta( array $user_ids ) {
1331+
if ( empty( $user_ids ) ) {
1332+
return;
1333+
}
1334+
$lazyloader = wp_metadata_lazyloader();
1335+
$lazyloader->queue_objects( 'user', $user_ids );
1336+
}
1337+
13231338
/**
13241339
* Counts number of users who have each of the user roles.
13251340
*

tests/phpunit/includes/abstract-testcase.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,7 @@ protected function reset_lazyload_queue() {
303303
$lazyloader->reset_queue( 'term' );
304304
$lazyloader->reset_queue( 'comment' );
305305
$lazyloader->reset_queue( 'blog' );
306+
$lazyloader->reset_queue( 'user' );
306307
}
307308

308309
/**

tests/phpunit/tests/post/updatePostAuthorCaches.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,28 @@ public function test_update_post_author_caches() {
6767
$q->the_post();
6868
}
6969

70+
$this->assertSame( 0, $action->get_call_count(), 'Ensure that user meta are not primed' );
71+
}
72+
73+
/**
74+
* @ticket 63021
75+
*/
76+
public function test_update_post_author_caches_force_load_meta() {
77+
$action = new MockAction();
78+
add_filter( 'update_user_metadata_cache', array( $action, 'filter' ), 10, 2 );
79+
80+
$q = new WP_Query(
81+
array(
82+
'post_type' => 'post',
83+
'posts_per_page' => self::$post_author_count,
84+
)
85+
);
86+
87+
while ( $q->have_posts() ) {
88+
$q->the_post();
89+
get_the_author_meta(); // Force loading of author meta.
90+
}
91+
7092
$args = $action->get_args();
7193
$last_args = end( $args );
7294

tests/phpunit/tests/query/cacheResults.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1982,11 +1982,10 @@ public function test_author_cache_warmed_by_the_loop( $fields ) {
19821982
$query_1->the_post();
19831983
$num_loop_queries = get_num_queries() - $start_loop_queries;
19841984
/*
1985-
* Two expected queries:
1986-
* 1: User meta data,
1987-
* 2: User data.
1985+
* One expected query:
1986+
* 1: User data.
19881987
*/
1989-
$this->assertSame( 2, $num_loop_queries, 'Unexpected number of queries while initializing the loop.' );
1988+
$this->assertSame( 1, $num_loop_queries, 'Unexpected number of queries while initializing the loop.' );
19901989

19911990
$start_author_queries = get_num_queries();
19921991
get_user_by( 'ID', self::$author_id );

tests/phpunit/tests/query/thePost.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -265,10 +265,10 @@ public function test_the_loop_primes_the_author_cache( $fields, $expected_querie
265265
*/
266266
public function data_the_loop_fields() {
267267
return array(
268-
'all fields' => array( 'all', 2 ),
269-
'all fields (empty fields)' => array( '', 2 ),
270-
'post IDs' => array( 'ids', 4 ),
271-
'post ids and parent' => array( 'id=>parent', 4 ),
268+
'all fields' => array( 'all', 1 ),
269+
'all fields (empty fields)' => array( '', 1 ),
270+
'post IDs' => array( 'ids', 3 ),
271+
'post ids and parent' => array( 'id=>parent', 3 ),
272272
);
273273
}
274274

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?php
2+
3+
/**
4+
* @group user
5+
* @covers ::wp_lazyload_user_meta
6+
*/
7+
class Tests_User_Lazy_Load_Meta extends WP_UnitTestCase {
8+
9+
/**
10+
* @ticket 63021
11+
*/
12+
public function test_lazy_load_meta() {
13+
$user_ids = self::factory()->user->create_many( 3 );
14+
// Clear any existing cache.
15+
wp_cache_delete_multiple( $user_ids, 'user_meta' );
16+
wp_lazyload_user_meta( $user_ids );
17+
$filter = new MockAction();
18+
add_filter( 'update_user_metadata_cache', array( $filter, 'filter' ), 10, 2 );
19+
get_user_meta( $user_ids[0] );
20+
21+
$args = $filter->get_args();
22+
$first = reset( $args );
23+
$load_user_ids = end( $first );
24+
$this->assertSameSets( $user_ids, $load_user_ids, 'Ensure all user IDs are loaded in a single batch' );
25+
}
26+
27+
/**
28+
* @ticket 63021
29+
*/
30+
public function test_lazy_load_meta_sets() {
31+
$user_ids1 = self::factory()->user->create_many( 3 );
32+
$user_ids2 = self::factory()->user->create_many( 3 );
33+
$user_ids = array_merge( $user_ids1, $user_ids2 );
34+
// Clear any existing cache.
35+
wp_cache_delete_multiple( $user_ids, 'user_meta' );
36+
wp_lazyload_user_meta( $user_ids );
37+
$filter = new MockAction();
38+
add_filter( 'update_user_metadata_cache', array( $filter, 'filter' ), 10, 2 );
39+
get_user_meta( $user_ids[0] );
40+
41+
$args = $filter->get_args();
42+
$first = reset( $args );
43+
$load_user_ids = end( $first );
44+
$this->assertSameSets( $user_ids, $load_user_ids, 'Ensure all user IDs are loaded in a single batch' );
45+
}
46+
47+
/**
48+
* @ticket 63021
49+
*/
50+
public function test_lazy_load_meta_not_in_queue() {
51+
$user_ids1 = self::factory()->user->create_many( 3 );
52+
$user_ids2 = self::factory()->user->create_many( 3 );
53+
$user_ids = array_merge( $user_ids1, $user_ids2 );
54+
$new_user_id = self::factory()->user->create();
55+
wp_lazyload_user_meta( $user_ids );
56+
// Add a user not in the lazy load queue.
57+
$user_ids[] = $new_user_id;
58+
// Clear any existing cache including the new user not in the queue.
59+
wp_cache_delete_multiple( $user_ids, 'user_meta' );
60+
61+
$filter = new MockAction();
62+
add_filter( 'update_user_metadata_cache', array( $filter, 'filter' ), 10, 2 );
63+
get_user_meta( $new_user_id );
64+
65+
$args = $filter->get_args();
66+
$first = reset( $args );
67+
$load_user_ids = end( $first );
68+
$this->assertSameSets( $user_ids, $load_user_ids, 'Ensure all user IDs are loaded, including the one not in the queue' );
69+
}
70+
}

0 commit comments

Comments
 (0)