diff --git a/core/core.services.yml b/core/core.services.yml index 91dd43a..32b0bd5 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -207,31 +207,31 @@ services: tags: - { name: cache.bin } factory: cache_factory:get - arguments: [default, ['maximum_permanent_ttl', 86400]] + arguments: [default, ['minimum_permanent_ttl', 86400]] cache.entity: class: Drupal\Core\Cache\CacheBackendInterface tags: - { name: cache.bin } factory: cache_factory:get - arguments: [entity] + arguments: [entity, ['minimum_permanent_ttl', 86400]] cache.menu: class: Drupal\Core\Cache\CacheBackendInterface tags: - { name: cache.bin } factory: cache_factory:get - arguments: [menu] + arguments: [menu, ['minimum_permanent_ttl', 86400]] cache.render: class: Drupal\Core\Cache\CacheBackendInterface tags: - { name: cache.bin } factory: cache_factory:get - arguments: [render] + arguments: [render, ['minimum_permanent_ttl', 86400]] cache.data: class: Drupal\Core\Cache\CacheBackendInterface tags: - { name: cache.bin } factory: cache_factory:get - arguments: [data] + arguments: [data, ['minimum_permanent_ttl', 86400]] cache.discovery: class: Drupal\Core\Cache\CacheBackendInterface tags: diff --git a/core/lib/Drupal/Core/Cache/ChainedFastBackendFactory.php b/core/lib/Drupal/Core/Cache/ChainedFastBackendFactory.php index e979f43..c56c365 100644 --- a/core/lib/Drupal/Core/Cache/ChainedFastBackendFactory.php +++ b/core/lib/Drupal/Core/Cache/ChainedFastBackendFactory.php @@ -71,18 +71,31 @@ public function __construct(Settings $settings = NULL, $consistent_service_name * {@inheritdoc} */ public function get($bin, array $options = []) { + $consistent = $this->container->get($this-consistentServiceName); + if ($consistent instanceof ConfigurableCacheBackendFactoryInterface) { + $consistent_backend = $consistent->get($bin, $options); + } + else { + $consistent_backend = $consistent->get($bin); + } // Use the chained backend only if there is a fast backend available; // otherwise, just return the consistent backend directly. if (isset($this->fastServiceName)) { + $fast = $this->container->get($this->fastServiceName); + if ($fast instanceof ConfigurableCacheBackendFactoryInterface) { + $fast_backend = $fast->get($bin, $options); + } + else { + $fast_backend = $fast->get($bin); + } return new ChainedFastBackend( - // @todo: check interface. - $this->container->get($this->consistentServiceName)->get($bin, $options), - $this->container->get($this->fastServiceName)->get($bin, $options), + $consistent_backend, + $fast_backend, $bin ); } else { - return $this->container->get($this->consistentServiceName)->get($bin); + return $consistent_backend; } } diff --git a/core/lib/Drupal/Core/Cache/ConfigurablePermanentTtlInterface.php b/core/lib/Drupal/Core/Cache/ConfigurablePermanentTtlInterface.php index 14b84ce..4dbc8a4 100644 --- a/core/lib/Drupal/Core/Cache/ConfigurablePermanentTtlInterface.php +++ b/core/lib/Drupal/Core/Cache/ConfigurablePermanentTtlInterface.php @@ -6,7 +6,11 @@ * * This allows cache backends with restrictions on storage space to set a * shorter TTL for 'permanent' cache items, so that they get expired by garbage - * collection. The actual TTL used may be the same or higher than configured. + * collection. The actual TTL used may be the same or higher than configured, + * to allow 'jitter' to be applied so that items set immediately after a cache + * clear do not all expire at the same time. Cache backends should assign jitter + * higher rather than lower to avoid the risk of cache stampedes, since the + * minimum ttl could potentially be set very low for some use cases. * * @ingroup cache */ @@ -18,4 +22,5 @@ * @param int $ttl */ function setMinimumPermanentTtl($ttl); + } diff --git a/core/lib/Drupal/Core/Cache/DatabaseBackend.php b/core/lib/Drupal/Core/Cache/DatabaseBackend.php index 26db042..7582869 100644 --- a/core/lib/Drupal/Core/Cache/DatabaseBackend.php +++ b/core/lib/Drupal/Core/Cache/DatabaseBackend.php @@ -22,6 +22,13 @@ class DatabaseBackend implements CacheBackendInterface, ConfigurablePermanentTtlInterface { /** + * The 'jitter' multiplier, applied to the minimum TTL to avoid stampedes. + * + * @var float + */ + const JITTER_MULTIPLIER = 1.5; + + /** * @var string */ protected $bin; @@ -253,10 +260,12 @@ protected function doSetMultiple(array $items) { /** * Calculate permanent expiry. + * + * @return an expires timestamp based on the minimum TTL with added 'jitter'. */ protected function calculatePermanentExpire() { $minimum = $this->minimumPermanentTtl; - return rand($minimum, $minimum * 1.5) + REQUEST_TIME; + return rand($minimum, $minimum * self::JITTER_MULTIPLIER) + REQUEST_TIME; } /** diff --git a/core/modules/system/src/Tests/Cache/DatabaseBackendUnitTest.php b/core/modules/system/src/Tests/Cache/DatabaseBackendUnitTest.php index 89812a3..e3aff07 100644 --- a/core/modules/system/src/Tests/Cache/DatabaseBackendUnitTest.php +++ b/core/modules/system/src/Tests/Cache/DatabaseBackendUnitTest.php @@ -52,7 +52,6 @@ public function testSetGet() { $cached_value_short = $this->randomMachineName(); $backend->set($cid_short, $cached_value_short); $this->assertIdentical($cached_value_short, $backend->get($cid_short)->data, "Backend contains the correct value for short, non-ASCII cache id."); - } /**