Refactoring hux services breaks container rebuild

Created on 1 June 2023, over 1 year ago
Updated 16 June 2023, over 1 year ago

Problem/Motivation

In other issues I was attempting to refactor the services registered by hux.
E.g. 📌 Should we really cache the "HuxDiscovery" object? Closed: works as designed , implementation in 📌 Combined refactoring and attributes interface Needs review .

Unfortunately, when we change anything in hux.services.yml that is used by the hux module handler, we get errors like "class not found" or "wrong parameter type".

Normally this would be fixed by `drush cr` (container rebuild).
But with hux this does not work, because the module handler is created during bootstrap, before any container rebuild would happen.

Steps to reproduce

  1. Rename the class "HuxModuleHandler" to "HuxModuleHandlerRenamed".
  2. Change the same in hux.services.yml.
  3. Run `drush cr`.

Expected: Container is rebuilt just fine.
Actual: Class "HuxModuleHandler" not found.

Workaround

For the given issue I was able to circumvent this issue by leaving an old version of the HuxModuleHandler class, reduced to a stub, and adding a new version HuxModuleHandler1.

But this solution has no future.
In fact, all of the new services I introduce in the above mentioned issue would have the same problem.
So the next time we would want to refactor, the problem would be even bigger.

Proposed resolution

Either we never refactor anything related to hux.services.yml.
OR we find a way to trigger a container rebuild before the module handler is initialized.

Remaining tasks

User interface changes

API changes

Data model changes

📌 Task
Status

Closed: cannot reproduce

Version

1.2

Component

Code

Created by

🇩🇪Germany donquixote

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

Comments & Activities

  • Issue created by @donquixote
  • 🇩🇪Germany donquixote

    One option can be to return the decorated (core) module handler as a fallback.

  • 🇩🇪Germany donquixote

    We can do this kind of contraption. But I would really prefer something simpler.

      public static function createOrFallback(
        ContainerInterface $container,
        ModuleHandlerInterface $fallbackModuleHandler,
        string $huxModuleHandlerServiceId,
        string|int $huxContainerVersion,
      ): ModuleHandlerInterface {
        if ((string) $huxContainerVersion !== '2') {
          // Container is out of date.
          # \Drupal::service('kernel')->invalidateContainer();
          return $fallbackModuleHandler;
        }
        // Container is up to date. Get the real Hux module handler.
        $module_handler = $container->get($huxModuleHandlerServiceId);
        assert($module_handler instanceof ModuleHandlerInterface);
        return $module_handler;
      }
    
    
      hux.module_handler:
        decorates: module_handler
        class: Drupal\hux\HuxModuleHandler2
        public: true
        arguments:
          - '@hux.module_handler.inner'
          - '@hux.map'
        calls:
          - [ setContainer, [ '@service_container' ] ]
      hux.module_handler_or_fallback:
        decorates: module_handler
        class: Drupal\Core\Extension\ModuleHandlerInterface
        factory: [ Drupal\hux\HuxModuleHandler, 'createOrFallback' ]
        public: true
        arguments:
          - '@service_container'
          # The fallback module handler is the "decorated" object from the other decorator..
          - '@hux.module_handler.inner'
          - 'hux.module_handler_or_fallback.inner'
          - '%hux.container_version%'
    

    So the idea would be to have the "hux.module_handler_or_fallback" service, which would never change, but we are free to change any other services below that.

    So, we are using a "fake decorator" that does not actually wrap its own class around the decorated value, but instead returns either the original value, or something else.

  • Status changed to Closed: cannot reproduce over 1 year ago
  • 🇦🇺Australia dpi Perth, Australia

    Couldnt reproduce.

    Changed Classname + File name + updated reference in service.yml.

    No errors on `drush cr`, and Hux hooks continued to work.

    This is with stock Hux + Drupal 10.1 + fresh site install + only one Hux hook implementation.

    Posting stack:

    Closing as cant repro, feel free to reopen with more specific steps to repro, or alternative setup/enviro.

  • 🇩🇪Germany donquixote

    Now I cannot reproduce it either. Strange.
    I will get back to it when I have more time.

  • 🇩🇪Germany donquixote

    I found it!
    The problem occurs when I use drush/drush:12.1.0, but not with drush/drush:11.6.0.
    It seems that drush 12 does a more complete bootstrap before it runs the command.

Production build 0.71.5 2024