Problem/Motivation
Prior to Drupal 11.2, when we install multiple modules at once, each of them would go through the regular steps of hook_install() and config install, before the next module is installed.
This means that, if module B depends on module A, then in B_install() it can pick up and alter configuration that module B introduced in B/config/optional.
Since Drupal 11.2., this is no longer the case.
If A and B are installed in bulk, then B_install() will fire _before_ the config from A/config/optional is present.
If A and B are installed one after the other, then B_install() will fire _after_ the config from A/config/optional is present.
This seems to be coming from #3496558: Install entity definitions for all modules in batch install before simple config.
Likewise, services from A won't be available in B_install(), if the container was not rebuilt.
This can be mitigated by setting 'container_rebuild_required' on one of the two modules.
But do we really want this, only to make hook_install() work?
Steps to reproduce
- Create module A with config/optional/views.view.a.yml
- Create module B with B_install() which loads 'views.view.a' and adds some fields to it.
- Let B depend on A (not sure if this is needed to reproduce this).
- Install both modules together.
- Uninstall both, then install A separately, then install B separately.
Expected: In both cases, the changes from B_install() are applied.
Actual: When both modules are installed together, then changes from B_install() are not applied (or B_install() crashes if it does not have defensive code).
Proposed resolution
We could detect if modules have a hook_install(), and if so, put them in separate groups.
Perhaps we could create "subgroups" where we don't do a full container rebuild in between.
Comments
Comment #2
donquixote commentedComment #3
donquixote commentedHere is a list of commits for ModuleInstaller since 11.1.8.
Comment #4
nicxvan commentedComment #5
nicxvan commentedI'm wondering if it's worth considering a new hook: hook_post_install_optional
https://git.drupalcode.org/project/drupal/-/blob/11.x/core/lib/Drupal/Co...
I think this type of config was never really meant to be handled in hook install but worked.
I think adding a new hook might give a place to interact with this config safely.
Comment #6
donquixote commentedI don't think the creators of this hook had any preference whether or not people use it to alter configuration from config/optional from another module.
To me it seems like a clear regression.
We should fix core, rather than asking people to change their code.
Comment #7
donquixote commentedI noticed that "container_rebuild_required" does not really help with config dependencies, because the following code happens before modules are grouped based on 'container_rebuild_required':
Comment #8
donquixote commentedI found that:
There is also hook_module_preinstall() and hook_modules_installed().
And then there could be funny side effects if e.g. plugin derivers depend on configuration.
Because $config_installer->checkConfigurationToInstall('module', $module); is called for all modules in the initial list, not only for those in the group.
Therefore what I proposed cannot be a sufficient solution.
My original idea was to auto-detect which module needs to be in a separate group. But that might just not be viable, we might have to stick with that "container_rebuild_required", and tweak the order of operations in ModuleInstaller.
Comment #9
nicxvan commentedComment #10
nicxvan commentedSo do we need to call: $config_installer->checkConfigurationToInstall('module', $module_list); per group?
And move it later, and still rely on the module maintainers to tag their modules appropriately?
Comment #11
codebymikey commentedAs per point 2 of @smulvih2's #3529670-16: Config dependency difference between Drupal 11.1 and 11.2 write-up, it seems like this change in behaviour needs to be appropriately documented in a change record (if its an intentional breaking change), or fixed, as it affects existing distributions and features modules.
Within the modules making use of optional configs, a backwards compatible workaround is to move the config-dependant logic from within
hook_install()tohook_modules_installed()instead.An example module affected by this is forum module where the
forumsvocabulary might not be available before it's saved.Comment #12
ghost of drupal pastTo me at least it is self evident #3416522: Add the ability to install multiple modules and only do a single container rebuild to ModuleInstaller broke this by changing the landscape, by changing what installed means. Fixing this without reverting to a slower system is somewhere between hard and impossible. (So much so that I knew it's this issue without checking which version it appeared in and then being not surprised at all to see it's 11.2 which this issue complains about.) I am afraid https://www.drupal.org/node/3473563 applies and an update of the change record to cover this is the only "fix" reasonably attainable.