Issue #2493665 by Fabianx, dawehner, msonnabaum, catch: Add centralized container invalidation method
parent
c78d806eb3
commit
5a528e59df
|
@ -1295,8 +1295,10 @@ function drupal_flush_all_caches() {
|
|||
// Reset all static caches.
|
||||
drupal_static_reset();
|
||||
|
||||
// Wipe the PHP Storage caches.
|
||||
PhpStorageFactory::get('service_container')->deleteAll();
|
||||
// Invalidate the container.
|
||||
\Drupal::service('kernel')->invalidateContainer();
|
||||
|
||||
// Wipe the Twig PHP Storage cache.
|
||||
PhpStorageFactory::get('twig')->deleteAll();
|
||||
|
||||
// Rebuild module and theme data.
|
||||
|
|
|
@ -29,13 +29,17 @@ function drupal_rebuild(ClassLoader $class_loader, Request $request) {
|
|||
restore_error_handler();
|
||||
restore_exception_handler();
|
||||
|
||||
// Force kernel to rebuild container.
|
||||
PhpStorageFactory::get('service_container')->deleteAll();
|
||||
// Force kernel to rebuild php cache.
|
||||
PhpStorageFactory::get('twig')->deleteAll();
|
||||
|
||||
// Bootstrap up to where caches exist and clear them.
|
||||
$kernel = new DrupalKernel('prod', $class_loader);
|
||||
$kernel->setSitePath(DrupalKernel::findSitePath($request));
|
||||
|
||||
// Invalidate the container.
|
||||
$kernel->invalidateContainer();
|
||||
|
||||
// Prepare a NULL request.
|
||||
$kernel->prepareLegacyRequest($request);
|
||||
|
||||
foreach (Cache::getBins() as $bin) {
|
||||
|
|
|
@ -126,6 +126,13 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface {
|
|||
*/
|
||||
protected $allowDumping;
|
||||
|
||||
/**
|
||||
* Whether the container needs to be rebuilt the next time it is initialized.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $containerNeedsRebuild = FALSE;
|
||||
|
||||
/**
|
||||
* Whether the container needs to be dumped once booting is complete.
|
||||
*
|
||||
|
@ -695,11 +702,13 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface {
|
|||
}
|
||||
|
||||
// If we haven't yet booted, we don't need to do anything: the new module
|
||||
// list will take effect when boot() is called. If we have already booted,
|
||||
// then rebuild the container in order to refresh the serviceProvider list
|
||||
// and container.
|
||||
// list will take effect when boot() is called. However we set a
|
||||
// flag that the container needs a rebuild, so that a potentially cached
|
||||
// container is not used. If we have already booted, then rebuild the
|
||||
// container in order to refresh the serviceProvider list and container.
|
||||
$this->containerNeedsRebuild = TRUE;
|
||||
if ($this->booted) {
|
||||
$this->initializeContainer(TRUE);
|
||||
$this->initializeContainer();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -738,11 +747,9 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface {
|
|||
/**
|
||||
* Initializes the service container.
|
||||
*
|
||||
* @param bool $rebuild
|
||||
* Force a container rebuild.
|
||||
* @return \Symfony\Component\DependencyInjection\ContainerInterface
|
||||
*/
|
||||
protected function initializeContainer($rebuild = FALSE) {
|
||||
protected function initializeContainer() {
|
||||
$this->containerNeedsDumping = FALSE;
|
||||
$session_started = FALSE;
|
||||
if (isset($this->container)) {
|
||||
|
@ -764,7 +771,7 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface {
|
|||
|
||||
// If the module list hasn't already been set in updateModules and we are
|
||||
// not forcing a rebuild, then try and load the container from the disk.
|
||||
if (empty($this->moduleList) && !$rebuild) {
|
||||
if (empty($this->moduleList) && !$this->containerNeedsRebuild) {
|
||||
$fully_qualified_class_name = '\\' . $this->getClassNamespace() . '\\' . $this->getClassName();
|
||||
|
||||
// First, try to load from storage.
|
||||
|
@ -781,6 +788,9 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface {
|
|||
$container = $this->compileContainer();
|
||||
}
|
||||
|
||||
// The container was rebuilt successfully.
|
||||
$this->containerNeedsRebuild = FALSE;
|
||||
|
||||
$this->attachSynthetic($container);
|
||||
|
||||
$this->container = $container;
|
||||
|
@ -998,15 +1008,33 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface {
|
|||
}
|
||||
|
||||
/**
|
||||
* Force a container rebuild.
|
||||
*
|
||||
* @return \Symfony\Component\DependencyInjection\ContainerInterface
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function rebuildContainer() {
|
||||
// Empty module properties and for them to be reloaded from scratch.
|
||||
$this->moduleList = NULL;
|
||||
$this->moduleData = array();
|
||||
return $this->initializeContainer(TRUE);
|
||||
$this->containerNeedsRebuild = TRUE;
|
||||
return $this->initializeContainer();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function invalidateContainer() {
|
||||
// An invalidated container needs a rebuild.
|
||||
$this->containerNeedsRebuild = TRUE;
|
||||
|
||||
// If we have not yet booted, settings or bootstrap services might not yet
|
||||
// be available. In that case the container will not be loaded from cache
|
||||
// due to the above setting when the Kernel is booted.
|
||||
if (!$this->booted) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Also wipe the PHP Storage caches, so that the container is rebuilt
|
||||
// for the next request.
|
||||
$this->storage()->deleteAll();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -96,6 +96,18 @@ interface DrupalKernelInterface extends HttpKernelInterface {
|
|||
*/
|
||||
public function updateModules(array $module_list, array $module_filenames = array());
|
||||
|
||||
/**
|
||||
* Force a container rebuild.
|
||||
*
|
||||
* @return \Symfony\Component\DependencyInjection\ContainerInterface
|
||||
*/
|
||||
public function rebuildContainer();
|
||||
|
||||
/**
|
||||
* Invalidate the service container for the next request.
|
||||
*/
|
||||
public function invalidateContainer();
|
||||
|
||||
/**
|
||||
* Prepare the kernel for handling a request without handling the request.
|
||||
*
|
||||
|
|
|
@ -16,13 +16,11 @@ class InstallerKernel extends DrupalKernel {
|
|||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @param bool $rebuild
|
||||
* Force a container rebuild. Unlike the parent method, this defaults to
|
||||
* TRUE.
|
||||
*/
|
||||
protected function initializeContainer($rebuild = TRUE) {
|
||||
$container = parent::initializeContainer($rebuild);
|
||||
protected function initializeContainer() {
|
||||
// Always force a container rebuild.
|
||||
$this->containerNeedsRebuild = TRUE;
|
||||
$container = parent::initializeContainer();
|
||||
return $container;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
namespace Drupal\language;
|
||||
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\Core\PhpStorage\PhpStorageFactory;
|
||||
use Drupal\Core\Config\ConfigFactoryInterface;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\Core\Language\Language;
|
||||
|
@ -105,7 +104,7 @@ class ConfigurableLanguageManager extends LanguageManager implements Configurabl
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public static function rebuildServices() {
|
||||
PhpStorageFactory::get('service_container')->deleteAll();
|
||||
\Drupal::service('kernel')->invalidateContainer();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -9,9 +9,9 @@ namespace Drupal\language\EventSubscriber;
|
|||
|
||||
use Drupal\Core\Language\LanguageDefault;
|
||||
use Drupal\Core\Language\LanguageManagerInterface;
|
||||
use Drupal\Core\PhpStorage\PhpStorageFactory;
|
||||
use Drupal\Core\Config\ConfigCrudEvent;
|
||||
use Drupal\Core\Config\ConfigEvents;
|
||||
use Drupal\language\ConfigurableLanguageManager;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
/**
|
||||
|
@ -62,9 +62,8 @@ class ConfigSubscriber implements EventSubscriberInterface {
|
|||
$this->languageManager->reset();
|
||||
language_negotiation_url_prefixes_update();
|
||||
}
|
||||
// Trigger a container rebuild on the next request by deleting compiled
|
||||
// from PHP storage.
|
||||
PhpStorageFactory::get('service_container')->deleteAll();
|
||||
// Trigger a container rebuild on the next request by invalidating it.
|
||||
ConfigurableLanguageManager::rebuildServices();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -35,4 +35,26 @@ class ContainerRebuildWebTest extends WebTestBase {
|
|||
$this->assertHeader('container_rebuild_indicator', 'new-identifier');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests container invalidation.
|
||||
*/
|
||||
public function testContainerInvalidation() {
|
||||
|
||||
// Ensure that parameter is not set.
|
||||
$this->drupalGet('<front>');
|
||||
$this->assertHeader('container_rebuild_test_parameter', FALSE);
|
||||
|
||||
// Ensure that after setting the parameter, without a container rebuild the
|
||||
// parameter is still not set.
|
||||
$this->writeSettings(['settings' => ['container_rebuild_test_parameter' => (object) ['value' => 'rebuild_me_please', 'required' => TRUE]]]);
|
||||
|
||||
$this->drupalGet('<front>');
|
||||
$this->assertHeader('container_rebuild_test_parameter', FALSE);
|
||||
|
||||
// Ensure that after container invalidation the parameter is set.
|
||||
\Drupal::service('kernel')->invalidateContainer();
|
||||
$this->drupalGet('<front>');
|
||||
$this->assertHeader('container_rebuild_test_parameter', 'rebuild_me_please');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -26,5 +26,9 @@ class ServiceProviderTestServiceProvider implements ServiceModifierInterface {
|
|||
if ($indicator = Settings::get('deployment_identifier')) {
|
||||
$container->setParameter('container_rebuild_indicator', $indicator);
|
||||
}
|
||||
|
||||
if ($parameter = Settings::get('container_rebuild_test_parameter')) {
|
||||
$container->setParameter('container_rebuild_test_parameter', $parameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,6 +51,9 @@ class TestClass implements EventSubscriberInterface, DestructableInterface, Cont
|
|||
if ($this->container->hasParameter('container_rebuild_indicator')) {
|
||||
$event->getResponse()->headers->set('container_rebuild_indicator', $this->container->getParameter('container_rebuild_indicator'));
|
||||
}
|
||||
if ($this->container->hasParameter('container_rebuild_test_parameter')) {
|
||||
$event->getResponse()->headers->set('container_rebuild_test_parameter', $this->container->getParameter('container_rebuild_test_parameter'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue