Issue #3055443 by alexpott, amateescu, catch, chr.fritsch, Berdir, oknate, Wim Leers: Switch to a null backend for all caches for running the database updates
parent
5448b07b67
commit
80a307dc69
|
|
@ -0,0 +1,54 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Drupal\Core\Update;
|
||||||
|
|
||||||
|
use Drupal\Core\Cache\CacheBackendInterface;
|
||||||
|
use Drupal\Core\Cache\NullBackend;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines a cache backend for use during Drupal database updates.
|
||||||
|
*
|
||||||
|
* Passes on deletes to another backend while extending the NullBackend to avoid
|
||||||
|
* using anything cached prior to running updates.
|
||||||
|
*/
|
||||||
|
class UpdateBackend extends NullBackend {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The regular runtime cache backend.
|
||||||
|
*
|
||||||
|
* @var \Drupal\Core\Cache\CacheBackendInterface
|
||||||
|
*/
|
||||||
|
protected $backend;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UpdateBackend constructor.
|
||||||
|
*
|
||||||
|
* @param \Drupal\Core\Cache\CacheBackendInterface $backend
|
||||||
|
* The regular runtime cache backend.
|
||||||
|
*/
|
||||||
|
public function __construct(CacheBackendInterface $backend) {
|
||||||
|
$this->backend = $backend;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function delete($cid) {
|
||||||
|
$this->backend->delete($cid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function deleteMultiple(array $cids) {
|
||||||
|
$this->backend->deleteMultiple($cids);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function deleteAll() {
|
||||||
|
$this->backend->deleteAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Drupal\Core\Update;
|
||||||
|
|
||||||
|
use Drupal\Core\Cache\CacheFactoryInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache factory implementation for use during Drupal database updates.
|
||||||
|
*
|
||||||
|
* Decorates the regular runtime cache_factory service so that caches use
|
||||||
|
* \Drupal\Core\Update\UpdateBackend.
|
||||||
|
*
|
||||||
|
* @see \Drupal\Core\Update\UpdateServiceProvider::register()
|
||||||
|
*/
|
||||||
|
class UpdateCacheBackendFactory implements CacheFactoryInterface {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The regular runtime cache_factory service.
|
||||||
|
*
|
||||||
|
* @var \Drupal\Core\Cache\CacheFactoryInterface
|
||||||
|
*/
|
||||||
|
protected $cacheFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiated update cache bins.
|
||||||
|
*
|
||||||
|
* @var \Drupal\Core\Update\UpdateBackend[]
|
||||||
|
*/
|
||||||
|
protected $bins = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UpdateCacheBackendFactory constructor.
|
||||||
|
*
|
||||||
|
* @param \Drupal\Core\Cache\CacheFactoryInterface $cache_factory
|
||||||
|
* The regular runtime cache_factory service.
|
||||||
|
*/
|
||||||
|
public function __construct(CacheFactoryInterface $cache_factory) {
|
||||||
|
$this->cacheFactory = $cache_factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function get($bin) {
|
||||||
|
if (!isset($this->bins[$bin])) {
|
||||||
|
$this->bins[$bin] = new UpdateBackend($this->cacheFactory->get($bin), $bin);
|
||||||
|
}
|
||||||
|
return $this->bins[$bin];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -19,8 +19,16 @@ class UpdateServiceProvider implements ServiceProviderInterface, ServiceModifier
|
||||||
*/
|
*/
|
||||||
public function register(ContainerBuilder $container) {
|
public function register(ContainerBuilder $container) {
|
||||||
$definition = new Definition('Drupal\Core\Cache\NullBackend', ['null']);
|
$definition = new Definition('Drupal\Core\Cache\NullBackend', ['null']);
|
||||||
|
$definition->setDeprecated(TRUE, 'The "%service_id%\" service is deprecated. While updating Drupal all caches use \Drupal\Core\Update\UpdateBackend. See https://www.drupal.org/node/3066407');
|
||||||
$container->setDefinition('cache.null', $definition);
|
$container->setDefinition('cache.null', $definition);
|
||||||
|
|
||||||
|
// Decorate the cache factory in order to use
|
||||||
|
// \Drupal\Core\Update\UpdateBackend while running updates.
|
||||||
|
$container
|
||||||
|
->register('update.cache_factory', UpdateCacheBackendFactory::class)
|
||||||
|
->setDecoratedService('cache_factory')
|
||||||
|
->addArgument(new Reference('update.cache_factory.inner'));
|
||||||
|
|
||||||
$container->addCompilerPass(new UpdateCompilerPass(), PassConfig::TYPE_REMOVE, 128);
|
$container->addCompilerPass(new UpdateCompilerPass(), PassConfig::TYPE_REMOVE, 128);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -28,25 +36,6 @@ class UpdateServiceProvider implements ServiceProviderInterface, ServiceModifier
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
public function alter(ContainerBuilder $container) {
|
public function alter(ContainerBuilder $container) {
|
||||||
// Ensures for some services that they don't cache.
|
|
||||||
$null_cache_service = new Reference('cache.null');
|
|
||||||
|
|
||||||
$definition = $container->getDefinition('asset.resolver');
|
|
||||||
$definition->replaceArgument(5, $null_cache_service);
|
|
||||||
|
|
||||||
$definition = $container->getDefinition('library.discovery.collector');
|
|
||||||
$definition->replaceArgument(0, $null_cache_service);
|
|
||||||
|
|
||||||
$definition = $container->getDefinition('theme.registry');
|
|
||||||
$definition->replaceArgument(1, $null_cache_service);
|
|
||||||
$definition->replaceArgument(7, $null_cache_service);
|
|
||||||
|
|
||||||
$definition = $container->getDefinition('theme.initialization');
|
|
||||||
$definition->replaceArgument(2, $null_cache_service);
|
|
||||||
|
|
||||||
$definition = $container->getDefinition('plugin.manager.element_info');
|
|
||||||
$definition->replaceArgument(1, $null_cache_service);
|
|
||||||
|
|
||||||
// Prevent the alias-based path processor, which requires a path_alias db
|
// Prevent the alias-based path processor, which requires a path_alias db
|
||||||
// table, from being registered to the path processor manager. We do this by
|
// table, from being registered to the path processor manager. We do this by
|
||||||
// removing the tags that the compiler pass looks for. This means the url
|
// removing the tags that the compiler pass looks for. This means the url
|
||||||
|
|
|
||||||
|
|
@ -1859,20 +1859,20 @@ function system_update_8011() {
|
||||||
* Enable automated cron module and move the config into it.
|
* Enable automated cron module and move the config into it.
|
||||||
*/
|
*/
|
||||||
function system_update_8013() {
|
function system_update_8013() {
|
||||||
$config_factory = \Drupal::configFactory();
|
$autorun = \Drupal::configFactory()->getEditable('system.cron')->get('threshold.autorun');
|
||||||
$system_cron_config = $config_factory->getEditable('system.cron');
|
if ($autorun) {
|
||||||
if ($autorun = $system_cron_config->get('threshold.autorun')) {
|
|
||||||
// Install 'automated_cron' module.
|
// Install 'automated_cron' module.
|
||||||
\Drupal::service('module_installer')->install(['automated_cron'], FALSE);
|
\Drupal::service('module_installer')->install(['automated_cron'], FALSE);
|
||||||
|
|
||||||
// Copy 'autorun' value into the new module's 'interval' setting.
|
// Copy 'autorun' value into the new module's 'interval' setting.
|
||||||
$config_factory->getEditable('automated_cron.settings')
|
\Drupal::configFactory()->getEditable('automated_cron.settings')
|
||||||
->set('interval', $autorun)
|
->set('interval', $autorun)
|
||||||
->save(TRUE);
|
->save(TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the 'autorun' key in system module config.
|
// Remove the 'autorun' key in system module config.
|
||||||
$system_cron_config
|
\Drupal::configFactory()
|
||||||
|
->getEditable('system.cron')
|
||||||
->clear('threshold.autorun')
|
->clear('threshold.autorun')
|
||||||
->save(TRUE);
|
->save(TRUE);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Drupal\Tests\system\Functional\Update;
|
||||||
|
|
||||||
|
use Drupal\Core\Url;
|
||||||
|
use Drupal\Tests\BrowserTestBase;
|
||||||
|
use Drupal\Tests\RequirementsPageTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests caches during updates.
|
||||||
|
*
|
||||||
|
* @group Update
|
||||||
|
*/
|
||||||
|
class UpdateCacheTest extends BrowserTestBase {
|
||||||
|
use RequirementsPageTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that caches are cleared during updates.
|
||||||
|
*
|
||||||
|
* @see \Drupal\Core\Update\UpdateServiceProvider
|
||||||
|
* @see \Drupal\Core\Update\UpdateBackend
|
||||||
|
*/
|
||||||
|
public function testCaches() {
|
||||||
|
\Drupal::cache()->set('will_not_exist_after_update', TRUE);
|
||||||
|
// The site might be broken at the time so logging in using the UI might
|
||||||
|
// not work, so we use the API itself.
|
||||||
|
$this->writeSettings([
|
||||||
|
'settings' => [
|
||||||
|
'update_free_access' => (object) [
|
||||||
|
'value' => TRUE,
|
||||||
|
'required' => TRUE,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Clicking continue should clear the caches.
|
||||||
|
$this->drupalGet(Url::fromRoute('system.db_update', [], ['path_processing' => FALSE]));
|
||||||
|
$this->updateRequirementsProblem();
|
||||||
|
$this->clickLink(t('Continue'));
|
||||||
|
|
||||||
|
$this->assertFalse(\Drupal::cache()->get('will_not_exist_after_update', FALSE));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue