-
Notifications
You must be signed in to change notification settings - Fork 9.4k
Description
Preconditions and environment
This race condition is hard to reproduse every time, but doing a code analysis will confirm the bug.
Method \Magento\PageCache\Model\Layout\LayoutPlugin::afterGenerateElements is called before \Magento\PageCache\Model\Layout\LayoutPlugin::afterGetOutput meaning that other actions can happen mean time.
With the code first hits \Magento\PageCache\Model\Layout\LayoutPlugin::afterGenerateElements, the FPC could be evaluated as activ and public headers are set to response.
Then imagine that we have some code that calls \Magento\Framework\Cache\Backend\RemoteSynchronizedCache::load and we have the following scenario
public function load($id, $doNotTestCacheValidity = false)
{
$localData = $this->local->load($id);
if ($localData !== false) {
if ($this->getDataVersion($localData) === $this->loadRemoteDataVersion($id)) {
return $localData;
}
}
$remoteData = $this->remote->load($id);
if ($remoteData !== false) {
$this->local->save($remoteData, $id);
return $remoteData;
} elseif ($localData && $this->_options['use_stale_cache']) {
if ($this->lock($id)) {
return false;
} else {
$this->notifyStaleCache();
return $localData;
}
}
return false;
}The following thinks needs to happen:
- data should exists in local storage ($localData) but not in redis ($remoteData)
- The lock should not succeed
- The code calls
$this->notifyStaleCache();, which then will mark FPC as disabled (\Magento\Framework\Cache\CompositeStaleCacheNotifier::cacheLoaderIsUsingStaleCache) - The the function \Magento\PageCache\Model\Layout\LayoutPlugin::afterGetOutput will not set any headers because FPC is now disabled.
Steps to reproduce
- Have magento with
stale_cache_enabled - Have varnish configured and enabled
- Have cache warmed up. To have data in local cache and Redis
- Put a breakpoint at \Magento\PageCache\Model\Layout\LayoutPlugin::afterGenerateElements and \Magento\PageCache\Model\Layout\LayoutPlugin::afterGetOutput in order to be able to simulate the next steps
- Edit \Magento\Framework\Cache\Backend\RemoteSynchronizedCache::lock to return
falsein order to simulate a lock failure in Redis - Flush Redis cache - simulate a flush cache
- Have code that reads from cache, and that cache exists in local cache
- Run the code
- When the code arrives in \Magento\PageCache\Model\Layout\LayoutPlugin::afterGetOutput, you will that the $this->config->isEnabled() will return false and
X-Magento-Tagsheaders will no be set
It's very important that during manual testing to have step 7 executed
Expected result
The page should have private content headers in order to not be cached in Varnish.
Actual result
The page is generated with cacheable HTTP headers but without X-Magento-Tags.
Those pages remains with old contend (old prices, old stock) which causes customer issues.
Those pages can not be deleted from Varnish using admin or cli commands. Varnish needs to be restarted or wait until those pages are automatically deleted (depending of the TTL set)
Additional information
No response
Release note
No response
Triage and priority
- Severity: S0 - Affects critical data or functionality and leaves users without workaround.
- Severity: S1 - Affects critical data or functionality and forces users to employ a workaround.
- Severity: S2 - Affects non-critical data or functionality and forces users to employ a workaround.
- Severity: S3 - Affects non-critical data or functionality and does not force users to employ a workaround.
- Severity: S4 - Affects aesthetics, professional look and feel, “quality” or “usability”.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status