Skip to:
Content

BuddyPress.org

Changeset 9753


Ignore:
Timestamp:
04/15/2015 10:44:55 PM (6 years ago)
Author:
r-a-y
Message:

Messages: Cache calls to BP_Messages_Thread class.

This commit:

  • Introduces static method - BP_Messages_Thread::get_messages() - caches fetching messages by thread ID and introduces the 'bp_messages_threads' cache group.
  • Converts BP_Messages_Thread::check_access() and BP_Messages_Thread::is_valid() methods from using direct DB queries to reference the cache.
  • Includes unit tests.
  • Consolidates cache clearing functions in bp-messages-cache.php.

This handles the majority of uncached message DB queries. For the inbox
page, if there are 10 message threads in the loop, we save 20 DB queries.
On a single message thread, we save 5 DB queries.

Fixes #6221.

Location:
trunk
Files:
4 edited

Legend:

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

    r9482 r9753  
    4747
    4848/**
    49  * Clear unread count cache for each recipient after a message is sent.
     49 * Clear message cache after a message is saved.
    5050 *
    5151 * @since BuddyPress (2.0.0)
     
    5353 * @param BP_Messages_Message $message
    5454 */
    55 function bp_messages_clear_unread_count_cache_on_message_save( BP_Messages_Message $message ) {
     55function bp_messages_clear_cache_on_message_save( BP_Messages_Message $message ) {
     56    // Delete thread cache
     57    wp_cache_delete( $message->thread_id, 'bp_messages_threads' );
     58
     59    // Delete unread count for each recipient
    5660    foreach ( (array) $message->recipients as $recipient ) {
    5761        wp_cache_delete( $recipient->user_id, 'bp_messages_unread_count' );
    5862    }
     63
     64    // Delete thread recipient cache
     65    wp_cache_delete( 'thread_recipients_' . $message->thread_id, 'bp_messages' );
    5966}
    60 add_action( 'messages_message_after_save', 'bp_messages_clear_unread_count_cache_on_message_save' );
     67add_action( 'messages_message_after_save', 'bp_messages_clear_cache_on_message_save' );
    6168
    6269/**
    63  * Clear unread count cache for the logged-in user after a message is deleted.
     70 * Clear message cache after a message thread is deleted.
    6471 *
    6572 * @since BuddyPress (2.0.0)
     
    6875 *  array of thread IDs
    6976 */
    70 function bp_messages_clear_unread_count_cache_on_message_delete( $thread_ids ) {
     77function bp_messages_clear_cache_on_message_delete( $thread_ids ) {
     78    // Delete thread and thread recipient cache
     79    foreach( (array) $thread_ids as $thread_id ) {
     80        wp_cache_delete( $thread_id, 'bp_messages_threads' );
     81        wp_cache_delete( "thread_recipients_{$thread_id}", 'bp_messages' );
     82    }
     83
     84    // Delete unread count for logged-in user
    7185    wp_cache_delete( bp_loggedin_user_id(), 'bp_messages_unread_count' );
    7286}
    73 add_action( 'messages_before_delete_thread', 'bp_messages_clear_unread_count_cache_on_message_delete' );
     87add_action( 'messages_delete_thread', 'bp_messages_clear_cache_on_message_delete' );
    7488
    7589/**
     
    8599add_action( 'messages_notice_after_save',    'bp_notices_clear_cache' );
    86100add_action( 'messages_notice_before_delete', 'bp_notices_clear_cache' );
    87 
    88 /**
    89  * Invalidate thread recipient cache on message update.
    90  *
    91  * @since BuddyPress (2.3.0)
    92  *
    93  * @param BP_Messages_Message $message Message object.
    94  */
    95 function bp_messages_clear_message_thread_recipient_cache_on_message_sent( BP_Messages_Message $message ) {
    96     wp_cache_delete( 'thread_recipients_' . $message->thread_id, 'bp_messages' );
    97 }
    98 add_action( 'messages_message_sent', 'bp_messages_clear_message_thread_recipient_cache_on_message_sent' );
    99 
    100 /**
    101  * Invalidate thread recipient cache on thread deletion.
    102  *
    103  * @since BuddyPress (2.3.0)
    104  *
    105  * @param int|array $thread_ids IDs of deleted threads.
    106  */
    107 function bp_messages_clear_message_thread_recipient_cache_on_thread_delete( $thread_ids ) {
    108     foreach ( (array) $thread_ids as $thread_id ) {
    109         wp_cache_delete( 'thread_recipients_' . $thread_id, 'bp_messages' );
    110     }
    111 }
    112 add_action( 'messages_delete_thread', 'bp_messages_clear_message_thread_recipient_cache_on_thread_delete' );
  • trunk/src/bp-messages/bp-messages-loader.php

    r9351 r9753  
    304304        wp_cache_add_global_groups( array(
    305305            'bp_messages',
     306            'bp_messages_threads',
    306307            'bp_messages_unread_count',
    307308            'message_meta'
  • trunk/src/bp-messages/classes/class-bp_messages-thread.php

    r9752 r9753  
    148148        $this->thread_id      = $thread_id;
    149149
    150         $bp = buddypress();
    151 
    152         if ( !$this->messages = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$bp->messages->table_name_messages} WHERE thread_id = %d ORDER BY date_sent " . $order, $this->thread_id ) ) ) {
     150        // get messages for thread
     151        $this->messages = self::get_messages( $thread_id );
     152
     153        if ( empty( $this->messages ) || is_wp_error( $this->messages ) ) {
    153154            return false;
     155        }
     156
     157        // flip if order is DESC
     158        if ( 'DESC' === $order ) {
     159            $this->messages = array_reverse( $this->messages );
    154160        }
    155161
     
    245251
    246252    /** Static Functions ******************************************************/
     253
     254    /**
     255     * Get all messages associated with a thread.
     256     *
     257     * @since BuddyPress (2.3.0)
     258     *
     259     * @param int $thread_id The message thread ID
     260     * @return array
     261     */
     262    public static function get_messages( $thread_id = 0 ) {
     263        $messages = wp_cache_get( $thread_id, 'bp_messages_threads' );
     264
     265        if ( false === $messages ) {
     266            global $wpdb;
     267
     268            $bp = buddypress();
     269
     270            // always sort by ASC by default
     271            $messages = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$bp->messages->table_name_messages} WHERE thread_id = %d ORDER BY date_sent ASC", $thread_id ) );
     272
     273            wp_cache_set( $thread_id, (array) $messages, 'bp_messages_threads' );
     274        }
     275
     276        return $messages;
     277    }
    247278
    248279    /**
     
    664695     * @param int $thread_id The message thread ID.
    665696     * @param int $user_id The user ID.
    666      * @return int The message ID on success.
     697     * @return int|null The recorded recipient ID on success, null on failure
    667698     */
    668699    public static function check_access( $thread_id, $user_id = 0 ) {
    669         global $wpdb;
    670 
    671         if ( empty( $user_id ) )
     700        if ( empty( $user_id ) ) {
    672701            $user_id = bp_loggedin_user_id();
    673 
    674         $bp = buddypress();
    675 
    676         return $wpdb->get_var( $wpdb->prepare( "SELECT id FROM {$bp->messages->table_name_recipients} WHERE thread_id = %d AND is_deleted = 0 AND user_id = %d", $thread_id, $user_id ) );
     702        }
     703
     704        $recipients = self::get_recipients_for_thread( $thread_id );
     705
     706        if ( isset( $recipients[$user_id] ) && 0 == $recipients[$user_id]->is_deleted ) {
     707            return $recipients[$user_id]->id;
     708        } else {
     709            return null;
     710        }
    677711    }
    678712
     
    683717     *
    684718     * @param int $thread_id The message thread ID.
    685      * @return int The message thread ID on success.
     719     * @return int|null The message thread ID on success, null on failure
    686720     */
    687721    public static function is_valid( $thread_id = 0 ) {
    688         global $wpdb;
    689 
    690722        // Bail if no thread ID is passed
    691723        if ( empty( $thread_id ) ) {
     
    693725        }
    694726
    695         $bp = buddypress();
    696 
    697         return $wpdb->get_var( $wpdb->prepare( "SELECT thread_id FROM {$bp->messages->table_name_messages} WHERE thread_id = %d LIMIT 1", $thread_id ) );
     727        $thread = self::get_messages( $thread_id );
     728
     729        if ( ! empty( $thread ) ) {
     730            return $thread_id;
     731        } else {
     732            return null;
     733        }
    698734    }
    699735
  • trunk/tests/phpunit/testcases/messages/class.bp-messages-thread.php

    r9714 r9753  
    55 */
    66class BP_Tests_BP_Messages_Thread extends BP_UnitTestCase {
     7
     8    /**
     9     * @group cache
     10     */
     11    public function test_construct_cache() {
     12        $u1 = $this->factory->user->create();
     13        $u2 = $this->factory->user->create();
     14
     15        $t1 = $this->factory->message->create( array(
     16            'sender_id' => $u1,
     17            'recipients' => array( $u2 ),
     18            'subject' => 'Foo',
     19        ) );
     20
     21        // prime cache
     22        new BP_Messages_Thread( $t1 );
     23
     24        // Cache should exist
     25        $this->assertThat(
     26            wp_cache_get( $t1, 'bp_messages_threads' ),
     27            $this->logicalNot( $this->equalTo( false ) ),
     28            'Message thread cache should exist.'
     29        );
     30    }
     31
     32    /**
     33     * @group order
     34     */
     35    public function test_construct_order_desc() {
     36        $u1 = $this->factory->user->create();
     37        $u2 = $this->factory->user->create();
     38
     39        // create thread
     40        $t1 = $this->factory->message->create( array(
     41            'sender_id' => $u1,
     42            'recipients' => array( $u2 ),
     43            'subject' => 'Foo',
     44        ) );
     45        // save message ID
     46        $thread = new BP_Messages_Thread( $t1 );
     47        $m1 = wp_list_pluck( $thread->messages, 'id' );
     48        $m1 = array_pop( $m1 );
     49
     50        // create reply
     51        $t2 = $this->factory->message->create( array(
     52            'thread_id' => $t1,
     53            'sender_id' => $u1,
     54            'recipients' => array( $u2 ),
     55            'content' => 'Bar'
     56        ) );
     57        // save message ID
     58        $thread = new BP_Messages_Thread( $t1 );
     59        $m2 = wp_list_pluck( $thread->messages, 'id' );
     60        $m2 = array_pop( $m2 );
     61
     62        // now get thread by DESC
     63        $thread = new BP_Messages_Thread( $t1, 'DESC' );
     64
     65        // assert!
     66        $this->assertEquals(
     67            array( $m2, $m1 ),
     68            wp_list_pluck( $thread->messages, 'id' )
     69        );
     70    }
     71
    772    /**
    873     * @group get_current_threads_for_user
     
    287352        $this->set_current_user( $current_user );
    288353    }
     354
     355    /**
     356     * @group check_access
     357     */
     358    public function test_check_access_valid_thread() {
     359        $u1 = $this->factory->user->create();
     360        $u2 = $this->factory->user->create();
     361
     362        $t1 = $this->factory->message->create( array(
     363            'sender_id' => $u1,
     364            'recipients' => array( $u2 ),
     365            'subject' => 'Foo',
     366        ) );
     367
     368        // save recipient ID
     369        $thread = new BP_Messages_Thread( $t1 );
     370        $r1 = wp_list_pluck( $thread->recipients, 'id' );
     371        $r1 = array_pop( $r1 );
     372
     373        $this->assertEquals( $r1, BP_Messages_Thread::check_access( $t1, $u1 ) );
     374    }
     375
     376    /**
     377     * @group check_access
     378     */
     379    public function test_check_access_invalid_thread() {
     380        $this->assertEquals( null, BP_Messages_Thread::check_access( 999, 1 ) );
     381    }
     382
     383    /**
     384     * @group is_valid
     385     */
     386    public function test_is_valid_valid_thread() {
     387        $u1 = $this->factory->user->create();
     388        $u2 = $this->factory->user->create();
     389
     390        $t1 = $this->factory->message->create( array(
     391            'sender_id' => $u1,
     392            'recipients' => array( $u2 ),
     393            'subject' => 'Foo',
     394        ) );
     395
     396        $this->assertEquals( $t1, BP_Messages_Thread::is_valid( $t1 ) );
     397    }
     398
     399    /**
     400     * @group is_valid
     401     */
     402    public function test_is_valid_invalid_thread() {
     403        $this->assertEquals( null, BP_Messages_Thread::is_valid( 999 ) );
     404    }
    289405}
Note: See TracChangeset for help on using the changeset viewer.