Cache API: Cache non-existent users in WP_User::get_data_by() to prevent duplicate queries#11632
Cache API: Cache non-existent users in WP_User::get_data_by() to prevent duplicate queries#11632MarcinDudekDev wants to merge 1 commit intoWordPress:trunkfrom
Conversation
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the Core Committers: Use this line as a base for the props when committing in SVN: To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
Test using WordPress PlaygroundThe changes in this pull request can previewed and tested using a WordPress Playground instance. WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser. Some things to be aware of
For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation. |
00d068b to
5990948
Compare
…ent duplicate queries.
When get_userdata() or WP_User::get_data_by('id', $id) is called for a non-existent
user ID, the result is now cached as a per-ID key ('notuser_$id') in the 'users' cache
group. Subsequent calls return false immediately without hitting the database. The cache
entry expires after one day as a safety net for persistent object cache backends.
The cache is invalidated by clean_user_cache(), which is the canonical invalidation
path called by both wp_insert_user() and wp_update_user(). When called with a plain
integer (as wp_insert_user() does), the notuser key is cleared *before* constructing
a new WP_User internally, preventing a self-referential cache miss.
Using per-ID keys (rather than a shared array) avoids unbounded memory growth under
persistent object cache backends and eliminates read-modify-write race conditions.
Fixes #46388.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
5990948 to
0617fe6
Compare
Fixes https://core.trac.wordpress.org/ticket/46388
Problem
When
get_userdata()(orWP_User::get_data_by('id', $id)) is called for a non-existent user ID, it always executes a database query. If the same non-existent ID is looked up multiple times — for example, through repeated calls toget_userdata(),get_avatar(), or other functions that resolve user data — each call results in a duplicateSELECT * FROM wp_users WHERE ID = ...query.Solution
Cache non-existent user IDs in a
notusersarray within theusersobject cache group, following the establishednotoptionspattern from the options API (get_option()).WP_User::get_data_by()(when$field === 'id'):notuserscache. Returnfalseimmediately if the ID is cached as non-existent.notuserscache.update_user_caches():notuserscache to ensure stale negative-cache entries are invalidated. This addresses the concern raised in comment:1 about cache invalidation on user creation.The
userscache group is already registered as a global group in multisite (wp_cache_add_global_groups()), so thenotuserskey inherits that scope correctly.Tests
Four new tests in
tests/phpunit/tests/user/getDataBy.php:notuserscache after first miss.notuserscache is invalidated whenupdate_user_caches()is called.notusers.AI assistance: Yes
Tool(s): Claude Code (Anthropic)
Model(s): Claude Sonnet 4.6
Used for: Implementation and test authorship; reviewed and verified by contributor.