Skip to content

PROD-9998: cache xProfile visibility check, cap ReadyLaunch dropdown - #5047

Open
rezwan-buddyboss wants to merge 1 commit into
releasefrom
PROD-9998
Open

PROD-9998: cache xProfile visibility check, cap ReadyLaunch dropdown#5047
rezwan-buddyboss wants to merge 1 commit into
releasefrom
PROD-9998

Conversation

@rezwan-buddyboss

@rezwan-buddyboss rezwan-buddyboss commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

PROD link: https://buddyboss.atlassian.net/browse/PROD-9998

Two-repo fix — this is the buddyboss-platform half. Companion PR: buddyboss/buddyboss-theme#2817, which fixes the actual query-count scaling (the part visible in Query Monitor). This PR alone does not fix that scaling — its cache addition only matters on a site with a persistent object cache backend (Redis/Memcached) and produces no visible change in Query Monitor by itself. Merge both for the complete fix.

Issue

Same underlying ticket as buddyboss/buddyboss-theme#2817: on a large site with a message thread that has a large recipient list, resolving each recipient's display name for the header's unread-messages dropdown triggers one xProfile visibility check per recipient. This PR addresses two things the theme-side fix alone doesn't cover: BB_XProfile_Visibility::user_data_exists() never used the persistent object cache at all, and the Platform ships its own separate copy of the same dropdown template for ReadyLaunch that has the identical unbounded-loop problem.

Root cause

BB_XProfile_Visibility::user_data_exists() only cached its result in a per-request static $cache array, then fell straight through to $wpdb->get_var() on every cache miss. It never called wp_cache_get()/wp_cache_set(), so on a site running Redis or Memcached, the same user's visibility-scan result was recomputed from the database on every single page load instead of being reused across requests — the persistent cache layer existed for the rest of xProfile (the sibling method is_valid_field() in this same class already uses the standard wp_cache_get()/wp_cache_set( ..., 'bp_xprofile' ) pattern) but was simply missing here.

Separately, src/bp-templates/bp-nouveau/readylaunch/header/unread-messages.php — the Platform's own template for sites using the ReadyLaunch header instead of the classic BuddyBoss Theme header — has the exact same recipient-loop structure as the theme's template-parts/unread-messages.php, so it has the exact same per-recipient-resolution problem the theme PR fixes.

Fix

Object cache for user_data_exists(): added a wp_cache_get( $cache_key, 'bp_xprofile' ) check before the DB query, and wp_cache_set() after computing the result, mirroring is_valid_field()'s existing pattern. Added a new delete_user_data_exists_cache( $user_id ) helper and called it from every write path that can change a user's visibility-data existence: save(), delete(), and delete_specific_data_for_user(). delete_for_field() needed an extra step — it does a bulk $wpdb->query() across every user with data on a given field without going through save()/delete(), so no invalidation hook fires for the individual users affected. Fixed by first querying the affected user_ids (SELECT DISTINCT user_id ... WHERE field_id = %d) before the delete, then invalidating each one's cache afterward.

Note: this cache addition has no visible effect on a single page-load's query count — Query Monitor won't show a difference from it alone. It only matters on a site with a persistent cache backend, where it's the difference between "resolved once per cache lifetime" and "resolved fresh on every request." The query-count fix that actually shows up in Query Monitor is the theme-side loop cap in the companion PR.

ReadyLaunch template: applied the identical recipient-count cap as the theme PR — resolve $recipient_data only for the logged-in user or one of the first 3 "other" recipients, track the true total via $other_recipient_total, and switch every other count( $other_recipients ) read in the file to that counter — to src/bp-templates/bp-nouveau/readylaunch/header/unread-messages.php, since it's structurally identical to the file the theme PR fixes.

… dropdown

BB_XProfile_Visibility::user_data_exists() bypassed the object cache,
using only a per-request static array before hitting the DB directly.
On a persistent-cache (Redis) site this meant the same user's
visibility-scan result was recomputed from scratch every request. Add
the same wp_cache_get()/wp_cache_set( ..., 'bp_xprofile' ) pattern
already used by the sibling is_valid_field() method, with invalidation
wired into every write path that can change a user's visibility-data
existence (save(), delete(), delete_specific_data_for_user(),
delete_for_field()) since no after_save/after_delete cache-invalidation
hook previously existed.

Also applies the theme fix's recipient-count cap (see companion PR) to
the Platform's own ReadyLaunch copy of the header messages dropdown
template, which has the identical loop structure.

Companion fix: buddyboss/buddyboss-theme#2817
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant