[buddypress-trac] [BuddyPress Trac] #6643: Incrementor-based caching for ID queries

buddypress-trac noreply at wordpress.org
Fri Oct 2 18:48:26 UTC 2015

#6643: Incrementor-based caching for ID queries
 Reporter:  boonebgorges  |      Owner:
     Type:  enhancement   |     Status:  new
 Priority:  normal        |  Milestone:  Awaiting Review
Component:  API           |    Version:
 Severity:  normal        |   Keywords:
 In an increasing number of places in BP, we use the following pattern:

 1. Query for an array of IDs whose objects match the passed params
 2. Prime the cache for the full items (if necessary)
 3. Server the objects from the cache.

 We do this for activity and members, and we should do it for groups etc

 The second half of this process is fairly cache-optimized. Activity items,
 for example, are cached individually. But the first part, where activity
 queries take place, is not cached at all.

 The challenge with caching ID queries is that the queries themselves can
 vary greatly based on the params passed to the function. This makes it
 nearly impossible to do highly focused cache invalidation. (For example,
 if a new activity item is posted in a group, you need to invalidate the
 cache for: (a) all pages of the group's activity, (b) all pages of the
 group's activity, as filterable by the "Show" dropdown, (c) the All
 Activity query, (d) the All Activity query, as filtered by the "Show"
 dropdown, (e) the My Groups and other activity queries for each member of
 the group, etc etc etc.)

 This is a case where we can take a page from WP's playbook. In the
 taxonomy component (and to some extent in comments and posts), a cache
 incrementor 'last_changed' is used. By creating a cache key that's a hash
 of `last_changed` + the query vars, you have a simple method for cache
 invalidation: whenever new activity (or whatever) is created, bump
 `last_changed`. Now all cache using a key generated from `last_changed` is
 invalidated. See `get_terms()`.

 Zach Tollman wrote a nice piece about the strategy a few years ago:
 https://www.tollmanz.com/invalidation-schemes/ The biggest challenge is
 making sure that we work reasonably well with cache backends that have
 suboptimal eviction policies. One idea is this: there are two incrementor-
 related items in the cache. One is the `last_changed` key itself. The
 other is an array of all cache keys that use that particular
 `last_changed` key. When we increment, we use that array to delete the
 stale cache items. So invalidation would look like this:

 function bp_increment_last_changed( $cache_group ) {
     $last_changed = wp_cache_get( 'last_changed', $cache_group );
     $keys = wp_cache_get( 'last_changed_cache_keys', $cache_group );
     foreach ( $keys as $key ) {
         wp_cache_delete( $key, $cache_group );

     wp_cache_delete( 'last_changed_cache_keys', $cache_group );
     wp_cache_set( 'last_changed', microtime(), $cache_group );

 and when we cache a query, we do it like this:

 $last_changed = wp_cache_get( 'last_changed', 'bp_activity' );
 $cache_key = $last_changed . md5(
 $some_cleanedup_version_of_the_query_params );

 // do the query

 wp_cache_set( $cache_key, $query_results, 'bp_activity' );
 $cache_keys = wp_cache_get( 'last_changed_cache_keys', 'bp_activity' );
 $cache_keys[] = $cache_key;
 wp_cache_set( 'last_changed_cache_keys', $cache_keys, 'bp_activity' );

 Or something like that.


Ticket URL: <https://buddypress.trac.wordpress.org/ticket/6643>
BuddyPress Trac <http://buddypress.org/>
BuddyPress Trac

More information about the buddypress-trac mailing list