Consider defaulting requires_container_rebuild to FALSE

Created on 6 December 2024, 5 months ago

Problem/Motivation

Spin-off from πŸ“Œ Add the ability to install multiple modules and only do a single container rebuild to ModuleInstaller Active .

In that issue we are defaulting container_rebuild_required to FALSE if it's not set in a module's .info.yml to preserve bc with modules that modify the container in a way that affects the install of other modules.

However, given the memory leak we've discovered in attribute discovery, I think we should consider being more aggressive and defaulting it to TRUE when it's not set instead. This will dramatically reduce the memory requirements and time to install Drupal (Berdir tested with his install profile and it went down from 1.6gb to ~200mb). We would need to find as many of the affected modules proactively as we can and open issues against them.

Steps to reproduce

Proposed resolution

Remaining tasks

User interface changes

Introduced terminology

API changes

Data model changes

Release notes snippet

πŸ“Œ Task
Status

Active

Version

11.0 πŸ”₯

Component

extension system

Created by

πŸ‡¬πŸ‡§United Kingdom catch

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @catch
  • πŸ‡¬πŸ‡§United Kingdom longwave UK

    Wondering if we can do this in a safe way. If a module calls \Drupal::service() in hook_install() for a service provided by a just-installed dependency then we need to rebuild the container, but that's the problem of the second module - the container only needs to be rebuilt if both are installed at the same time.

    Do we know what other scenarios require a container rebuild?

  • πŸ‡¬πŸ‡§United Kingdom catch

    The example @alexpott gave was one of the config trickery modules in contrib which affects how config is installed, I don't think it's config_split but that general area. We could maybe look for the magic service provider class since that is consistently named, if that's a good indication of the problem.

    Drupal::service() calls in hook_install() is a different problem I had not even really thought of, but there is no way for modules to know that another module is going to do that, so container_rebuild_required won't help. However that also seems pretty fragile anyway. I guess we could try to detect when we've just installed a module that another module we're about to install depends on, and rebuild the container then?

  • πŸ‡¬πŸ‡§United Kingdom catch

    Found the reference #3416522-22: Add the ability to install multiple modules and only do a single container rebuild to ModuleInstaller β†’

    Thunder uses the config_selector module. That module decorates the config installer and changes the behaviour of installDefaultConfig().

  • πŸ‡¬πŸ‡§United Kingdom longwave UK

    For #4 I'm trying to think how we could automatically detect that but it's tricky because the decoration is done in a service provider class.

  • πŸ‡¬πŸ‡§United Kingdom catch

    https://git.drupalcode.org/project/config_selector/-/blob/8.x-2.x/src/Co... does exist, so

    This from DrupalKernel:

        // Load each module's serviceProvider class.
        foreach ($module_filenames as $module => $filename) {
          $camelized = ContainerBuilder::camelize($module);
          $name = "{$camelized}ServiceProvider";
          $class = "Drupal\\{$module}\\{$name}";
          if (class_exists($class)) {
            $this->serviceProviderClasses['app'][$module] = $class;
          }
    

    So a combination of checking dependencies and whether this class exists might reduce any potential disruption by a lot.

  • πŸ‡¬πŸ‡§United Kingdom longwave UK

    Building on #3, maybe we can just rely on dependencies? If we build a graph of dependencies then we can guarantee container rebuilds between two modules that depend on each other, but we can still combine the branches of the graph in a way that minimises the total number of rebuilds that is required.

    If this works then all that modules have to do is ensure their dependencies are correctly declared.

  • πŸ‡¬πŸ‡§United Kingdom catch

    #7 I think will be fine for the 'module calls a service of another service during installation'. If we put all the depended-upon modules at the start, that would be enough to minimise the number of container rebuilds.

    However it won't solve the problem of #6 where modules are impacting the installation process itself - so maybe we can do the dependencies here, and then split installer-modification out to its own issue, or just not fix that and open issues against modules like config_selector?

  • πŸ‡¬πŸ‡§United Kingdom longwave UK

    I haven't looked but I don't understand in the config_selector case how it ensures it is installed first when multiple modules are installed simultaneously, if it affects the install process itself.

  • πŸ‡¬πŸ‡§United Kingdom catch
  • Pipeline finished with Failed
    4 months ago
    Total: 668s
    #363298
  • Pipeline finished with Failed
    4 months ago
    Total: 384s
    #363356
  • πŸ‡¬πŸ‡§United Kingdom catch

    If we build a graph of dependencies then we can guarantee a container rebuild between a module and any dependency, but we can still combine the branches of the graph in a way that minimises the total number of rebuilds that is required.

    I started thinking about this but I think we might be fine without any special logic.

    The thing we need to guarantee that is after a module that is a dependency of a module we're also installing is installed, we do a container rebuild.

    We could potentially optimize things by grouping together modules that are dependencies of other modules, and then only rebuild the container after those are installed.

    However if we do that, we need to account for modules that depend on one module and are also depended upon by another module.

    We could handle that by just in time rebuilding the container when a module that specifies dependencies is installed, but we only need to do that if another module with the same dependency wasn't just installed - e.g. if two modules depend on views, we only need to container rebuild once.

    If we just find all the modules that are dependencies of other modules, rebuild the container after each one, then we still get a good distribution without anything extra on top.

    Let's say three modules that are dependencies and three that specify those as dependencies. xxx and yyy.

    If we do xxx yyy - that's four container rebuilds (3 + 1 at the end).

    If we do xy xy xy that's also four container rebuilds.

  • Pipeline finished with Failed
    4 months ago
    Total: 650s
    #363408
  • πŸ‡¬πŸ‡§United Kingdom longwave UK

    ModuleHandler::buildModuleDependencies() already builds a graph of dependencies so I was hoping we could use that.

    I think that we need install modules in the order of the longest possible route through the graph, which will ensure that all dependencies are met by the time each subsequent module gets to be installed.

  • Pipeline finished with Failed
    4 months ago
    Total: 426s
    #363459
  • πŸ‡ΊπŸ‡ΈUnited States mikelutz Michigan, USA

    Drupal::service() calls in hook_install() is a different problem I had not even really thought of, but there is no way for modules to know that another module is going to do that, so container_rebuild_required won't help. However that also seems pretty fragile anyway. I guess we could try to detect when we've just installed a module that another module we're about to install depends on, and rebuild the container then?

    Is this an issue though? From a brief reading of the issues and code it seems like we rebuild the container for the batch prior to running any of the install hooks for the batch anyway. We also rebuild the container before the config installer is used, so I'm not even sure that config_selector would be an issue, as we would be using the updated config installer for the batch containing config_selector too. Seems like what would be different would be on hook install you would have items in the container that wouldn't have been there previously, i.e. some service might be decorated from a module dependent on this module that wouldn't have otherwise been decorated when this module is being installed.

    So if module a depends on module b, and module a decorates some service, currently it knows that when module b is installed it is using the original service and not the decorated service. With this change it can't be sure of that, and the flag won't help. But I can't think of a scenario or example that would make that an issue? Possible though.

  • Merge request !10495Just switch the default. β†’ (Closed) created by catch
  • Pipeline finished with Canceled
    4 months ago
    Total: 83s
    #363514
  • Pipeline finished with Success
    4 months ago
    Total: 335s
    #363517
  • πŸ‡¬πŸ‡§United Kingdom catch

    I've put a simpler MR up at https://git.drupalcode.org/project/drupal/-/merge_requests/10495 which only changes the default and doesn't try to handle dependencies, because as @mikelutz points out, hook_install() looks to be already covered.

    Postponing on πŸ“Œ Some of the package manager kernel tests are much slower than other kernel tests - mark them #slow Active though since that will ensure that when a module specifies this manually, it really does get its own container rebuild.

  • πŸ‡¬πŸ‡§United Kingdom catch
  • πŸ‡ΊπŸ‡ΈUnited States mikelutz Michigan, USA

    I think you meant to postpone this on πŸ“Œ Install modules with container_rebuild_true set by themselves Active , no?

  • πŸ‡¬πŸ‡§United Kingdom catch

    Oops yes I did, edited the comment.

  • πŸ‡ΊπŸ‡ΈUnited States mikelutz Michigan, USA

    After all the discussions here, and in slack I think it really is this simple. I've updated the change record here β†’ . I really think the best thing is to get this into 11.2 now, as early as possible, just in case there are any unexpected patterns in contrib that this might negatively affect. This will give us as much time as possible to identify and adjust.

  • πŸ‡¬πŸ‡§United Kingdom longwave UK

    If the default is now false we can remove container_rebuild_required: false from all .info.yml files again.

  • πŸ‡¬πŸ‡§United Kingdom catch

    Removed.

  • πŸ‡ΊπŸ‡ΈUnited States mikelutz Michigan, USA

    +1 to back to RTBC

  • πŸ‡¬πŸ‡§United Kingdom longwave UK

    longwave β†’ changed the visibility of the branch 3492235-rebuild-required to hidden.

  • Pipeline finished with Success
    4 months ago
    Total: 6116s
    #364280
  • πŸ‡¬πŸ‡§United Kingdom longwave UK

    Committed 58be5f1 and pushed to 11.x. Thanks!

  • Automatically closed - issue fixed for 2 weeks with no activity.

Production build 0.71.5 2024