Issue #2202537 by alexpott: Avoid repeated cache tag invalidations.
parent
78e5e9bfd9
commit
1747f674f9
|
@ -165,12 +165,17 @@ class DatabaseBackend implements CacheBackendInterface {
|
|||
protected function doSet($cid, $data, $expire, $tags) {
|
||||
$flat_tags = $this->flattenTags($tags);
|
||||
$deleted_tags = &drupal_static('Drupal\Core\Cache\DatabaseBackend::deletedTags', array());
|
||||
// Remove tags that were already deleted during this request from the static
|
||||
// cache so that another deletion for them will be correctly updated.
|
||||
$invalidated_tags = &drupal_static('Drupal\Core\Cache\DatabaseBackend::invalidatedTags', array());
|
||||
// Remove tags that were already deleted or invalidated during this request
|
||||
// from the static caches so that another deletion or invalidation can
|
||||
// occur.
|
||||
foreach ($flat_tags as $tag) {
|
||||
if (isset($deleted_tags[$tag])) {
|
||||
unset($deleted_tags[$tag]);
|
||||
}
|
||||
if (isset($invalidated_tags[$tag])) {
|
||||
unset($invalidated_tags[$tag]);
|
||||
}
|
||||
}
|
||||
$checksum = $this->checksumTags($flat_tags);
|
||||
$fields = array(
|
||||
|
@ -301,7 +306,13 @@ class DatabaseBackend implements CacheBackendInterface {
|
|||
public function invalidateTags(array $tags) {
|
||||
try {
|
||||
$tag_cache = &drupal_static('Drupal\Core\Cache\CacheBackendInterface::tagCache', array());
|
||||
$invalidated_tags = &drupal_static('Drupal\Core\Cache\DatabaseBackend::invalidatedTags', array());
|
||||
foreach ($this->flattenTags($tags) as $tag) {
|
||||
// Only invalidate tags once per request unless they are written again.
|
||||
if (isset($invalidated_tags[$tag])) {
|
||||
continue;
|
||||
}
|
||||
$invalidated_tags[$tag] = TRUE;
|
||||
unset($tag_cache[$tag]);
|
||||
$this->connection->merge('cache_tags')
|
||||
->insertFields(array('invalidations' => 1))
|
||||
|
|
|
@ -1055,6 +1055,7 @@ abstract class WebTestBase extends TestBase {
|
|||
// Clear the tag cache.
|
||||
drupal_static_reset('Drupal\Core\Cache\CacheBackendInterface::tagCache');
|
||||
drupal_static_reset('Drupal\Core\Cache\DatabaseBackend::deletedTags');
|
||||
drupal_static_reset('Drupal\Core\Cache\DatabaseBackend::invalidatedTags');
|
||||
|
||||
$this->container->get('config.factory')->reset();
|
||||
$this->container->get('state')->resetCache();
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\system\Tests\Cache\DatabaseBackendTagTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\system\Tests\Cache;
|
||||
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\simpletest\DrupalUnitTestBase;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
|
||||
/**
|
||||
* Tests DatabaseBackend cache tag implementation.
|
||||
*/
|
||||
class DatabaseBackendTagTest extends DrupalUnitTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('system');
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Database backend tag test',
|
||||
'description' => 'Tests database backend cache tag implementation.',
|
||||
'group' => 'Cache',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function containerBuild(ContainerBuilder $container) {
|
||||
parent::containerBuild($container);
|
||||
// Change container to database cache backends.
|
||||
$container
|
||||
->register('cache_factory', 'Drupal\Core\Cache\CacheFactory')
|
||||
->addArgument(new Reference('settings'))
|
||||
->addMethodCall('setContainer', array(new Reference('service_container')));
|
||||
}
|
||||
|
||||
public function testTagInvalidations() {
|
||||
// Create cache entry in multiple bins.
|
||||
$tags = array('test_tag' => array(1, 2, 3));
|
||||
$bins = array('path', 'bootstrap', 'page');
|
||||
foreach ($bins as $bin) {
|
||||
$bin = \Drupal::cache($bin);
|
||||
$bin->set('test', 'value', Cache::PERMANENT, $tags);
|
||||
$this->assertTrue($bin->get('test'), 'Cache item was set in bin.');
|
||||
}
|
||||
|
||||
$invalidations_before = intval(db_select('cache_tags')->fields('cache_tags', array('invalidations'))->condition('tag', 'test_tag:2')->execute()->fetchField());
|
||||
Cache::invalidateTags(array('test_tag' => array(2)));
|
||||
|
||||
// Test that cache entry has been invalidated in multiple bins.
|
||||
foreach ($bins as $bin) {
|
||||
$bin = \Drupal::cache($bin);
|
||||
$this->assertFalse($bin->get('test'), 'Tag invalidation affected item in bin.');
|
||||
}
|
||||
|
||||
// Test that only one tag invalidation has occurred.
|
||||
$invalidations_after = intval(db_select('cache_tags')->fields('cache_tags', array('invalidations'))->condition('tag', 'test_tag:2')->execute()->fetchField());
|
||||
$this->assertEqual($invalidations_after, $invalidations_before + 1, 'Only one addition cache tag invalidation has occurred after invalidating a tag used in multiple bins.');
|
||||
}
|
||||
|
||||
public function testTagDeletetions() {
|
||||
// Create cache entry in multiple bins.
|
||||
$tags = array('test_tag' => array(1, 2, 3));
|
||||
$bins = array('path', 'bootstrap', 'page');
|
||||
foreach ($bins as $bin) {
|
||||
$bin = \Drupal::cache($bin);
|
||||
$bin->set('test', 'value', Cache::PERMANENT, $tags);
|
||||
$this->assertTrue($bin->get('test'), 'Cache item was set in bin.');
|
||||
}
|
||||
|
||||
$deletions_before = intval(db_select('cache_tags')->fields('cache_tags', array('deletions'))->condition('tag', 'test_tag:2')->execute()->fetchField());
|
||||
Cache::deleteTags(array('test_tag' => array(2)));
|
||||
|
||||
// Test that cache entry has been deleted in multiple bins.
|
||||
foreach ($bins as $bin) {
|
||||
$bin = \Drupal::cache($bin);
|
||||
$this->assertFalse($bin->get('test'), 'Tag invalidation affected item in bin.');
|
||||
}
|
||||
|
||||
// Test that only one tag deletion has occurred.
|
||||
$deletions_after = intval(db_select('cache_tags')->fields('cache_tags', array('deletions'))->condition('tag', 'test_tag:2')->execute()->fetchField());
|
||||
$this->assertEqual($deletions_after, $deletions_before + 1, 'Only one addition cache tag deletion has occurred after deleting a tag used in multiple bins.');
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue