Skip to:
Content

BuddyPress.org

Changeset 11054


Ignore:
Timestamp:
09/01/2016 03:27:12 AM (3 years ago)
Author:
boonebgorges
Message:

Cache the results of activity ID and count queries.

Query results are cached using an incrementor, and are invalidated in
bulk whenever an activity item is created, updated, or deleted.

Fixes #7237.

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/bp-activity/bp-activity-cache.php

    r10455 r11054  
    6464}
    6565add_action( 'bp_activity_deleted_activities', 'bp_activity_clear_cache_for_deleted_activity' );
     66
     67/**
     68 * Reset cache incrementor for the Activity component.
     69 *
     70 * Called whenever an activity item is created, updated, or deleted, this
     71 * function effectively invalidates all cached results of activity queries.
     72 *
     73 * @since 2.7.0
     74 *
     75 * @return bool True on success, false on failure.
     76 */
     77function bp_activity_reset_cache_incrementor() {
     78    return bp_core_reset_incrementor( 'bp_activity' );
     79}
     80add_action( 'bp_activity_delete', 'bp_activity_reset_cache_incrementor' );
     81add_action( 'bp_activity_add', 'bp_activity_reset_cache_incrementor' );
  • trunk/src/bp-activity/classes/class-bp-activity-activity.php

    r10908 r11054  
    646646            $activity_ids_sql = apply_filters( 'bp_activity_paged_activities_sql', $activity_ids_sql, $r );
    647647
    648             $activity_ids = $wpdb->get_col( $activity_ids_sql );
     648            $cached = bp_core_get_incremented_cache( $activity_ids_sql, 'bp_activity' );
     649            if ( false === $cached ) {
     650                $activity_ids = $wpdb->get_col( $activity_ids_sql );
     651                bp_core_set_incremented_cache( $activity_ids_sql, 'bp_activity', $activity_ids );
     652            } else {
     653                $activity_ids = $cached;
     654            }
    649655
    650656            $retval['has_more_items'] = ! empty( $per_page ) && count( $activity_ids ) > $per_page;
     
    703709             */
    704710            $total_activities_sql = apply_filters( 'bp_activity_total_activities_sql', "SELECT count(DISTINCT a.id) FROM {$bp->activity->table_name} a {$join_sql} {$where_sql}", $where_sql, $sort );
    705             $total_activities     = $wpdb->get_var( $total_activities_sql );
     711            $cached = bp_core_get_incremented_cache( $total_activities_sql, 'bp_activity' );
     712            if ( false === $cached ) {
     713                $total_activities = $wpdb->get_var( $total_activities_sql );
     714                bp_core_set_incremented_cache( $total_activities_sql, 'bp_activity', $total_activities );
     715            } else {
     716                $total_activities = $cached;
     717            }
    706718
    707719            if ( !empty( $r['max'] ) ) {
  • trunk/tests/phpunit/testcases/activity/cache.php

    r9819 r11054  
    8484        $this->assertSame( 'bar foo', $a_fp['activities'][0]->content );
    8585    }
     86
     87    /**
     88     * @ticket BP7237
     89     * @ticket BP6643
     90     */
     91    public function test_query_should_be_cached() {
     92        global $wpdb;
     93
     94        $u = $this->factory->user->create();
     95        $a = $this->factory->activity->create( array(
     96            'component'     => buddypress()->activity->id,
     97            'type'          => 'activity_update',
     98            'user_id'       => $u,
     99            'content'       => 'foo bar',
     100        ) );
     101
     102        $activity_args = array(
     103            'per_page' => 10,
     104            'fields' => 'ids',
     105            'count_total' => true,
     106        );
     107
     108        $a1 = bp_activity_get( $activity_args );
     109
     110        $num_queries = $wpdb->num_queries;
     111
     112        $a2 = bp_activity_get( $activity_args );
     113
     114        $this->assertEqualSets( $a1, $a2 );
     115        $this->assertSame( $num_queries, $wpdb->num_queries );
     116    }
     117
     118    /**
     119     * @ticket BP7237
     120     * @ticket BP6643
     121     */
     122    public function test_query_cache_should_be_skipped_for_different_query_params() {
     123        global $wpdb;
     124
     125        $u = $this->factory->user->create();
     126        $a = $this->factory->activity->create( array(
     127            'component'     => buddypress()->activity->id,
     128            'type'          => 'activity_update',
     129            'user_id'       => $u,
     130            'content'       => 'foo bar',
     131        ) );
     132
     133        $activity_args = array(
     134            'per_page' => 10,
     135            'fields' => 'ids',
     136            'count_total' => true,
     137            'filter' => array(
     138                'component' => buddypress()->activity->id,
     139            ),
     140        );
     141
     142        $a1 = bp_activity_get( $activity_args );
     143
     144        $num_queries = $wpdb->num_queries;
     145
     146        // This is enough to make the ID and COUNT clause miss the cache.
     147        $activity_args['filter']['action'] = 'activity_update';
     148        $a2 = bp_activity_get( $activity_args );
     149
     150        $this->assertEqualSets( $a1, $a2 );
     151
     152        // Two extra queries: one for the IDs, one for the count.
     153        $n = $num_queries + 2;
     154        $this->assertSame( $num_queries + 2, $wpdb->num_queries );
     155    }
     156
     157    /**
     158     * @ticket BP7237
     159     * @ticket BP6643
     160     */
     161    public function test_query_cache_should_be_invalidated_by_activity_add() {
     162        global $wpdb;
     163
     164        $u = $this->factory->user->create();
     165        $a1 = $this->factory->activity->create( array(
     166            'component'     => buddypress()->activity->id,
     167            'type'          => 'activity_update',
     168            'user_id'       => $u,
     169            'content'       => 'foo bar',
     170        ) );
     171
     172        $activity_args = array(
     173            'per_page' => 10,
     174            'fields' => 'ids',
     175            'count_total' => true,
     176        );
     177
     178        $q1 = bp_activity_get( $activity_args );
     179
     180        // Bust the cache.
     181        $a2 = $this->factory->activity->create( array(
     182            'component'     => buddypress()->activity->id,
     183            'type'          => 'activity_update',
     184            'user_id'       => $u,
     185            'content'       => 'foo bar',
     186        ) );
     187
     188        $num_queries = $wpdb->num_queries;
     189
     190        $q2 = bp_activity_get( $activity_args );
     191
     192        $expected = array( $a1, $a2 );
     193
     194        $this->assertEqualSets( $expected, $q2['activities'] );
     195        $this->assertEquals( 2, $q2['total'] );
     196        $this->assertSame( $num_queries + 2, $wpdb->num_queries );
     197    }
     198
     199    /**
     200     * @ticket BP7237
     201     * @ticket BP6643
     202     */
     203    public function test_query_cache_should_be_invalidated_by_activity_edit() {
     204        global $wpdb;
     205
     206        $u = $this->factory->user->create();
     207        $a = $this->factory->activity->create( array(
     208            'component'     => buddypress()->activity->id,
     209            'type'          => 'activity_update',
     210            'user_id'       => $u,
     211            'content'       => 'foo bar',
     212        ) );
     213
     214        $activity_args = array(
     215            'per_page' => 10,
     216            'fields' => 'ids',
     217            'count_total' => true,
     218        );
     219
     220        $q1 = bp_activity_get( $activity_args );
     221
     222        // Bust the cache.
     223        $this->factory->activity->create( array(
     224            'id'            => $a,
     225            'component'     => buddypress()->activity->id,
     226            'type'          => 'activity_update',
     227            'user_id'       => $u,
     228            'content'       => 'foo bar baz',
     229        ) );
     230
     231        $num_queries = $wpdb->num_queries;
     232
     233        $q2 = bp_activity_get( $activity_args );
     234
     235        $this->assertEqualSets( $q1, $q2 );
     236        $this->assertSame( $num_queries + 2, $wpdb->num_queries );
     237    }
     238
     239    /**
     240     * @ticket BP7237
     241     * @ticket BP6643
     242     */
     243    public function test_query_cache_should_be_invalidated_by_activity_delete() {
     244        global $wpdb;
     245
     246        $u = $this->factory->user->create();
     247        $a = $this->factory->activity->create( array(
     248            'component'     => buddypress()->activity->id,
     249            'type'          => 'activity_update',
     250            'user_id'       => $u,
     251            'content'       => 'foo bar',
     252        ) );
     253
     254        $activity_args = array(
     255            'per_page' => 10,
     256            'fields' => 'ids',
     257            'count_total' => true,
     258        );
     259
     260        $q1 = bp_activity_get( $activity_args );
     261
     262        // Bust the cache.
     263        bp_activity_delete( array(
     264            'id' => $a,
     265        ) );
     266
     267        $num_queries = $wpdb->num_queries;
     268
     269        $q2 = bp_activity_get( $activity_args );
     270
     271        $this->assertEqualSets( array(), $q2['activities'] );
     272        $this->assertEquals( 0, $q2['total'] );
     273        $this->assertSame( $num_queries + 2, $wpdb->num_queries );
     274    }
    86275}
Note: See TracChangeset for help on using the changeset viewer.