From a188f0341c99c8e7a7639634ea28c2aede2fd877 Mon Sep 17 00:00:00 2001 From: Kamran Abdul Aziz Date: Tue, 4 Aug 2026 01:42:41 +0530 Subject: [PATCH 1/6] Add transients size check --- composer.json | 2 +- doctor.yml | 2 + features/check-transients-size.feature | 80 ++++++++++++++++++++++++++ features/check.feature | 1 + src/Check/Transients_Size.php | 61 ++++++++++++++++++++ src/Command.php | 2 + 6 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 features/check-transients-size.feature create mode 100644 src/Check/Transients_Size.php diff --git a/composer.json b/composer.json index cdf4806..683132b 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,7 @@ "wp-cli/checksum-command": "^2", "wp-cli/core-command": "^2", "wp-cli/cron-command": "^2", - "wp-cli/entity-command": "^2", + "wp-cli/entity-command": "^2.8.12", "wp-cli/extension-command": "^2", "wp-cli/language-command": "^2", "wp-cli/wp-cli": "^2.13" diff --git a/doctor.yml b/doctor.yml index bf8fbf9..cddcad3 100644 --- a/doctor.yml +++ b/doctor.yml @@ -1,6 +1,8 @@ # Default check configuration for `wp doctor` autoload-options-size: check: Autoload_Options_Size +transients-size: + check: Transients_Size constant-savequeries-falsy: check: Constant_Definition options: diff --git a/features/check-transients-size.feature b/features/check-transients-size.feature new file mode 100644 index 0000000..cedff76 --- /dev/null +++ b/features/check-transients-size.feature @@ -0,0 +1,80 @@ +Feature: Check the size of autoloaded transients + + Scenario: Verify check description + Given an empty directory + + When I run `wp doctor list --fields=name,description` + Then STDOUT should be a table containing rows: + | name | description | + | transients-size | Warns when autoloaded transients size exceeds threshold of 900 kb. | + + Scenario: Autoloaded transients are less than 900 kb + Given a WP install + + When I run `wp doctor check transients-size --fields=name,status` + Then STDOUT should be a table containing rows: + | name | status | + | transients-size | success | + + When I run `wp doctor check transients-size --fields=message` + Then STDOUT should contain: + """ + is less than threshold (900kb) + """ + + Scenario: Autoloaded transients are greater than 900 kb + Given a WP install + And a create-large-transients.php file: + """ + true, + 'autoload' => 'on', + 'format' => 'total_bytes', + ) + ); + $total_bytes = (int) ob_get_clean(); + + $threshold_bytes = $this->threshold_kb * 1024; + $human_threshold = self::format_bytes( $threshold_bytes ); + $human_total = self::format_bytes( $total_bytes ); + if ( $threshold_bytes < $total_bytes ) { + $this->set_status( 'warning' ); + $this->set_message( "Autoloaded transients size ({$human_total}) exceeds threshold ({$human_threshold})" ); + } else { + $this->set_status( 'success' ); + $this->set_message( "Autoloaded transients size ({$human_total}) is less than threshold ({$human_threshold})." ); + } + } + + /** + * @param int|float $size Size in bytes. + * @param int $precision Precision. + * @return string + */ + private static function format_bytes( $size, $precision = 2 ) { + if ( 0 >= $size ) { + return '0'; + } + + $base = log( $size, 1024 ); + $suffixes = array( '', 'kb', 'mb', 'g', 't' ); + return round( pow( 1024, $base - floor( $base ) ), $precision ) . $suffixes[ (int) floor( $base ) ]; + } +} diff --git a/src/Command.php b/src/Command.php index 3dd5753..da86f85 100644 --- a/src/Command.php +++ b/src/Command.php @@ -28,6 +28,7 @@ * | name | description | * +----------------------------+--------------------------------------------------------------------------------+ * | autoload-options-size | Warns when autoloaded options size exceeds threshold of 900 kb. | + * | transients-size | Warns when autoloaded transients size exceeds threshold of 900 kb. | * | constant-savequeries-falsy | Confirms expected state of the SAVEQUERIES constant. | * | constant-wp-debug-falsy | Confirms expected state of the WP_DEBUG constant. | * | core-update | Errors when new WordPress minor release is available; warns for major release. | @@ -325,6 +326,7 @@ function ( $check ) { * | name | description | * +----------------------------+--------------------------------------------------------------------------------+ * | autoload-options-size | Warns when autoloaded options size exceeds threshold of 900 kb. | + * | transients-size | Warns when autoloaded transients size exceeds threshold of 900 kb. | * | constant-savequeries-falsy | Confirms expected state of the SAVEQUERIES constant. | * | constant-wp-debug-falsy | Confirms expected state of the WP_DEBUG constant. | * | core-update | Errors when new WordPress minor release is available; warns for major release. | From 8b3b086a59a1cc24c1be481f77faf6f4a5bbdf4c Mon Sep 17 00:00:00 2001 From: Kamran Abdul Aziz Date: Tue, 4 Aug 2026 02:04:14 +0530 Subject: [PATCH 2/6] Fix transient size test with object cache --- features/check-transients-size.feature | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/features/check-transients-size.feature b/features/check-transients-size.feature index cedff76..5eff62d 100644 --- a/features/check-transients-size.feature +++ b/features/check-transients-size.feature @@ -29,7 +29,7 @@ Feature: Check the size of autoloaded transients Date: Wed, 5 Aug 2026 03:56:39 +0530 Subject: [PATCH 3/6] Share byte formatting across size checks --- features/check-transients-size.feature | 32 ++++++++++++++++++++++++++ src/Check.php | 18 +++++++++++++++ src/Check/Autoload_Options_Size.php | 11 --------- src/Check/Transients_Size.php | 15 ------------ 4 files changed, 50 insertions(+), 26 deletions(-) diff --git a/features/check-transients-size.feature b/features/check-transients-size.feature index 5eff62d..bdf5f91 100644 --- a/features/check-transients-size.feature +++ b/features/check-transients-size.feature @@ -79,3 +79,35 @@ Feature: Check the size of autoloaded transients """ is less than threshold (800kb) """ + + Scenario: Zero threshold is formatted safely + Given a WP install + And a custom.yml file: + """ + transients-size: + class: WP_CLI\Doctor\Check\Transients_Size + options: + threshold_kb: 0 + """ + + When I run `wp doctor check transients-size --fields=message --config=custom.yml` + Then STDOUT should contain: + """ + threshold (0) + """ + + Scenario: Very large thresholds are formatted safely + Given a WP install + And a custom.yml file: + """ + transients-size: + class: WP_CLI\Doctor\Check\Transients_Size + options: + threshold_kb: 1099511627776 + """ + + When I run `wp doctor check transients-size --fields=message --config=custom.yml` + Then STDOUT should contain: + """ + is less than threshold (1024t) + """ diff --git a/src/Check.php b/src/Check.php index c86b31b..ee0ff91 100644 --- a/src/Check.php +++ b/src/Check.php @@ -87,6 +87,24 @@ protected function set_message( $message ) { $this->_message = $message; } + /** + * Format a byte count for check result messages. + * + * @param int|float $size Size in bytes. + * @param int $precision Precision. + * @return string + */ + protected static function format_bytes( $size, $precision = 2 ) { + if ( 0 >= $size ) { + return '0'; + } + + $suffixes = array( '', 'kb', 'mb', 'g', 't' ); + $base = min( (int) floor( log( $size, 1024 ) ), count( $suffixes ) - 1 ); + + return round( $size / pow( 1024, $base ), $precision ) . $suffixes[ $base ]; + } + /** * Run the check. * diff --git a/src/Check/Autoload_Options_Size.php b/src/Check/Autoload_Options_Size.php index 8752410..db2f3c7 100644 --- a/src/Check/Autoload_Options_Size.php +++ b/src/Check/Autoload_Options_Size.php @@ -42,15 +42,4 @@ public function run() { $this->set_message( "Autoloaded options size ({$human_total}) is less than threshold ({$human_threshold})." ); } } - - /** - * @param int|float $size Size in bytes. - * @param int $precision Precision. - * @return string - */ - private static function format_bytes( $size, $precision = 2 ) { - $base = log( $size, 1024 ); - $suffixes = array( '', 'kb', 'mb', 'g', 't' ); - return round( pow( 1024, $base - floor( $base ) ), $precision ) . $suffixes[ (int) floor( $base ) ]; - } } diff --git a/src/Check/Transients_Size.php b/src/Check/Transients_Size.php index 34b651a..9f10000 100644 --- a/src/Check/Transients_Size.php +++ b/src/Check/Transients_Size.php @@ -43,19 +43,4 @@ public function run() { $this->set_message( "Autoloaded transients size ({$human_total}) is less than threshold ({$human_threshold})." ); } } - - /** - * @param int|float $size Size in bytes. - * @param int $precision Precision. - * @return string - */ - private static function format_bytes( $size, $precision = 2 ) { - if ( 0 >= $size ) { - return '0'; - } - - $base = log( $size, 1024 ); - $suffixes = array( '', 'kb', 'mb', 'g', 't' ); - return round( pow( 1024, $base - floor( $base ) ), $precision ) . $suffixes[ (int) floor( $base ) ]; - } } From 02706d7e37e2039de32083c5f9ef93d1fb9c6dbe Mon Sep 17 00:00:00 2001 From: Kamran Abdul Aziz Date: Wed, 5 Aug 2026 04:08:46 +0530 Subject: [PATCH 4/6] Test exact transient size threshold --- features/check-autoload-options-size.feature | 4 +- features/check-transients-size.feature | 49 ++++++++++++++++++-- src/Check/Autoload_Options_Size.php | 2 +- src/Check/Transients_Size.php | 2 +- 4 files changed, 50 insertions(+), 7 deletions(-) diff --git a/features/check-autoload-options-size.feature b/features/check-autoload-options-size.feature index 1630fb6..500a506 100644 --- a/features/check-autoload-options-size.feature +++ b/features/check-autoload-options-size.feature @@ -19,7 +19,7 @@ Feature: Check the size of autoloaded options When I run `wp doctor check autoload-options-size --fields=message` Then STDOUT should contain: """ - is less than threshold (900kb) + does not exceed threshold (900kb) """ @less-than-wp-6.5 @@ -59,5 +59,5 @@ Feature: Check the size of autoloaded options When I run `wp doctor check autoload-options-size --fields=message --config=custom.yml` Then STDOUT should contain: """ - is less than threshold (800kb) + does not exceed threshold (800kb) """ diff --git a/features/check-transients-size.feature b/features/check-transients-size.feature index bdf5f91..46daac2 100644 --- a/features/check-transients-size.feature +++ b/features/check-transients-size.feature @@ -19,7 +19,50 @@ Feature: Check the size of autoloaded transients When I run `wp doctor check transients-size --fields=message` Then STDOUT should contain: """ - is less than threshold (900kb) + does not exceed threshold (900kb) + """ + + Scenario: Autoloaded transients equal 900 kb + Given a WP install + And a wp-content/mu-plugins/exact-threshold-transients.php file: + """ + get_col( "SELECT option_name FROM {$wpdb->options}" ); + foreach ( $option_names as $option_name ) { + if ( + 0 === strpos( $option_name, '_transient_' ) + || 0 === strpos( $option_name, '_site_transient_' ) + ) { + delete_option( $option_name ); + } + } + + add_option( '_transient_doctor_exact_threshold', str_repeat( '9', 900 * 1024 ), '', true ); + }, + PHP_INT_MAX + ); + """ + + When I run `wp option list --transients --autoload=on --format=total_bytes` + Then STDOUT should be: + """ + 921600 + """ + + When I run `wp doctor check transients-size --fields=name,status` + Then STDOUT should be a table containing rows: + | name | status | + | transients-size | success | + + When I run `wp doctor check transients-size --fields=message` + Then STDOUT should contain: + """ + Autoloaded transients size (900kb) does not exceed threshold (900kb). """ Scenario: Autoloaded transients are greater than 900 kb @@ -77,7 +120,7 @@ Feature: Check the size of autoloaded transients When I run `wp doctor check transients-size --fields=message --config=custom.yml` Then STDOUT should contain: """ - is less than threshold (800kb) + does not exceed threshold (800kb) """ Scenario: Zero threshold is formatted safely @@ -109,5 +152,5 @@ Feature: Check the size of autoloaded transients When I run `wp doctor check transients-size --fields=message --config=custom.yml` Then STDOUT should contain: """ - is less than threshold (1024t) + does not exceed threshold (1024t) """ diff --git a/src/Check/Autoload_Options_Size.php b/src/Check/Autoload_Options_Size.php index db2f3c7..4ff3ffa 100644 --- a/src/Check/Autoload_Options_Size.php +++ b/src/Check/Autoload_Options_Size.php @@ -39,7 +39,7 @@ public function run() { $this->set_message( "Autoloaded options size ({$human_total}) exceeds threshold ({$human_threshold})" ); } else { $this->set_status( 'success' ); - $this->set_message( "Autoloaded options size ({$human_total}) is less than threshold ({$human_threshold})." ); + $this->set_message( "Autoloaded options size ({$human_total}) does not exceed threshold ({$human_threshold})." ); } } } diff --git a/src/Check/Transients_Size.php b/src/Check/Transients_Size.php index 9f10000..69de176 100644 --- a/src/Check/Transients_Size.php +++ b/src/Check/Transients_Size.php @@ -40,7 +40,7 @@ public function run() { $this->set_message( "Autoloaded transients size ({$human_total}) exceeds threshold ({$human_threshold})" ); } else { $this->set_status( 'success' ); - $this->set_message( "Autoloaded transients size ({$human_total}) is less than threshold ({$human_threshold})." ); + $this->set_message( "Autoloaded transients size ({$human_total}) does not exceed threshold ({$human_threshold})." ); } } } From 792daf9bf85e012e4fc2a7cedb66eb86404e27a7 Mon Sep 17 00:00:00 2001 From: Kamran Abdul Aziz Date: Tue, 15 Sep 2026 03:14:46 +0530 Subject: [PATCH 5/6] Use consistent gb and tb suffixes in byte formatting The shared formatter printed kb and mb but bare g and t for the larger units. schlessera asked for consistent suffixes before the feature test locks the output in. --- src/Check.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Check.php b/src/Check.php index ee0ff91..0f31142 100644 --- a/src/Check.php +++ b/src/Check.php @@ -99,7 +99,7 @@ protected static function format_bytes( $size, $precision = 2 ) { return '0'; } - $suffixes = array( '', 'kb', 'mb', 'g', 't' ); + $suffixes = array( '', 'kb', 'mb', 'gb', 'tb' ); $base = min( (int) floor( log( $size, 1024 ) ), count( $suffixes ) - 1 ); return round( $size / pow( 1024, $base ), $precision ) . $suffixes[ $base ]; From 41788367c72722b046a984a32d8c5d06074b337d Mon Sep 17 00:00:00 2001 From: Kamran Abdul Aziz Date: Tue, 15 Sep 2026 03:14:46 +0530 Subject: [PATCH 6/6] Seed the exact-threshold scenario once instead of using an mu-plugin The mu-plugin re-ran inside every wp invocation, including the measured option list and doctor check runs. The scenario now warms the lazy core block CSS transients with one doctor check run, then seeds a single transient whose size is measured against the same option list query, so the total lands exactly on the threshold without any code running during the measured commands. --- features/check-transients-size.feature | 31 +++++++++----------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/features/check-transients-size.feature b/features/check-transients-size.feature index 46daac2..bd923f9 100644 --- a/features/check-transients-size.feature +++ b/features/check-transients-size.feature @@ -24,29 +24,20 @@ Feature: Check the size of autoloaded transients Scenario: Autoloaded transients equal 900 kb Given a WP install - And a wp-content/mu-plugins/exact-threshold-transients.php file: + # Warm the lazy core caches (block CSS transients) so the ambient autoloaded + # transients stop changing between the seed run and the assertions below. + And I run `wp doctor check transients-size --fields=name,status` + And a seed-exact-threshold-transient.php file: """ get_col( "SELECT option_name FROM {$wpdb->options}" ); - foreach ( $option_names as $option_name ) { - if ( - 0 === strpos( $option_name, '_transient_' ) - || 0 === strpos( $option_name, '_site_transient_' ) - ) { - delete_option( $option_name ); - } - } - - add_option( '_transient_doctor_exact_threshold', str_repeat( '9', 900 * 1024 ), '', true ); - }, - PHP_INT_MAX + $existing_bytes = (int) WP_CLI::runcommand( + 'option list --transients --autoload=on --format=total_bytes', + array( 'launch' => false, 'return' => true ) ); + + add_option( '_transient_doctor_exact_threshold', str_repeat( '9', ( 900 * 1024 ) - $existing_bytes ), '', true ); """ + And I run `wp eval-file seed-exact-threshold-transient.php` When I run `wp option list --transients --autoload=on --format=total_bytes` Then STDOUT should be: @@ -152,5 +143,5 @@ Feature: Check the size of autoloaded transients When I run `wp doctor check transients-size --fields=message --config=custom.yml` Then STDOUT should contain: """ - does not exceed threshold (1024t) + does not exceed threshold (1024tb) """