Issue #2205527 by cilefen, alexpott, martin107, Xen, Gaelan, clintrandall777@gmail.com: Fixed Move configuration import lock to lock.persistent service since a lock can not exist beyond a single request.
parent
cfd30d63e8
commit
6ba1da1c63
|
@ -450,6 +450,9 @@ services:
|
|||
arguments: ['@database']
|
||||
tags:
|
||||
- { name: backend_overridable }
|
||||
lock.persistent:
|
||||
class: Drupal\Core\Lock\PersistentDatabaseLockBackend
|
||||
arguments: ['@database']
|
||||
router.request_context:
|
||||
class: Drupal\Core\Routing\RequestContext
|
||||
tags:
|
||||
|
|
|
@ -44,7 +44,7 @@ class ConfigImporter {
|
|||
/**
|
||||
* The name used to identify the lock.
|
||||
*/
|
||||
const LOCK_ID = 'config_importer';
|
||||
const LOCK_NAME = 'config_importer';
|
||||
|
||||
/**
|
||||
* The storage comparer used to discover configuration changes.
|
||||
|
@ -512,9 +512,9 @@ class ConfigImporter {
|
|||
// Ensure that the changes have been validated.
|
||||
$this->validate();
|
||||
|
||||
if (!$this->lock->acquire(static::LOCK_ID)) {
|
||||
if (!$this->lock->acquire(static::LOCK_NAME)) {
|
||||
// Another process is synchronizing configuration.
|
||||
throw new ConfigImporterException(sprintf('%s is already importing', static::LOCK_ID));
|
||||
throw new ConfigImporterException(sprintf('%s is already importing', static::LOCK_NAME));
|
||||
}
|
||||
|
||||
$sync_steps = array();
|
||||
|
@ -611,7 +611,7 @@ class ConfigImporter {
|
|||
protected function finish(array &$context) {
|
||||
$this->eventDispatcher->dispatch(ConfigEvents::IMPORT, new ConfigImporterEvent($this));
|
||||
// The import is now complete.
|
||||
$this->lock->release(static::LOCK_ID);
|
||||
$this->lock->release(static::LOCK_NAME);
|
||||
$this->reset();
|
||||
$context['message'] = t('Finalizing configuration synchronization.');
|
||||
$context['finished'] = 1;
|
||||
|
@ -996,7 +996,7 @@ class ConfigImporter {
|
|||
* TRUE if an import is already running, FALSE if not.
|
||||
*/
|
||||
public function alreadyImporting() {
|
||||
return !$this->lock->lockMayBeAvailable(static::LOCK_ID);
|
||||
return !$this->lock->lockMayBeAvailable(static::LOCK_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1007,13 +1007,13 @@ class ConfigImporter {
|
|||
* keep the services used by the importer in sync.
|
||||
*/
|
||||
protected function reInjectMe() {
|
||||
$this->eventDispatcher = \Drupal::service('event_dispatcher');
|
||||
$this->configManager = \Drupal::service('config.manager');
|
||||
$this->lock = \Drupal::lock();
|
||||
$this->typedConfigManager = \Drupal::service('config.typed');
|
||||
$this->moduleHandler = \Drupal::moduleHandler();
|
||||
$this->themeHandler = \Drupal::service('theme_handler');
|
||||
$this->stringTranslation = \Drupal::service('string_translation');
|
||||
$this->_serviceIds = array();
|
||||
$vars = get_object_vars($this);
|
||||
foreach ($vars as $key => $value) {
|
||||
if (is_object($value) && isset($value->_serviceId)) {
|
||||
$this->$key = \Drupal::service($value->_serviceId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\Lock\PersistentDatabaseLockBackend.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\Lock;
|
||||
|
||||
use Drupal\Core\Database\Connection;
|
||||
|
||||
/**
|
||||
* Defines the persistent database lock backend. This backend is global for this
|
||||
* Drupal installation.
|
||||
*
|
||||
* @ingroup lock
|
||||
*/
|
||||
class PersistentDatabaseLockBackend extends DatabaseLockBackend {
|
||||
|
||||
/**
|
||||
* Constructs a new PersistentDatabaseLockBackend.
|
||||
*
|
||||
* @param \Drupal\Core\Database\Connection $database
|
||||
* The database connection.
|
||||
*/
|
||||
public function __construct(Connection $database) {
|
||||
// Do not call the parent constructor to avoid registering a shutdown
|
||||
// function that releases all the locks at the end of a request.
|
||||
$this->database = $database;
|
||||
// Set the lockId to a fixed string to make the lock ID the same across
|
||||
// multiple requests. The lock ID is used as a page token to relate all the
|
||||
// locks set during a request to each other.
|
||||
// @see \Drupal\Core\Lock\LockBackendInterface::getLockId()
|
||||
$this->lockId = 'persistent';
|
||||
}
|
||||
}
|
|
@ -134,7 +134,7 @@ class ConfigSync extends FormBase {
|
|||
$container->get('config.storage.staging'),
|
||||
$container->get('config.storage'),
|
||||
$container->get('config.storage.snapshot'),
|
||||
$container->get('lock'),
|
||||
$container->get('lock.persistent'),
|
||||
$container->get('event_dispatcher'),
|
||||
$container->get('config.manager'),
|
||||
$container->get('config.typed'),
|
||||
|
|
|
@ -55,7 +55,7 @@ class ConfigImportRenameValidationTest extends DrupalUnitTestBase {
|
|||
$storage_comparer->createChangelist(),
|
||||
$this->container->get('event_dispatcher'),
|
||||
$this->container->get('config.manager'),
|
||||
$this->container->get('lock'),
|
||||
$this->container->get('lock.persistent'),
|
||||
$this->container->get('config.typed'),
|
||||
$this->container->get('module_handler'),
|
||||
$this->container->get('theme_handler'),
|
||||
|
|
|
@ -228,14 +228,14 @@ class ConfigImportUITest extends WebTestBase {
|
|||
|
||||
// Acquire a fake-lock on the import mechanism.
|
||||
$config_importer = $this->configImporter();
|
||||
$this->container->get('lock')->acquire($config_importer::LOCK_ID);
|
||||
$this->container->get('lock.persistent')->acquire($config_importer::LOCK_NAME);
|
||||
|
||||
// Attempt to import configuration and verify that an error message appears.
|
||||
$this->drupalPostForm(NULL, array(), t('Import all'));
|
||||
$this->assertText(t('Another request may be synchronizing configuration already.'));
|
||||
|
||||
// Release the lock, just to keep testing sane.
|
||||
$this->container->get('lock')->release($config_importer::LOCK_ID);
|
||||
$this->container->get('lock.persistent')->release($config_importer::LOCK_NAME);
|
||||
|
||||
// Verify site name has not changed.
|
||||
$this->assertNotEqual($new_site_name, \Drupal::config('system.site')->get('name'));
|
||||
|
|
|
@ -527,4 +527,3 @@ class ConfigImporterTest extends DrupalUnitTestBase {
|
|||
$this->assertEqual(count($logs), 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -59,4 +59,29 @@ class LockFunctionalTest extends WebTestBase {
|
|||
$this->assertText($lock_acquired_exit, 'Lock acquired by the other request before exit.', 'Lock');
|
||||
$this->assertTrue($lock->acquire('system_test_lock_exit'), 'Lock acquired by this request after the other request exits.', 'Lock');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the persistent lock is persisted between requests.
|
||||
*/
|
||||
public function testPersistentLock() {
|
||||
$persistent_lock = $this->container->get('lock.persistent');
|
||||
// Get a persistent lock.
|
||||
$this->drupalGet('system-test/lock-persist/lock1');
|
||||
$this->assertText('TRUE: Lock successfully acquired in SystemTestController::lockPersist()');
|
||||
// Ensure that a shutdown function has not released the lock.
|
||||
$this->assertFalse($persistent_lock->lockMayBeAvailable('lock1'));
|
||||
$this->drupalGet('system-test/lock-persist/lock1');
|
||||
$this->assertText('FALSE: Lock not acquired in SystemTestController::lockPersist()');
|
||||
|
||||
// Get another persistent lock.
|
||||
$this->drupalGet('system-test/lock-persist/lock2');
|
||||
$this->assertText('TRUE: Lock successfully acquired in SystemTestController::lockPersist()');
|
||||
$this->assertFalse($persistent_lock->lockMayBeAvailable('lock2'));
|
||||
|
||||
// Release the first lock and try getting it again.
|
||||
$persistent_lock->release('lock1');
|
||||
$this->drupalGet('system-test/lock-persist/lock1');
|
||||
$this->assertText('TRUE: Lock successfully acquired in SystemTestController::lockPersist()');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -10,12 +10,38 @@ namespace Drupal\system_test\Controller;
|
|||
use Drupal\Core\Controller\ControllerBase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Drupal\Core\Lock\LockBackendInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Controller routines for system_test routes.
|
||||
*/
|
||||
class SystemTestController extends ControllerBase {
|
||||
|
||||
/**
|
||||
* The persistent lock service.
|
||||
*
|
||||
* @var \Drupal\Core\Lock\LockBackendInterface
|
||||
*/
|
||||
protected $persistentLock;
|
||||
|
||||
/**
|
||||
* Constructs the SystemTestController.
|
||||
*
|
||||
* @param \Drupal\Core\Lock\LockBackendInterface $persistent_lock
|
||||
* The persistent lock service.
|
||||
*/
|
||||
public function __construct(LockBackendInterface $persistent_lock) {
|
||||
$this->persistentLock = $persistent_lock;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static($container->get('lock.persistent'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests main content fallback.
|
||||
*
|
||||
|
@ -56,6 +82,24 @@ class SystemTestController extends ControllerBase {
|
|||
return system_test_lock_exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a lock that will persist across requests.
|
||||
*
|
||||
* @param string $lock_name
|
||||
* The name of the persistent lock to acquire.
|
||||
*
|
||||
* @return string
|
||||
* The text to display.
|
||||
*/
|
||||
public function lockPersist($lock_name) {
|
||||
if ($this->persistentLock->acquire($lock_name)) {
|
||||
return 'TRUE: Lock successfully acquired in SystemTestController::lockPersist()';
|
||||
}
|
||||
else {
|
||||
return 'FALSE: Lock not acquired in SystemTestController::lockPersist()';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set cache tag on on the returned render array.
|
||||
*/
|
||||
|
|
|
@ -53,6 +53,14 @@ system_test.lock_exit:
|
|||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
system_test.lock_persist:
|
||||
path: '/system-test/lock-persist/{lock_name}'
|
||||
defaults:
|
||||
_title: 'Persistent lock acquire'
|
||||
_content: '\Drupal\system_test\Controller\SystemTestController::lockPersist'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
system_test.cache_tags_page:
|
||||
path: '/system-test/cache_tags_page'
|
||||
defaults:
|
||||
|
|
Loading…
Reference in New Issue