Making WordPress.org

Changeset 9720


Ignore:
Timestamp:
04/14/2020 04:55:52 AM (4 years ago)
Author:
dd32
Message:

Translate: Move the stats generation for /stats from the Stats screen router to the Custom Stats plugin, store the data in the project translation status table rather than the options.

This also avoids the query-timeout problems by running the query as a INSERT INTO ... SELECT FROM which should be more resiliant to timeouts.

See #3155.

Location:
sites/trunk/wordpress.org/public_html/wp-content/plugins
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/wporg-gp-custom-stats/stats/project.php

    r4355 r9720  
    99 *
    1010 * NOTE: The counts includes all sub-projects in the count, as that's more useful for querying (top-level projects excluded)
    11  * for example, wp-plugins won't exist, but wp-plugins/akismet will include wp-plugins/akismet/stable wp-plugins/akismet/stable-readme
     11 * for example, wp-plugins/akismet will include wp-plugins/akismet/stable and wp-plugins/akismet/stable-readme
     12 * wp-plugins and wp-themes are special top-level projects which are included here, where their string counts are updated
     13 * on a twice-daily cron task.
    1214 *
    1315 * @author dd32
     
    2729        add_action( 'shutdown', array( $this, 'shutdown' ) );
    2830
     31        // Cron task to cache the wp-themes/wp-plugins string counts.
     32        if ( ! wp_next_scheduled ( 'wporg_gp_stats_cache_waiting_strings' ) ) {
     33            wp_schedule_event( time(), 'twicedaily', 'wporg_gp_stats_cache_waiting_strings' );
     34        }
     35        add_action( 'wporg_gp_stats_cache_waiting_strings', [ $this, 'cache_wp_themes_wp_plugins_strings' ] );
     36
    2937        $wpdb->project_translation_status = $gp_table_prefix . 'project_translation_status';
    3038    }
     
    4654    }
    4755
    48     // Counts up all the
     56    // Count up all the strings
    4957    function get_project_translation_counts( $project_id, $locale, $locale_slug, &$counts = array() ) {
    5058        if ( ! $counts ) {
     
    7583
    7684        return $counts;
     85    }
     86
     87    /**
     88     * Cron task to cache the string counts for the wp-themes and wp-plugins parent categories.
     89     *
     90     * These don't have any translation sets, but we need to be able to query the waiting strings for them.
     91     */
     92    public function cache_wp_themes_wp_plugins_strings() {
     93        global $wpdb;
     94
     95        $cached_projects = [
     96            GP::$project->by_path( 'wp-plugins' ),
     97            GP::$project->by_path( 'wp-themes' ),
     98        ];
     99
     100        // Store the counts for these parent projects as the sum of their children.
     101        $sql = "INSERT INTO {$wpdb->project_translation_status} ( `project_id`, `locale`, `locale_slug`, `all`, `current`, `waiting`, `fuzzy`, `warnings`, `untranslated`, `date_added`, `date_modified`)
     102        SELECT
     103            p.parent_project_id as project_id,
     104            locale, locale_slug,
     105            SUM( stats.all ) as `all`, SUM( stats.current ) as `current`, SUM( stats.waiting ) as `waiting`,
     106            SUM( stats.fuzzy ) as `fuzzy`, SUM( stats.warnings ) as `warnings`, SUM( stats.untranslated ) as `untranslated`,
     107            NOW() as `date_added`, NOW() as `date_modified`
     108        FROM {$wpdb->project_translation_status} stats
     109            LEFT JOIN {$wpdb->gp_projects} p ON stats.project_id = p.id
     110        WHERE
     111            p.parent_project_id = %d
     112            AND p.active = 1
     113        GROUP BY locale, locale_slug
     114        ON DUPLICATE KEY UPDATE
     115            `all` = VALUES(`all`), `current` = VALUES(`current`),
     116            `waiting` = VALUES(`waiting`), `fuzzy` = VALUES(`fuzzy`),
     117            `warnings` = VALUES(`warnings`), `untranslated` = VALUES(`untranslated`),
     118            `date_modified` = VALUES(`date_modified`);
     119        ";
     120
     121        foreach ( $cached_projects as $project ) {
     122            $wpdb->query( $wpdb->prepare( $sql, $project->id ) );
     123        }
     124
    77125    }
    78126
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/wporg-gp-routes/inc/class-plugin.php

    r9711 r9720  
    4747
    4848        add_action( 'init', [ $this, 'respect_robots_txt' ], 9 );
    49 
    50         add_action( 'init', [ $this, 'cron_tasks' ] );
    5149    }
    5250
     
    6058        // ?gp_route=robots.txt is here, as GlotPress ultimately is the router for the request.
    6159        add_rewrite_rule( '^robots\.txt$', 'index.php?robots=1&gp_route=robots.txt', 'top' );
    62     }
    63 
    64     /**
    65      * Some pages rely upon a regular cron task to update the stats rather than live updates.
    66      */
    67     function cron_tasks() {
    68         if ( ! wp_next_scheduled ( 'wporg_gp_stats_cache_waiting_strings' ) ) {
    69             wp_schedule_event( time(), 'twicedaily', 'wporg_gp_stats_cache_waiting_strings' );
    70         }
    71         add_action( 'wporg_gp_stats_cache_waiting_strings', [ __NAMESPACE__ . '\Routes\Stats', 'cache_waiting_strings' ] );
    7260    }
    7361
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/wporg-gp-routes/inc/routes/class-stats.php

    r9713 r9720  
    1313 */
    1414class Stats extends GP_Route {
    15 
    16     /**
    17      * Cache some expensive queries to be run on a Cron task.
    18      */
    19     public function cache_waiting_strings() {
    20         global $wpdb;
    21 
    22         // Run the query on a primary DB server to avoid timing out.
    23         if ( method_exists( $qpdb, 'send_reads_to_masters' ) ) {
    24             $wpdb->send_reads_to_masters();
    25         }
    26 
    27         $cached_projects = [
    28             GP::$project->by_path( 'wp-plugins' ),
    29             GP::$project->by_path( 'wp-themes' ),
    30         ];
    31         $sql = "SELECT
    32                 locale, locale_slug,
    33                 SUM( stats.waiting ) + SUM( stats.fuzzy ) as waiting_strings
    34             FROM {$wpdb->project_translation_status} stats
    35                 LEFT JOIN {$wpdb->gp_projects} p ON stats.project_id = p.id
    36             WHERE
    37                 p.parent_project_id = %d
    38                 AND p.active = 1
    39             GROUP BY locale, locale_slug";
    40 
    41         foreach ( $cached_projects as $project ) {
    42             $rows = $wpdb->get_results( $wpdb->prepare( $sql, $project->id ) );
    43             if ( ! $rows ) {
    44                 continue;
    45             }
    46 
    47             $cached_data = [];
    48             foreach ( $rows as $set ) {
    49                 $locale_key = $set->locale;
    50                 if ( 'default' != $set->locale_slug ) {
    51                     $locale_key = $set->locale . '/' . $set->locale_slug;
    52                 }
    53    
    54                 $cached_data[ $locale_key ] = (int) $set->waiting_strings;
    55             }
    56             $cached_data[ 'last_updated' ] = time();
    57 
    58             update_option( __CLASS__ . '_cached_waiting_' . $project->slug, $cached_data, false );
    59         }
    60 
    61     }
    6215
    6316    public function get_stats_overview() {
     
    10053                path, locale, locale_slug,
    10154                (100 * stats.current/stats.all) as percent_complete,
    102                 stats.waiting+stats.fuzzy as waiting_strings
     55                stats.waiting+stats.fuzzy as waiting_strings,
     56                stats.date_modified as last_modified
    10357            FROM {$wpdb->project_translation_status} stats
    10458                LEFT JOIN {$wpdb->gp_projects} p ON stats.project_id = p.id
     
    12579            $translation_locale_statuses[ $locale_key ][ $set->path ] = $percent_complete;
    12680
     81            // Don't include these in the 'waiting' section, override the value to be waiting strings w/ Date Modified.
     82            if ( 'wp-plugins' === $set->path || 'wp-themes' === $set->path ) {
     83                $translation_locale_statuses[ $locale_key ][ $set->path ] = $set->waiting_strings;
     84                $projects[ $set->path ]->cache_last_updated = $set->last_modified;
     85                continue;
     86            }
     87
    12788            if ( ! isset( $translation_locale_statuses[ $locale_key ]['waiting'] ) ) {
    12889                $translation_locale_statuses[ $locale_key ]['waiting'] = 0;
     
    13192        }
    13293        unset( $rows, $locale_key, $set );
    133 
    134         // Append the Plugins/Themes waiting strings
    135         foreach ( [ 'wp-plugins', 'wp-themes' ] as $project_slug ) {
    136             $cached_data = get_option( __CLASS__ . '_cached_waiting_' . $project_slug, [] );
    137             $projects[ $project_slug ]->cache_last_updated = gmdate( 'Y-m-d H:i:s \U\T\C', $cached_data['last_updated'] );
    138             foreach ( $cached_data as $locale => $waiting ) {
    139                 $translation_locale_statuses[ $locale ][ $project_slug ] = $waiting;
    140             }
    141         }
    14294
    14395        // Calculate a list of [Locale] = % subtotals
    14496        $translation_locale_complete = array();
    14597        foreach ( $translation_locale_statuses as $locale => $sets ) {
    146             unset( $sets['waiting'] );
     98            unset( $sets['waiting'], $sets['wp-plugins'], $sets['wp-themes'] );
    14799            $sets_count = count( $sets );
    148100            if ( $sets_count ) {
Note: See TracChangeset for help on using the changeset viewer.