Problem/Motivation

Discovered while debugging #3612284: Circular reference on Drupal 11.4: logger.raven eagerly resolves event_dispatcher during container build, it's possible to get circular references where the cache tags invalidator is loaded, because all invalidator services and all bins are eagerly loaded into the invalidator.

Tagged iterators would let us lazily load them instead, only when invalidateTags() is actually called. This might also improve performance.

Steps to reproduce

Proposed resolution

Convert the invalidators and bins properties to tagged iterators injected into the constructor.

Remaining tasks

User interface changes

Introduced terminology

API changes

Data model changes

Release notes snippet

Issue fork drupal-3622391

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

longwave created an issue. See original summary.

longwave-bot made their first commit to this issue’s fork.

longwave’s picture

Status: Active » Needs review

smustgrave’s picture

Status: Needs review » Needs work

Small comment feel free to self RTBC if it's nothing or you delete. @longwave.

mfb’s picture

FYI apparently this circular reference issue can be reproduced with core syslog module, which loads configuration in its logger constructor, making this both a bug and a task.

berdir’s picture

The syslog issue is not related to this and has an existing open issue.

+1 to this, noticed as well that all these bins get initialized early a while ago.

Not sure about BC here. This is a new constructor method. What happens if someone subclasses with it's own construct but didn't call the parent?

There is one subclass in contrib that I found, but that doesn't have a constructor: https://search.tresbien.tech/search?q=%22extends%20CacheTagsInvalidator%22

mfb’s picture

@berdir: This issue's merge request resolves the circular reference when core syslog and symfony_mailer modules are installed:

./vendor/bin/drush cr

In Container.php line 143:
                                                                                                                                                                                      
  Circular reference detected for service "logger.channel.default", path: "Drupal\Core\Recipe\Command\RecipeCommand -> logger.channel.default -> logger.factory -> logger.syslog ->   
  Drupal\menu_link_content\Hook\MenuLinkContentHooks -> plugin.manager.menu.link -> Drupal\Core\Menu\MenuTreeStorageInterface -> cache_tags.invalidator -> plugin.manager.block".

So as far as I can tell, the syslog issue is directly related to this one?

Note that I only get the circular reference every other time I run drush cr, not every time

longwave’s picture

@berdir I think extending CacheTagsInvalidator is going to be fairly rare so we can likely just add a change record? addBin() and addInvalidator() still work - we can deprecate these later in D12 if we want, or just leave them forever - so BC is only really concerning the constructor that I can see.

berdir’s picture

@mfb: That looks super weird to me, especially:

 logger.syslog -> Drupal\menu_link_content\Hook\MenuLinkContentHooks

Why would MenuLinkContentHooks get injected into logger.syslog, that makes no sense? Hook services should never get injected into something, especially not low-level services like a logger.

Also, plugin.manager.block shouldn't get injected into cache_tags.invalidator, that doesn't implement this tag, not in core at least. Maybe you're using some kind of custom module that overrides that?

To be clear, I fully support this change. I also think log channels should pretty much always use AutowireServiceClosure although I'm not sure would help much in this case. It's just quite surprising that this fixes that problem on your site and it looks like there might be something very strange going on there.

mfb’s picture

@longwave is one of several bug reporters who brought this issue to my attention. I thought it was "weird" too - I merely reproduced it.

It requires only the default install profile of Drupal core, core syslog module, symfony_mailer module, and Drush.

berdir’s picture

What I'd do is put a breakpoint in the constructor of MenuLinkContentHooks and then look at the backtrace. what exactly creates that, where, which parameter to what other service is it? I suspect the container recursion check is a bit confused, maybe something triggers a hook, possibly entity type definitions if that's not been built yet at that point?

You've been active in #3103620: Dependency on config storage causes circular reference in service container too, that's the issue I was thinking off. Would be nice to resolve that one.

mfb’s picture

According to @longwave, it's because "Symfony Mailer has a config factory override that also performs plugin discovery". As a result of those other subsystems pulling in a logger, any logger that gets configuration in its constructor, such as core syslog module, can trigger the circular reference when symfony_mailer is installed.

berdir’s picture

@longwave: I think I'm OK keeping it as is. On BC, I suppose that's a committer decision, technically the constructor and property type changes are BC breaks, also the fact that there's no one more list of services to worry about in case someone did replace it completely, I found only the one implementation in contrib that should be OK with those changes. I can mark it as RTBC with a note on that if you create a CR for that.