Skip to:
Content

BuddyPress.org


Ignore:
Timestamp:
02/12/2014 09:27:20 PM (10 years ago)
Author:
boonebgorges
Message:

Migrate user 'last_activity' data from usermeta to the activity table

Storing last_activity in usermeta caused severe bottlenecks on sites with
large user bases. The usermeta table has a tendency to get bloated. Its
option_value column is not indexed, and even if it were, it would not be
indexed properly for the kind of chronological sorting that BuddyPress was
using it for.

This changeset refactors all core last_activity user functionality, so that
the data is stored in the wp_bp_activity table (even when the activity
component is disabled).

For backward compatibility with plugins that reference last_activity metadata
entries, all last_activity data is retained in wp_usermeta, and new data will
be mirrored there until further notice.

See #5128

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/bp-core/bp-core-classes.php

    r7812 r7860  
    246246            case 'online' :
    247247                $this->uid_name = 'user_id';
    248                 $sql['select']  = "SELECT u.{$this->uid_name} as id FROM {$wpdb->usermeta} u";
    249                 $sql['where'][] = $wpdb->prepare( "u.meta_key = %s", bp_get_user_meta_key( 'last_activity' ) );
    250                 $sql['where'][] = $wpdb->prepare( "u.meta_value >= DATE_SUB( UTC_TIMESTAMP(), INTERVAL %d MINUTE )", apply_filters( 'bp_user_query_online_interval', 15 ) );
    251                 $sql['orderby'] = "ORDER BY u.meta_value";
     248                $sql['select']  = "SELECT u.{$this->uid_name} as id FROM {$bp->members->table_name_last_activity} u";
     249                $sql['where'][] = $wpdb->prepare( "u.component = %s AND u.type = 'last_activity'", buddypress()->members->id );
     250                $sql['where'][] = $wpdb->prepare( "u.date_recorded >= DATE_SUB( UTC_TIMESTAMP(), INTERVAL %d MINUTE )", apply_filters( 'bp_user_query_online_interval', 15 ) );
     251                $sql['orderby'] = "ORDER BY u.date_recorded";
    252252                $sql['order']   = "DESC";
    253253
     
    260260            case 'random' :
    261261                $this->uid_name = 'user_id';
    262                 $sql['select']  = "SELECT u.{$this->uid_name} as id FROM {$wpdb->usermeta} u";
    263                 $sql['where'][] = $wpdb->prepare( "u.meta_key = %s", bp_get_user_meta_key( 'last_activity' ) );
     262                $sql['select']  = "SELECT u.{$this->uid_name} as id FROM {$bp->members->table_name_last_activity} u";
     263                $sql['where'][] = $wpdb->prepare( "u.component = %s AND u.type = 'last_activity'", buddypress()->members->id );
    264264
    265265                if ( 'newest' == $type ) {
     
    269269                    $sql['orderby'] = "ORDER BY rand()";
    270270                } else {
    271                     $sql['orderby'] = "ORDER BY u.meta_value";
     271                    $sql['orderby'] = "ORDER BY u.date_recorded";
    272272                    $sql['order'] = "DESC";
    273273                }
     
    538538        // Turn user ID's into a query-usable, comma separated value
    539539        $user_ids_sql = implode( ',', wp_parse_id_list( $this->user_ids ) );
     540
     541        $bp = buddypress();
    540542
    541543        /**
     
    554556        do_action_ref_array( 'bp_user_query_populate_extras', array( $this, $user_ids_sql ) );
    555557
     558        // Fetch last_active data from the activity table
     559        $last_activities = BP_Core_User::get_last_activity( $this->user_ids );
     560
     561        if ( ! empty( $last_activities ) ) {
     562            foreach ( $last_activities as $la_user => $la_value ) {
     563                if ( isset( $this->results[ $la_user ] ) ) {
     564                    $this->results[ $la_user ]->last_activity = $la_value['date_recorded'];
     565                }
     566            }
     567        }
     568
    556569        // Fetch usermeta data
    557570        // We want the three following pieces of info from usermeta:
    558571        // - friend count
    559         // - last activity
    560572        // - latest update
    561573        $total_friend_count_key = bp_get_user_meta_key( 'total_friend_count' );
    562         $last_activity_key      = bp_get_user_meta_key( 'last_activity'      );
    563574        $bp_latest_update_key   = bp_get_user_meta_key( 'bp_latest_update'   );
    564575
     
    570581
    571582        // Create, prepare, and run the seperate usermeta query
    572         $user_metas = $wpdb->get_results( $wpdb->prepare( "SELECT user_id, meta_key, meta_value FROM {$wpdb->usermeta} WHERE meta_key IN (%s,%s,%s) AND user_id IN ({$user_ids_sql})", $total_friend_count_key, $last_activity_key, $bp_latest_update_key ) );
     583        $user_metas = $wpdb->get_results( $wpdb->prepare( "SELECT user_id, meta_key, meta_value FROM {$wpdb->usermeta} WHERE meta_key IN (%s,%s) AND user_id IN ({$user_ids_sql})", $total_friend_count_key, $bp_latest_update_key ) );
    573584
    574585        // The $members_template global expects the index key to be different
     
    578589                case $total_friend_count_key :
    579590                    $key = 'total_friend_count';
    580                     break;
    581 
    582                 case $last_activity_key :
    583                     $key = 'last_activity';
    584591                    break;
    585592
     
    12971304
    12981305        return $user;
     1306    }
     1307
     1308    /**
     1309     * Get last activity data for a user or set of users.
     1310     *
     1311     * @param int|array User IDs or multiple user IDs.
     1312     * @return array
     1313     */
     1314    public static function get_last_activity( $user_id ) {
     1315        global $wpdb;
     1316
     1317        if ( is_array( $user_id ) ) {
     1318            $user_ids = wp_parse_id_list( $user_id );
     1319        } else {
     1320            $user_ids = array( absint( $user_id ) );
     1321        }
     1322
     1323        if ( empty( $user_ids ) ) {
     1324            return false;
     1325        }
     1326
     1327        $bp = buddypress();
     1328
     1329        $user_ids_sql = implode( ',', $user_ids );
     1330        $user_count   = count( $user_ids );
     1331
     1332        $last_activities = $wpdb->get_results( $wpdb->prepare( "SELECT id, user_id, date_recorded FROM {$bp->members->table_name_last_activity} WHERE component = %s AND type = 'last_activity' AND user_id IN ({$user_ids_sql}) LIMIT {$user_count}", $bp->members->id ) );
     1333
     1334        // Re-key
     1335        $retval = array();
     1336        foreach ( $last_activities as $last_activity ) {
     1337            $retval[ $last_activity->user_id ] = array(
     1338                'user_id'       => $last_activity->user_id,
     1339                'date_recorded' => $last_activity->date_recorded,
     1340                'activity_id'   => $last_activity->id,
     1341            );
     1342        }
     1343
     1344        return $retval;
     1345    }
     1346
     1347    /**
     1348     * Set a user's last_activity value.
     1349     *
     1350     * Will create a new entry if it does not exist. Otherwise updates the
     1351     * existing entry.
     1352     *
     1353     * @since 2.0
     1354     *
     1355     * @param int $user_id ID of the user whose last_activity you are updating.
     1356     * @param string $time MySQL-formatted time string.
     1357     * @return bool True on success, false on failure.
     1358     */
     1359    public static function update_last_activity( $user_id, $time ) {
     1360        global $wpdb;
     1361
     1362        $table_name = buddypress()->members->table_name_last_activity;
     1363
     1364        $existing = self::get_last_activity( $user_id );
     1365
     1366        if ( ! empty( $existing ) ) {
     1367            $data = array(
     1368                'date_recorded' => $time,
     1369            );
     1370
     1371            $data_format = array(
     1372                '%s',
     1373            );
     1374
     1375            $where = array(
     1376            );
     1377
     1378            $where_format = array(
     1379                '%d',
     1380            );
     1381
     1382            $updated = $wpdb->update(
     1383                $table_name,
     1384
     1385                // Data to update
     1386                array(
     1387                    'date_recorded' => $time,
     1388                ),
     1389
     1390                // WHERE
     1391                array(
     1392                    'id' => $existing[ $user_id ]['activity_id'],
     1393                ),
     1394
     1395                // Data sanitization format
     1396                array(
     1397                    '%s',
     1398                ),
     1399
     1400                // WHERE sanitization format
     1401                array(
     1402                    '%d',
     1403                )
     1404            );
     1405        } else {
     1406            $updated = $wpdb->insert(
     1407                $table_name,
     1408
     1409                // Data
     1410                array(
     1411                    'user_id'       => $user_id,
     1412                    'component'     => buddypress()->members->id,
     1413                    'type'          => 'last_activity',
     1414                    'date_recorded' => $time,
     1415                ),
     1416
     1417                // Data sanitization format
     1418                array(
     1419                    '%d',
     1420                    '%s',
     1421                    '%s',
     1422                    '%s',
     1423                )
     1424            );
     1425        }
     1426
     1427        return $updated;
     1428    }
     1429
     1430    /**
     1431     * Delete a user's last_activity value.
     1432     *
     1433     * @since 2.0
     1434     *
     1435     * @param int $user_id
     1436     * @return bool True on success, false on failure or if no last_activity
     1437     *         is found for the user.
     1438     */
     1439    public static function delete_last_activity( $user_id ) {
     1440        global $wpdb;
     1441
     1442        $existing = self::get_last_activity( $user_id );
     1443
     1444        if ( empty( $existing ) ) {
     1445            return false;
     1446        }
     1447
     1448        $deleted = $wpdb->delete(
     1449            buddypress()->members->table_name_last_activity,
     1450
     1451            // WHERE
     1452            array(
     1453                'id' => $existing[ $user_id ]['activity_id'],
     1454            ),
     1455
     1456            // WHERE sanitization format
     1457            array(
     1458                '%s',
     1459            )
     1460        );
     1461
     1462        return $deleted;
    12991463    }
    13001464}
Note: See TracChangeset for help on using the changeset viewer.