diff --git a/core/core.services.yml b/core/core.services.yml index 5e63508..3208606 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] + arguments: [default, ['override_permanent_ttl', 86400]] cache.entity: class: Drupal\Core\Cache\CacheBackendInterface tags: - { name: cache.bin } factory: cache_factory:get - arguments: [entity] + arguments: [entity, ['override_permanent_ttl', 86400]] cache.menu: class: Drupal\Core\Cache\CacheBackendInterface tags: - { name: cache.bin } factory: cache_factory:get - arguments: [menu] + arguments: [menu, ['override_permanent_ttl', 86400]] cache.render: class: Drupal\Core\Cache\CacheBackendInterface tags: - { name: cache.bin } factory: cache_factory:get - arguments: [render] + arguments: [render, ['override_permanent_ttl', 86400]] cache.data: class: Drupal\Core\Cache\CacheBackendInterface tags: - { name: cache.bin } factory: cache_factory:get - arguments: [data] + arguments: [data, ['override_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 ca38ca0..06d642b 100644 --- a/core/lib/Drupal/Core/Cache/ChainedFastBackendFactory.php +++ b/core/lib/Drupal/Core/Cache/ChainedFastBackendFactory.php @@ -12,7 +12,7 @@ /** * Defines the chained fast cache backend factory. */ -class ChainedFastBackendFactory implements CacheFactoryInterface { +class ChainedFastBackendFactory implements ConfigurableCacheFactoryInterface { use ContainerAwareTrait; @@ -68,26 +68,34 @@ public function __construct(Settings $settings = NULL, $consistent_service_name } /** - * Instantiates a chained, fast cache backend class for a given cache bin. - * - * @param string $bin - * The cache bin for which a cache backend object should be returned. - * - * @return \Drupal\Core\Cache\CacheBackendInterface - * The cache backend object associated with the specified bin. + * {@inheritdoc} */ - public function get($bin) { + 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( - $this->container->get($this->consistentServiceName)->get($bin), - $this->container->get($this->fastServiceName)->get($bin), + $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/ConfigurableCacheFactoryInterface.php b/core/lib/Drupal/Core/Cache/ConfigurableCacheFactoryInterface.php new file mode 100644 index 0000000..e9b07a4 --- /dev/null +++ b/core/lib/Drupal/Core/Cache/ConfigurableCacheFactoryInterface.php @@ -0,0 +1,23 @@ + $item) { + if (!isset($item['expire']) || $item['expire'] === CacheBackendInterface::CACHE_PERMANENT) { + if ($this->overridePermanentTtl === CacheBackendInterface::CACHE_PERMANENT) { + $item['expire'] = CacheBackendInterface::CACHE_PERMANENT; + } + else { + $item['expire'] = $this->calculatePermanentExpire(); + } + } $item += array( - 'expire' => CacheBackendInterface::CACHE_PERMANENT, 'tags' => array(), ); @@ -240,6 +259,16 @@ protected function doSetMultiple(array $items) { } /** + * Calculate permanent expiry. + * + * @return an expires timestamp based on the override TTL with added 'jitter'. + */ + protected function calculatePermanentExpire() { + $minimum = $this->overridePermanentTtl; + return rand($minimum, $minimum * self::JITTER_MULTIPLIER) + REQUEST_TIME; + } + + /** * {@inheritdoc} */ public function delete($cid) { @@ -356,6 +385,13 @@ public function removeBin() { } /** + * {@inheritdoc} + */ + public function setOverridePermanentTtl($ttl) { + $this->overridePermanentTtl = $ttl; + } + + /** * Check if the cache bin exists and create it if not. */ protected function ensureBinExists() { diff --git a/core/lib/Drupal/Core/Cache/DatabaseBackendFactory.php b/core/lib/Drupal/Core/Cache/DatabaseBackendFactory.php index 59b0b22..05459b2 100644 --- a/core/lib/Drupal/Core/Cache/DatabaseBackendFactory.php +++ b/core/lib/Drupal/Core/Cache/DatabaseBackendFactory.php @@ -9,7 +9,7 @@ use Drupal\Core\Database\Connection; -class DatabaseBackendFactory implements CacheFactoryInterface { +class DatabaseBackendFactory implements ConfigurableCacheFactoryInterface { /** * The database connection. @@ -39,16 +39,14 @@ function __construct(Connection $connection, CacheTagsChecksumInterface $checksu } /** - * Gets DatabaseBackend for the specified cache bin. - * - * @param $bin - * The cache bin for which the object is created. - * - * @return \Drupal\Core\Cache\DatabaseBackend - * The cache backend object for the specified cache bin. + * {@inheritdoc} */ - function get($bin) { - return new DatabaseBackend($this->connection, $this->checksumProvider, $bin); + function get($bin, array $options = []) { + $class = new DatabaseBackend($this->connection, $this->checksumProvider, $bin); + if (isset($options['override_permanent_ttl'])) { + $class->setOverridePermanentTtl($options['override_permanent_ttl']); + } + return $class; } } diff --git a/core/modules/system/src/Tests/Cache/DatabaseBackendUnitTest.php b/core/modules/system/src/Tests/Cache/DatabaseBackendUnitTest.php index 934fe81..63a6f8f 100644 --- a/core/modules/system/src/Tests/Cache/DatabaseBackendUnitTest.php +++ b/core/modules/system/src/Tests/Cache/DatabaseBackendUnitTest.php @@ -7,6 +7,7 @@ namespace Drupal\system\Tests\Cache; +use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Cache\DatabaseBackend; /** @@ -53,4 +54,18 @@ public function testSetGet() { $this->assertIdentical($cached_value_short, $backend->get($cid_short)->data, "Backend contains the correct value for short, non-ASCII cache id."); } + /** + * Test overridePermanentTtl. + */ + function testOverridePermanentTtl() { + $backend = $this->getCacheBackend(); + $backend->setOverridePermanentTtl(2); + $cid = 'test'; + $value = 'test'; + $backend->set($cid, $value); + $item = $backend->get($cid); + $this->assertTrue($item->expire !== CacheBackendInterface::CACHE_PERMANENT); + $this->assertTrue($item->expire <= REQUEST_TIME + 2 * 1.5); + } + }