fix(newspack-popups): cache empty popups_for_post() results#482
Open
jhalitschke wants to merge 2 commits into
Open
fix(newspack-popups): cache empty popups_for_post() results#482jhalitschke wants to merge 2 commits into
jhalitschke wants to merge 2 commits into
Conversation
self::$popups defaulted to [] and the cache guard was `! empty( self::$popups )`, so a legitimate empty result (no popups eligible for the current request) was indistinguishable from "not yet computed". Every call re-ran assess_has_disabled_popups(), parse_view_as(), retrieve_eligible_popups() and a should_display() pass over every campaign — on archive pages this repeats once per post instead of once per request. Switch the memoization guard to null, since an empty array is a valid, cacheable result. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR aims to reduce redundant work in newspack-popups by ensuring Newspack_Popups_Inserter::popups_for_post() memoization treats an empty result as a valid cache hit (using null as the “not computed yet” sentinel).
Changes:
- Change
Newspack_Popups_Inserter::$popupsdefault from[]tonulland update its docblock to reflect the new sentinel behavior. - Update the memoization guard in
popups_for_post()from! empty( self::$popups )tonull !== self::$popupsso empty results are cached/hit.
Copilot flagged that assess_has_disabled_popups() and should_display() both depend on the current post (post meta, post type, taxonomy terms), so a single request-wide cache — which is what the previous fix in this PR produced — can return a stale result for a post other than the one it was computed for. On an archive page looping over posts with different categories, this could suppress prompts that should display, or show prompts that shouldn't, for every post after the first. Split the cache into two tiers: - self::$eligible_popups: the raw retrieve_eligible_popups() query result, which doesn't depend on the current post, memoized once per request as before (this is the expensive part — a WP_Query). - self::$popups: the post-dependent should_display() filter result, now keyed by post ID instead of a single value, so different posts in the same request get their own cache entry. array_key_exists() (rather than an empty()/null check) distinguishes "not yet computed for this post ID" from "computed and empty", so the original empty-result bug this PR set out to fix stays fixed on a per-post basis. Update the two tests that seed Newspack_Popups_Inserter::$popups directly via reflection (test-block-theme-header-insertion.php, test-overlay-queueing.php) to seed at the current post ID instead of as a flat list, matching the new keyed shape. The existing setValue(null, []) resets in those tests' set_up()/tear_down() are unaffected, since an empty array still correctly means "nothing cached for any post". Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
All Submissions:
Changes proposed in this Pull Request:
Re-opened against the monorepo — originally submitted as Automattic/newspack-popups#1563, auto-closed since that repo is now a read-only mirror.
Problem
Newspack_Popups_Inserter::popups_for_post()(plugins/newspack-popups/includes/class-newspack-popups-inserter.php) memoizes its result inself::$popups, guarded by:empty( [] )is alwaystrue, so whenever no campaign is eligible for the current request, the cache is written but never read back as a hit. Every subsequent call in the same request re-runsassess_has_disabled_popups(),parse_view_as(),Newspack_Popups_Model::retrieve_eligible_popups()(aWP_Query) and ashould_display()pass over every campaign.popups_for_post()is called frominsert_popups_in_content(),insert_popups_after_header(),insert_before_header()andinsert_inline_prompt_in_archive_pages(), so on an archive page this repeats once per post instead of once per request. On a site where no campaigns match the request context (e.g. all campaigns are scoped to a segment/view that excludes the current visitor), this turns into 40-50+ redundant query + evaluation passes on a single archive page load.Fix
Use
nullinstead of[]as the "not yet computed" sentinel, since an empty array is a legitimate, cacheable result:No other change in behavior: the
IS_TEST_ENVbranch already skips writing the cache, so tests are unaffected either way, and nothing else readsNewspack_Popups_Inserter::$popupsdirectly (the data-api class has its own unrelated$popupsproperty).Closes # .
How to test the changes in this Pull Request:
php -lon the changed fileretrieve_eligible_popups()per post (checked via query count / profiling)Other information: