Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions app/AbstractUseStaleRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,10 @@ protected function responseFromCache(): ?Response

protected function writeResponseToCache(): void
{
if ($this->shouldWriteResponseToCache()) {
Cache::tags($this->getCacheTags())->put($this->refreshCacheKey(), 'refresh after', $this->refreshAfter());
if (!$this->shouldWriteResponseToCache()) {
return;
}
Cache::tags($this->getCacheTags())->put($this->refreshCacheKey(), 'refresh after', $this->refreshAfter());
parent::writeResponseToCache();
}

Expand Down
57 changes: 57 additions & 0 deletions tests/Feature/AbstractUseStaleRequestTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,63 @@ public function testRefreshOnNextRequest(): void
self::assertTrue($request->needsRefresh(), 'But we want to refresh opportunistically');
}

public function testCacheHitDoesNotWriteRefreshMarker(): void
{
$request = new ConcreteUseStaleRequest('thing');

self::mockRequestCachedResponse($request, 'cached body');
Cache::tags($request->getCacheTags())->put(
$request->refreshCacheKey(),
'sentinel',
Carbon::now()->addMinutes(15),
);

self::assertSame('cached body', $request->sync());

self::assertSame(
'sentinel',
Cache::tags($request->getCacheTags())->get($request->refreshCacheKey()),
'Refresh marker should be untouched on a cache hit — writeResponseToCache must early-return.',
);
}

public function testFreshFetchWritesRefreshMarker(): void
{
$this->mockGuzzleWithTapper()->addMatchBody('GET', '/test/', 'fresh');
$request = new ConcreteUseStaleRequest('thing');

self::assertNull(
Cache::tags($request->getCacheTags())->get($request->refreshCacheKey()),
'Marker should not exist before first fetch.',
);

self::assertSame('fresh', $request->sync());

self::assertSame(
'refresh after',
Cache::tags($request->getCacheTags())->get($request->refreshCacheKey()),
'A successful live fetch must write the refresh marker.',
);
}

public function testWriteCacheDisabledSkipsRefreshMarker(): void
{
$this->mockGuzzleWithTapper()->addMatchBody('GET', '/test/', 'fresh');
$request = new ConcreteUseStaleRequest('thing');
$request->setWriteCache(false);

self::assertSame('fresh', $request->sync());

self::assertNull(
Cache::tags($request->getCacheTags())->get($request->refreshCacheKey()),
'setWriteCache(false) must prevent the refresh marker write.',
);
self::assertFalse(
$request->canBeFulfilledByCache(),
'setWriteCache(false) must also prevent the response from being cached.',
);
}

public function testCacheBehaviorUnderHeavyLoad(): void
{
Queue::fake();
Expand Down