Exhibit C-2 Evidence: commit 3652956
Committed · 3652956fa6e41393f1a11c609cbf04c6eb9a00f6
Every request loaded megabytes of dead cache
The repository itself is private; this page carries the commit as it is recorded there.
Commit message
The change
Text files only, as recorded in git. Lines starting with + were added, lines with − removed.
Files changed
---
site/wp-content/mu-plugins/hollis-migrations.php | 69 +++++++++++++++++++++++++++++++++++
site/wp-content/plugins/hc-social-feed/hc-social-feed.php | 41 ---------------------
tests/phpunit/repair/AutoloadTest.php | 50 +++++++++++++++++++++++++
3 files changed, 119 insertions(+), 41 deletions(-)
diff --git a/site/wp-content/mu-plugins/hollis-migrations.php b/site/wp-content/mu-plugins/hollis-migrations.php
new file mode 100644
index 0000000..6a79548
--- /dev/null
+++ b/site/wp-content/mu-plugins/hollis-migrations.php
@@ -0,0 +1,69 @@
+<?php
+/**
+ * Plugin Name: Hollis Creek repair migrations
+ * Description: Database changes that belong to the repair. Each step checks the current state first, so
+ * running them again changes nothing. Run by deploy.sh: `wp hollis migrate`.
+ * Version: 1.0.0
+ * Author: Hollis Creek Family Dental (fictional demo)
+ *
+ * @package Hollis\Migrations
+ */
+
+defined( 'ABSPATH' ) || exit;
+
+/**
+ * The steps, in order. Each returns a one-line description of what it did.
+ *
+ * @return array<string, callable>
+ */
+function hollis_migrations_steps() {
+ return apply_filters(
+ 'hollis_migrations_steps',
+ array(
+ 'remove-social-feed-caches' => 'hollis_migration_remove_social_feed_caches',
+ )
+ );
+}
+
+/**
+ * Runs every step.
+ *
+ * @return array<string, string> Step name => result.
+ */
+function hollis_migrations_run() {
+ $results = array();
+ foreach ( hollis_migrations_steps() as $name => $step ) {
+ $results[ $name ] = (string) call_user_func( $step );
+ }
+ update_option( 'hollis_migrations_last_run', array( gmdate( 'c' ), $results ), false );
+ return $results;
+}
+
+/**
+ * C-2: HC Social Feed is removed; its cached responses (autoloaded, ~3.5 MB) go with it.
+ *
+ * @return string
+ */
+function hollis_migration_remove_social_feed_caches() {
+ global $wpdb;
+ $like = $wpdb->esc_like( 'hcsf_' ) . '%';
+ $names = $wpdb->get_col( $wpdb->prepare( "SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE %s", $like ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery
+ $bytes = 0;
+ foreach ( $names as $name ) {
+ $bytes += strlen( maybe_serialize( get_option( $name ) ) );
+ delete_option( $name );
+ }
+ return sprintf( 'deleted %d social feed options (%s)', count( $names ), size_format( $bytes, 1 ) );
+}
+
+if ( defined( 'WP_CLI' ) && WP_CLI ) {
+ WP_CLI::add_command(
+ 'hollis migrate',
+ static function () {
+ foreach ( hollis_migrations_run() as $name => $result ) {
+ WP_CLI::log( "$name: $result" );
+ }
+ WP_CLI::success( 'Repair migrations are up to date.' );
+ }
+ );
+}
diff --git a/site/wp-content/plugins/hc-social-feed/hc-social-feed.php b/site/wp-content/plugins/hc-social-feed/hc-social-feed.php
deleted file mode 100644
index a2c4ab9..0000000
--- a/site/wp-content/plugins/hc-social-feed/hc-social-feed.php
+++ /dev/null
@@ -1,41 +0,0 @@
-<?php
-/**
- * Plugin Name: HC Social Feed
- * Description: Shows the practice's latest social posts in the footer. Caches each feed response in an option.
- * Version: 1.1.0
- * Author: Previous web developer (fictional)
- *
- * The feed service it reads was shut down in 2023; the widget has rendered nothing since, but every cached
- * response it ever stored is still an autoloaded option.
- *
- * @package HC\SocialFeed
- */
-
-defined( 'ABSPATH' ) || exit;
-
-/**
- * Stores a feed response. Called by the hourly refresh, which stopped when the service closed.
- *
- * @param string $url Feed URL.
- * @param array $data Response.
- */
-function hc_social_feed_store( $url, $data ) {
- $key = 'hcsf_cache_' . md5( $url . gmdate( 'YmdH' ) );
- add_option( $key, $data, '', 'yes' );
-}
-
-/**
- * Footer widget: the latest cached posts.
- */
-function hc_social_feed_render() {
- $items = get_option( 'hcsf_latest', array() );
- if ( empty( $items['posts'] ) ) {
- return;
- }
- echo '<ul class="social-feed">';
- foreach ( array_slice( $items['posts'], 0, 3 ) as $post ) {
- echo '<li>' . esc_html( $post['text'] ) . '</li>';
- }
- echo '</ul>';
-}
-add_action( 'clinicpress_footer_column', 'hc_social_feed_render', 20 );
diff --git a/tests/phpunit/repair/AutoloadTest.php b/tests/phpunit/repair/AutoloadTest.php
new file mode 100644
index 0000000..4762ddf
--- /dev/null
+++ b/tests/phpunit/repair/AutoloadTest.php
@@ -0,0 +1,50 @@
+<?php
+/**
+ * Exhibit C-2: what every request loads from wp_options stays small.
+ *
+ * @package Hollis\Tests
+ */
+
+/**
+ * Autoloaded options.
+ */
+class AutoloadTest extends WP_UnitTestCase {
+
+ /**
+ * Bytes of autoloaded option values, the way WordPress loads them on every request.
+ *
+ * @return int
+ */
+ private function autoload_bytes() {
+ global $wpdb;
+ $in = "'" . implode( "','", wp_autoload_values_to_autoload() ) . "'";
+ return (int) $wpdb->get_var( "SELECT SUM(LENGTH(option_value)) FROM {$wpdb->options} WHERE autoload IN ($in)" ); // phpcs:ignore
+ }
+
+ public function test_migration_removes_the_dead_feed_caches_and_autoload_drops_under_site_health_limit() {
+ // What the old plugin left behind: ten cached responses of ~300 KB, autoloaded.
+ for ( $i = 0; $i < 10; $i++ ) {
+ add_option( 'hcsf_cache_' . md5( (string) $i ), array( 'posts' => array_fill( 0, 800, str_repeat( 'smile creek ', 30 ) ) ), '', 'yes' );
+ }
+ add_option( 'hcsf_latest', array( 'posts' => array() ), '', 'yes' );
+ $this->assertGreaterThan( 2 * MB_IN_BYTES, $this->autoload_bytes() );
+
+ $results = hollis_migrations_run();
+
+ $this->assertStringContainsString( 'deleted 11 social feed options', $results['remove-social-feed-caches'] );
+ // Site Health warns above 800 KB of autoloaded options.
+ $this->assertLessThan( 800 * KB_IN_BYTES, $this->autoload_bytes() );
+ wp_cache_delete( 'alloptions', 'options' );
+ $this->assertSame( array(), preg_grep( '/^hcsf_/', array_keys( wp_load_alloptions() ) ) );
+ }
+
+ public function test_running_again_changes_nothing() {
+ hollis_migrations_run();
+ $again = hollis_migrations_run();
+ $this->assertStringContainsString( 'deleted 0 social feed options', $again['remove-social-feed-caches'] );
+ }
+
+ public function test_the_dead_plugin_is_gone_from_the_code() {
+ $this->assertDirectoryDoesNotExist( HOLLIS_CODE . '/plugins/hc-social-feed' );
+ }
+}
The proving test
tests/phpunit/repair/AutoloadTest.php
tests/phpunit/repair/AutoloadTest.php, as committed.
<?php
/**
* Exhibit C-2: what every request loads from wp_options stays small.
*
* @package Hollis\Tests
*/
/**
* Autoloaded options.
*/
class AutoloadTest extends WP_UnitTestCase {
/**
* Bytes of autoloaded option values, the way WordPress loads them on every request.
*
* @return int
*/
private function autoload_bytes() {
global $wpdb;
$in = "'" . implode( "','", wp_autoload_values_to_autoload() ) . "'";
return (int) $wpdb->get_var( "SELECT SUM(LENGTH(option_value)) FROM {$wpdb->options} WHERE autoload IN ($in)" ); // phpcs:ignore
}
public function test_migration_removes_the_dead_feed_caches_and_autoload_drops_under_site_health_limit() {
// What the old plugin left behind: ten cached responses of ~300 KB, autoloaded.
for ( $i = 0; $i < 10; $i++ ) {
add_option( 'hcsf_cache_' . md5( (string) $i ), array( 'posts' => array_fill( 0, 800, str_repeat( 'smile creek ', 30 ) ) ), '', 'yes' );
}
add_option( 'hcsf_latest', array( 'posts' => array() ), '', 'yes' );
$this->assertGreaterThan( 2 * MB_IN_BYTES, $this->autoload_bytes() );
$results = hollis_migrations_run();
$this->assertStringContainsString( 'deleted 11 social feed options', $results['remove-social-feed-caches'] );
// Site Health warns above 800 KB of autoloaded options.
$this->assertLessThan( 800 * KB_IN_BYTES, $this->autoload_bytes() );
wp_cache_delete( 'alloptions', 'options' );
$this->assertSame( array(), preg_grep( '/^hcsf_/', array_keys( wp_load_alloptions() ) ) );
}
public function test_running_again_changes_nothing() {
hollis_migrations_run();
$again = hollis_migrations_run();
$this->assertStringContainsString( 'deleted 0 social feed options', $again['remove-social-feed-caches'] );
}
public function test_the_dead_plugin_is_gone_from_the_code() {
$this->assertDirectoryDoesNotExist( HOLLIS_CODE . '/plugins/hc-social-feed' );
}
}