From c0b1ad48189bb6f02b3faff785e9b134805e8761 Mon Sep 17 00:00:00 2001
From: William Hearn <sylus1984@gmail.com>
Date: Mon, 16 Sep 2019 22:21:06 -0400
Subject: [PATCH] Issue #2488350 by alexpott, Wim Leers, Dimiter, catch,
 dawehner, Berdir: Switch to a memory cache backend during installation

---
 .../Installer/InstallerServiceProvider.php    | 18 +-------
 .../NormalInstallerServiceProvider.php        | 42 ++++++++++++++++---
 2 files changed, 39 insertions(+), 21 deletions(-)

diff --git a/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php b/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php
index e98aa3dcc8..cea42f49b2 100644
--- a/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php
+++ b/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php
@@ -14,7 +14,7 @@
  * $conf['container_service_providers'] and required to prevent various services
  * from trying to retrieve data from storages that do not exist yet.
  */
-class InstallerServiceProvider implements ServiceProviderInterface, ServiceModifierInterface {
+class InstallerServiceProvider extends NormalInstallerServiceProvider implements ServiceProviderInterface, ServiceModifierInterface {
 
   /**
    * {@inheritdoc}
@@ -26,18 +26,12 @@ public function register(ContainerBuilder $container) {
     $container->register('config.storage', 'Drupal\Core\Config\InstallStorage');
 
     // Replace services with in-memory implementations.
-    $definition = $container->getDefinition('cache_factory');
-    $definition->setClass('Drupal\Core\Cache\MemoryBackendFactory');
-    $definition->setArguments([]);
-    $definition->setMethodCalls([]);
     $container
       ->register('keyvalue', 'Drupal\Core\KeyValueStore\KeyValueMemoryFactory');
     $container
       ->register('keyvalue.expirable', 'Drupal\Core\KeyValueStore\KeyValueNullExpirableFactory');
 
     // Replace services with no-op implementations.
-    $container
-      ->register('lock', 'Drupal\Core\Lock\NullLockBackend');
     $container
       ->register('url_generator', 'Drupal\Core\Routing\NullGenerator')
       ->addArgument(new Reference('request_stack'));
@@ -46,12 +40,6 @@ public function register(ContainerBuilder $container) {
     $container
       ->register('router.dumper', 'Drupal\Core\Routing\NullMatcherDumper');
 
-    // Remove the cache tags invalidator tag from the cache tags storage, so
-    // that we don't call it when cache tags are invalidated very early in the
-    // installer.
-    $container->getDefinition('cache_tags.invalidator.checksum')
-      ->clearTag('cache_tags_invalidator');
-
     // Replace the route builder with an empty implementation.
     // @todo Convert installer steps into routes; add an installer.routing.yml.
     $definition = $container->getDefinition('router.builder');
@@ -60,9 +48,7 @@ public function register(ContainerBuilder $container) {
       // we don't need to ship with a custom proxy class.
       ->setLazy(FALSE);
 
-    // Use a performance optimised module extension list.
-    $container->getDefinition('extension.list.module')->setClass('Drupal\Core\Installer\InstallerModuleExtensionList');
-    $container->getDefinition('extension.list.profile')->setClass('Drupal\Core\Installer\InstallerProfileExtensionList');
+    parent::register($container);
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Installer/NormalInstallerServiceProvider.php b/core/lib/Drupal/Core/Installer/NormalInstallerServiceProvider.php
index 472d984b22..88f26f936f 100644
--- a/core/lib/Drupal/Core/Installer/NormalInstallerServiceProvider.php
+++ b/core/lib/Drupal/Core/Installer/NormalInstallerServiceProvider.php
@@ -2,11 +2,23 @@
 
 namespace Drupal\Core\Installer;
 
+use Drupal\Core\Cache\MemoryBackendFactory;
 use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Drupal\Core\DependencyInjection\ServiceProviderInterface;
+use Drupal\Core\Lock\NullLockBackend;
 
 /**
- * Service provider for the non early installer environment.
+ * Service provider for the installer environment.
+ *
+ * This class is manually added by install_begin_request() via
+ * $conf['container_service_providers'] and optimizes the container for
+ * installation.
+ *
+ * Note that the early installer environment requires the further customisations
+ * in InstallerServiceProvider.
+ *
+ * @see install_begin_request()
+ * @see \Drupal\Core\Installer\InstallerServiceProvider
  */
 class NormalInstallerServiceProvider implements ServiceProviderInterface {
 
@@ -14,10 +26,30 @@ class NormalInstallerServiceProvider implements ServiceProviderInterface {
    * {@inheritdoc}
    */
   public function register(ContainerBuilder $container) {
-    // Use a performance optimised module extension list.
-    $container->getDefinition('extension.list.module')->setClass('Drupal\Core\Installer\InstallerModuleExtensionList');
-    $container->getDefinition('extension.list.theme')->setClass('Drupal\Core\Installer\InstallerThemeExtensionList');
-    $container->getDefinition('extension.list.theme_engine')->setClass('Drupal\Core\Installer\InstallerThemeEngineExtensionList');
+    // Replace cache services with in-memory implementations. The results in
+    // less queries to set caches which will only be cleared on the next module
+    // install.
+    $definition = $container->getDefinition('cache_factory');
+    $definition->setClass(MemoryBackendFactory::class);
+    $definition->setArguments([]);
+    $definition->setMethodCalls([]);
+
+    // Replace lock service with no-op implementation as Drupal installation can
+    // only occur in a single thread and the site should not be publicly
+    // available.
+    $container
+      ->register('lock', NullLockBackend::class);
+
+    // Remove the cache tags invalidator tag from the cache tags storage, so
+    // that we don't call it when cache tags are invalidated in the installer.
+    $container->getDefinition('cache_tags.invalidator.checksum')
+      ->clearTag('cache_tags_invalidator');
+
+    // Use performance-optimized extension lists.
+    $container->getDefinition('extension.list.module')->setClass(InstallerModuleExtensionList::class);
+    $container->getDefinition('extension.list.profile')->setClass(InstallerProfileExtensionList::class);
+    $container->getDefinition('extension.list.theme')->setClass(InstallerThemeExtensionList::class);
+    $container->getDefinition('extension.list.theme_engine')->setClass(InstallerThemeEngineExtensionList::class);
   }
 
 }
-- 
2.20.1 (Apple Git-117)

