diff --git a/core/lib/Drupal/Core/Cache/ChainedFastBackend.php b/core/lib/Drupal/Core/Cache/ChainedFastBackend.php index 6a825af..1098e01 100644 --- a/core/lib/Drupal/Core/Cache/ChainedFastBackend.php +++ b/core/lib/Drupal/Core/Cache/ChainedFastBackend.php @@ -73,6 +73,32 @@ class ChainedFastBackend implements CacheBackendInterface { protected $lastWriteTimestamp; /** + * The time at which the last write timestamp was fetched. + * + * @var float + */ + protected $lastWriteTimestampFetchTime = 0.0; + + /** + * How long, in seconds, the last write timestamp is valid. + * + * The last write timestamp is checked at least once per instantiation of + * this class (i.e., once per bin per PHP request). To minimize network + * traffic to the consistent backend, it is not rechecked within the same + * instance for this TTL duration. As a result, during this TTL window, it is + * possible for a cache invalidation that happens in a parallel request to + * not propagate to this request, but that is also the case anywhere that a + * static cache is used. + * + * 300ms is longer than most simple web requests, but lets long running + * requests (e.g., complex pages or command line processes) stay reasonably + * synchronized with changes happening in parallel requests. + * + * @var float + */ + protected $lastWriteTimestampTtl = 0.3; + + /** * Constructs a ChainedFastBackend object. * * @param \Drupal\Core\Cache\CacheBackendInterface $consistent_backend @@ -233,7 +259,10 @@ public function removeBin() { * Gets the last write timestamp. */ protected function getLastWriteTimestamp() { - if ($this->lastWriteTimestamp === NULL) { + $now = microtime(TRUE); + $timestamp_fetch_time_plus_ttl = $this->lastWriteTimestampFetchTime + $this->lastWriteTimestampTtl; + if ($this->lastWriteTimestamp === NULL || ($now > $timestamp_fetch_time_plus_ttl)) { + $this->lastWriteTimestampFetchTime = $now; $cache = $this->consistentBackend->get(self::LAST_WRITE_TIMESTAMP_PREFIX . $this->bin); $this->lastWriteTimestamp = $cache ? $cache->data : 0; }