Skip to content

Fix: Meta Description: SEO plugin detection cache never expires and skips the "no plugin" case - #973

Open
hbhalodia wants to merge 5 commits into
WordPress:developfrom
hbhalodia:fix/issue-970
Open

hbhalodia wants to merge 5 commits into
WordPress:developfrom
hbhalodia:fix/issue-970

Conversation

@hbhalodia

@hbhalodia hbhalodia commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

What?

Closes #970

Why?

  1. The positive result is stored with no expiry and is only cleared on deactivated_plugin - a hook that's registered only while the Meta Description experiment is enabled. So the cache can go stale and never self-heal.
  2. The "no SEO plugin active" result is never cached, so a full plugin scan runs on every call, including the front-end output_meta_description() path.

How?

  • Updates the transient to cache it for a day.
  • Update the activated, deactivated hook outside of experiment, so a cache would invalidate regardless of experiment is enabled or not.

Use of AI Tools

AI assistance: Yes
Tool(s): Claude Code
Model(s): Opus 5
Used for: Code, Unit Test under the direction provided by me. Implementation reviwed by me.

Testing Instructions

  1. Activate a supported SEO plugin (e.g. Yoast) + enable the Meta Description experiment; trigger meta handling once to cache the slug.
  2. Disable the Meta Description experiment.
  3. Deactivate the SEO plugin.
  4. Re-enable the experiment, This should use the plugin's meta key, i.e wpai_meta_description.

Changelog Entry

Fixed - Cached the active SEO plugin detection - with a TTL and immediate invalidation on any plugin activation/deactivation - so meta description meta-key lookups no longer re-scan active plugins on every request.

Open WordPress Playground Preview

@hbhalodia
hbhalodia requested a review from a team August 25, 2026 06:35
@github-actions

github-actions Bot commented Aug 25, 2026

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: hbhalodia <hbhalodia@git.wordpress.org>
Co-authored-by: dkotter <dkotter@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@codecov

codecov Bot commented Aug 25, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 60.60606% with 13 lines in your changes missing coverage. Please review.
✅ Project coverage is 74.54%. Comparing base (8016220) to head (b482d0b).

Files with missing lines Patch % Lines
...des/Abilities/Meta_Description/SEO_Integration.php 55.55% 12 Missing ⚠️
includes/Admin/Upgrades/V1_4_0.php 80.00% 1 Missing ⚠️
Additional details and impacted files
@@              Coverage Diff              @@
##             develop     #973      +/-   ##
=============================================
- Coverage      74.57%   74.54%   -0.04%     
- Complexity      3132     3141       +9     
=============================================
  Files            132      133       +1     
  Lines          12213    12237      +24     
=============================================
+ Hits            9108     9122      +14     
- Misses          3105     3115      +10     
Flag Coverage Δ
unit 74.54% <60.60%> (-0.04%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Comment thread includes/Abilities/Meta_Description/SEO_Integration.php
Comment thread includes/Abilities/Meta_Description/SEO_Integration.php
@hbhalodia
hbhalodia requested a review from dkotter August 26, 2026 10:13
@dkotter dkotter added this to the 1.4.0 milestone Aug 26, 2026

@dkotter dkotter left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Things look good to me, thanks! Holding on merging this for now though as we add a new upgrade routine here that has the file name hardcoded to v1.4.0. If we end up doing a minor release (v1.3.1 as an example) prior to releasing 1.4.0, this code will be inaccurate. Will merge this once we know for sure the version we'll be releasing this as

@dugyen dugyen left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed this in detail (diff, tests, and interaction with the surrounding code). This looks like a solid, correct fix — didn't find a blocking issue.

What it does right, matching both parts of #970:

  • Adds a DAY_IN_SECONDS TTL to the positive cache in SEO_Integration.php, and now also caches a 'none' sentinel for "no SEO plugin active" so the front-end output_meta_description() path stops re-scanning every plugin on every request.
  • Moves cache invalidation off Meta_Description::register() and onto an unconditional SEO_Integration::register_cache_invalidation() called from Main::load() (hooked to plugins_loaded), so the cache now self-heals via activated_plugin/deactivated_plugin regardless of whether the experiment is enabled — exactly the "invalidation independent of experiment toggle" fix the issue asked for.
  • Goes a bit further than requested: the new V1_4_0 upgrade routine deletes the old non-expiring transient once on update, so sites with an already-stale infinite cache get a clean slate rather than waiting on the new logic. Also handles multisite network-wide activation by clearing the cache on every site in the network.
  • Test coverage is thorough: positive/negative caching, TTL-independent invalidation on both hooks, the upgrade routine's version-gating (skips on fresh installs and already-upgraded sites), and multisite network-wide vs. single-site invalidation scope.
  • I checked for stale references to the removed clear_active_plugin_cache() method/hook elsewhere in the codebase, including the pre-existing Meta_DescriptionTest.php — none found, so no regression there.

Two minor, non-blocking observations:

  1. The multisite network-wide path (clear_cache_for_network()) fetches every site (get_sites(['number' => 0])) and does a switch_to_blog() round-trip per site on every plugin activate/deactivate, not just SEO-relevant ones. Fine for typical networks; could be slow on a network with many thousands of sites.
  2. The phpcs:ignore comment on switch_to_blog() names a specific VIPMinimum sniff — worth confirming CI is happy with that exact sniff name for this repo's ruleset, but harmless either way.

Nice work, @hbhalodia.


AI assistance: Yes. Tool(s): Claude Code (Sonnet 5). Used for: reading the diff and tracing it against the rest of the codebase to write this review; I read and take responsibility for the assessment above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Meta Description: SEO plugin detection cache never expires and skips the "no plugin" case

3 participants