Skip to content

refactor: early-return writeResponseToCache on cache hit#32

Merged
jwadhams merged 1 commit into
developmentfrom
refactor/skip-write-on-cache-hit
May 1, 2026
Merged

refactor: early-return writeResponseToCache on cache hit#32
jwadhams merged 1 commit into
developmentfrom
refactor/skip-write-on-cache-hit

Conversation

@an-adamchuk
Copy link
Copy Markdown

@an-adamchuk an-adamchuk commented May 1, 2026

Summary

Restructure AbstractUseStaleRequest::writeResponseToCache() to early-return when shouldWriteResponseToCache() is false, instead of wrapping only the refresh-marker write and then falling through to parent::writeResponseToCache().

Why

The previous shape was correct in net effect — the parent already short-circuits on cache hit via its own guard — but it had two drawbacks:

  1. On every cache-hit invocation it still walked into parent::writeResponseToCache(), doing duplicate guard work that produced no side effects.
  2. Subclasses overriding writeResponseToCache() got an unclear contract: calling parent:: looked like it might do something, but actually never did on a cache hit.

The new shape makes the no-op explicit. If a subclass calls parent::writeResponseToCache() and adds side effects after, the parent's behavior is now unambiguous: it either fully wrote (marker + response) or it didn't run at all.

This is motivated by debugging an AIS-side bug (MR-7089) where a subclass of AbstractUseStaleRequest added Cache::tags(...)->flush() after parent::writeResponseToCache(). The flush fired on every cache hit because nothing in the chain signalled "no write happened." Cleaner framework semantics make that class of mistake easier to spot.

What changed

  • app/AbstractUseStaleRequest.phpwriteResponseToCache() now returns at the top when the guard is false.
  • tests/Feature/AbstractUseStaleRequestTest.php — three new tests covering the three branches:
    • testCacheHitDoesNotWriteRefreshMarker — seeds a sentinel marker, calls sync(), asserts the sentinel survives.
    • testFreshFetchWritesRefreshMarker — asserts the marker is written with value 'refresh after' after a live fetch.
    • testWriteCacheDisabledSkipsRefreshMarker — asserts setWriteCache(false) blocks both the marker write and the response write.

Behavior change

None at the framework boundary — all existing tests should still pass, including testCacheBehaviorUnderHeavyLoad which exercises the full lifecycle. The parent method simply isn't invoked on a cache hit anymore (it would have no-op'd anyway).

Test plan

  • vendor/bin/phpunit tests/Feature/AbstractUseStaleRequestTest.php passes locally
  • Full suite passes in CI

Skip the parent invocation when shouldWriteResponseToCache() is false.
Behavior is unchanged - the parent already short-circuits via its own
guard - but the structure is clearer and avoids walking into the parent
when no write will happen.

Adds tests covering cache hit (refresh marker untouched), fresh fetch
(marker written), and setWriteCache(false) (marker skipped even on a
fresh fetch).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@jwadhams jwadhams merged commit 55d8224 into development May 1, 2026
21 checks passed
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.

3 participants