Repository navigation
#56040 site health persistent object cache #2890
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
f3d3988
05c0f94
015e728
d7eb1c1
d280a9b
9663727
ae085db
b4474d0
e43e9fc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2253,6 +2253,105 @@ public function get_test_authorization_header() { | |
| return $result; | ||
| } | ||
|
|
||
| /** | ||
| * Tests if sites uses persistent object cache. | ||
| * | ||
| * Checks if site uses persistent object cache or recommends to use it if not. | ||
| * | ||
| * @since 6.1.0 | ||
| * | ||
| * @return array The test result. | ||
| */ | ||
| public function get_test_persistent_object_cache() { | ||
| /** | ||
| * Filters the action URL for the persistent object cache health check. | ||
| * | ||
| * @since 6.1.0 | ||
| * | ||
| * @param string $action_url Learn more link for persistent object cache health check. | ||
| */ | ||
| $action_url = apply_filters( | ||
| 'site_status_persistent_object_cache_url', | ||
| /* translators: Localized Support reference. */ | ||
| __( 'https://wordpress.org/support/article/optimization/#object-caching' ) | ||
| ); | ||
|
|
||
| $result = array( | ||
| 'test' => 'persistent_object_cache', | ||
| 'status' => 'good', | ||
| 'badge' => array( | ||
| 'label' => __( 'Performance' ), | ||
| 'color' => 'blue', | ||
| ), | ||
| 'label' => __( 'A persistent object cache is being used' ), | ||
| 'description' => sprintf( | ||
| '<p>%s</p>', | ||
| __( "A persistent object cache makes your site's database more efficient, resulting in faster load times because WordPress can retrieve your site's content and settings much more quickly." ) | ||
| ), | ||
| 'actions' => sprintf( | ||
| '<p><a href="%s" target="_blank" rel="noopener">%s <span class="screen-reader-text">%s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a></p>', | ||
| esc_url( $action_url ), | ||
| __( 'Learn more about persistent object caching.' ), | ||
| /* translators: Accessibility text. */ | ||
| __( '(opens in a new tab)' ) | ||
| ), | ||
| ); | ||
|
|
||
| if ( wp_using_ext_object_cache() ) { | ||
| return $result; | ||
| } | ||
|
|
||
| if ( ! $this->should_suggest_persistent_object_cache() ) { | ||
| $result['label'] = __( 'A persistent object cache is not required' ); | ||
|
|
||
| return $result; | ||
| } | ||
|
|
||
| $available_services = $this->available_object_cache_services(); | ||
|
|
||
| $notes = __( 'Your hosting provider can tell you if persistent object cache can be enabled on your site.' ); | ||
|
|
||
| if ( ! empty( $available_services ) ) { | ||
| $notes .= ' ' . sprintf( | ||
| /* translators: Available object caching services. */ | ||
| __( 'Your host appears to support the following object caching services: %s.' ), | ||
| implode( ', ', $available_services ) | ||
| ); | ||
| } | ||
|
|
||
| /** | ||
| * Filters the second paragraph of the health check's description | ||
| * when suggesting the use of a persistent object cache. | ||
| * | ||
| * Hosts may want to replace the notes to recommend their preferred object caching solution. | ||
| * | ||
| * Plugin authors may want to append notes (not replace) on why object caching is recommended for their plugin. | ||
| * | ||
| * @since 6.1.0 | ||
| * | ||
| * @param string $notes The notes appended to the health check description. | ||
| * @param array $available_services The list of available persistent object cache services. | ||
| */ | ||
| $notes = apply_filters( 'site_status_persistent_object_cache_notes', $notes, $available_services ); | ||
|
felixarntz marked this conversation as resolved.
|
||
|
|
||
| $result['status'] = 'recommended'; | ||
| $result['label'] = __( 'You should use a persistent object cache' ); | ||
| $result['description'] .= sprintf( | ||
| '<p>%s</p>', | ||
| wp_kses( | ||
| $notes, | ||
| array( | ||
| 'a' => array( 'href' => true ), | ||
| 'code' => true, | ||
| 'em' => true, | ||
| 'strong' => true, | ||
| ) | ||
| ) | ||
| ); | ||
|
|
||
| return $result; | ||
| } | ||
|
|
||
| /** | ||
| * Return a set of tests that belong to the site status page. | ||
| * | ||
|
|
@@ -2373,6 +2472,14 @@ public static function get_tests() { | |
| ); | ||
| } | ||
|
|
||
| // Only check for a persistent object cache in production environments to not unnecessarily promote complicated setups. | ||
| if ( 'production' === wp_get_environment_type() ) { | ||
|
manuelRod marked this conversation as resolved.
manuelRod marked this conversation as resolved.
|
||
| $tests['direct']['persistent_object_cache'] = array( | ||
|
felixarntz marked this conversation as resolved.
|
||
| 'label' => __( 'Persistent object cache' ), | ||
| 'test' => 'persistent_object_cache', | ||
| ); | ||
| } | ||
|
|
||
| /** | ||
| * Add or modify which site status tests are run on a site. | ||
| * | ||
|
|
@@ -2848,4 +2955,123 @@ public function is_development_environment() { | |
| return in_array( wp_get_environment_type(), array( 'development', 'local' ), true ); | ||
| } | ||
|
|
||
| /** | ||
| * Determines whether to suggest using a persistent object cache. | ||
| * | ||
| * @since 6.1.0 | ||
| * | ||
| * @global wpdb $wpdb WordPress database abstraction object. | ||
| * | ||
| * @return bool Whether to suggest using a persistent object cache. | ||
| */ | ||
| public function should_suggest_persistent_object_cache() { | ||
| global $wpdb; | ||
|
|
||
| if ( is_multisite() ) { | ||
| return true; | ||
| } | ||
|
|
||
| /** | ||
| * Filters to force suggestion to use a persistent object cache and bypass threshold checks. | ||
| * | ||
| * @since 6.1.0 | ||
| * | ||
| * @param bool $suggest Whether to suggest using a persistent object cache. | ||
| */ | ||
| if ( apply_filters( 'site_status_suggest_persistent_object_cache', false ) ) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @manuelRod A bit late, but I am just realizing that this should rather follow a more appropriate short-circuiting behavior: Right now, the only way to short-circuit would be to actually recommend a persistent object cache. But it also needs to be possible to run custom logic that would result in not recommending a persistent object cache. So I think the default value here should be This is a trivial change, which is compatible with the current behavior, it just expands it to also allow returning |
||
| return true; | ||
| } | ||
|
|
||
| /** | ||
| * Filters the thresholds used to determine whether to suggest the use of a persistent object cache. | ||
| * | ||
| * @since 6.1.0 | ||
| * | ||
| * @param array $thresholds The list of threshold names and numbers. | ||
| */ | ||
| $thresholds = apply_filters( | ||
| 'site_status_persistent_object_cache_thresholds', | ||
| array( | ||
| 'alloptions_count' => 500, | ||
| 'alloptions_bytes' => 100000, | ||
| 'comments_count' => 1000, | ||
| 'options_count' => 1000, | ||
| 'posts_count' => 1000, | ||
| 'terms_count' => 1000, | ||
| 'users_count' => 1000, | ||
| ) | ||
| ); | ||
|
|
||
| $alloptions = wp_load_alloptions(); | ||
|
|
||
| if ( $thresholds['alloptions_count'] < count( $alloptions ) ) { | ||
| return true; | ||
| } | ||
|
|
||
| if ( $thresholds['alloptions_bytes'] < strlen( serialize( $alloptions ) ) ) { | ||
| return true; | ||
| } | ||
|
|
||
| $table_names = implode( "','", array( $wpdb->comments, $wpdb->options, $wpdb->posts, $wpdb->terms, $wpdb->users ) ); | ||
|
|
||
| // With InnoDB the `TABLE_ROWS` are estimates, which are accurate enough and faster to retrieve than individual `COUNT()` queries. | ||
| $results = $wpdb->get_results( | ||
| $wpdb->prepare( | ||
| // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- This query cannot use interpolation. | ||
| "SELECT TABLE_NAME AS 'table', TABLE_ROWS AS 'rows', SUM(data_length + index_length) as 'bytes' FROM information_schema.TABLES WHERE TABLE_SCHEMA = %s AND TABLE_NAME IN ('$table_names') GROUP BY TABLE_NAME;", | ||
| DB_NAME | ||
| ), | ||
| OBJECT_K | ||
| ); | ||
|
|
||
| $threshold_map = array( | ||
| 'comments_count' => $wpdb->comments, | ||
| 'options_count' => $wpdb->options, | ||
| 'posts_count' => $wpdb->posts, | ||
| 'terms_count' => $wpdb->terms, | ||
| 'users_count' => $wpdb->users, | ||
| ); | ||
|
|
||
| foreach ( $threshold_map as $threshold => $table ) { | ||
| if ( $thresholds[ $threshold ] <= $results[ $table ]->rows ) { | ||
| return true; | ||
| } | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| /** | ||
| * Returns a list of available persistent object cache services. | ||
| * | ||
| * @since 6.1.0 | ||
| * | ||
| * @return array The list of available persistent object cache services. | ||
| */ | ||
| private function available_object_cache_services() { | ||
| $extensions = array_map( | ||
| 'extension_loaded', | ||
| array( | ||
| 'APCu' => 'apcu', | ||
| 'Redis' => 'redis', | ||
| 'Relay' => 'relay', | ||
| 'Memcache' => 'memcache', | ||
| 'Memcached' => 'memcached', | ||
| ) | ||
| ); | ||
|
|
||
| $services = array_keys( array_filter( $extensions ) ); | ||
|
|
||
| /** | ||
| * Filters the persistent object cache services available to the user. | ||
| * | ||
| * This can be useful to hide or add services not included in the defaults. | ||
| * | ||
| * @since 6.1.0 | ||
| * | ||
| * @param array $services The list of available persistent object cache services. | ||
| */ | ||
| return apply_filters( 'site_status_available_object_cache_services', $services ); | ||
| } | ||
|
|
||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To me this sounds incorrect.