Problem/Motivation

BackendCompilerPass overrides a service tagged backend_overridable by replacing its definition with an alias to <driver>.<service id> (or <default_backend>.<service id>). The definition, and everything attached to it, is gone. Most of the problems below follow from that one decision.

Registration order in CoreServiceProvider::register() matters for two of them. All three passes are TYPE_BEFORE_OPTIMIZATION at priority 0, so they run in registration order:

line 80  ModifyServiceDefinitionsPass  (runs module service providers' alter())
line 86  ProxyServicesPass             (lazy services)
line 88  BackendCompilerPass

Every claim below was reproduced against Drupal 12 / PostgreSQL 18, PHP 8.5.5.

1. The tags of the overridden service are lost

  • Tagged collections are built with ContainerBuilder::findTaggedServiceIds(), which returns definitions and skips aliases, so the override inherits none of the tags.
  • The override never takes over the role the tags gave the service it replaces: no logger, no needs_destruction, no access_check.
  • A consumer that resolves a service name in a tagged service locator gets a ServiceNotFoundException. Drupal\Core\Queue\QueueFactory is such a consumer: #[AutowireLocator('queue_factory')] with a name that defaults to queue.database.
  • Core services that are backend_overridable plus another tag: cache_tags.invalidator.checksum, lock.persistent, session_handler.storage, path_alias.repository, logger.dblog, node.grant_storage. None is overridden in core today, which is why this stayed latent.
  • Fix: transfer the tags to the overriding definition, keyed by the name of the service it overrides. Not filed yet; blocks #3615202.

2. A module's alter() on an overridden service is silently discarded

  • ModifyServiceDefinitionsPass (line 80) runs before BackendCompilerPass (line 88).
  • A module service provider alters the core definition, then that definition is thrown away and replaced by the alias, with no warning.
  • Same root cause as 1, but the tag transfer does not fix it.
  • Open question: is this a bug, or the intended precedence of driver overrides over alter()? Either way it needs a decision and documentation. Not filed.

3. Overriding a private service makes the service ID public

  • Drupal\Core\DependencyInjection\ContainerBuilder::setAlias() forces setPublic(TRUE) on every alias (ContainerBuilder.php:58).
  • Visibility of the same service ID therefore depends on the database driver: views.date_sql is private on MySQL and public on PostgreSQL and SQLite.
  • \Drupal::service('views.date_sql') works on one driver and dies on another.
  • Private and backend_overridable in core: config.storage.active, menu.tree_storage, workspaces.entity.query.sql, workspaces.menu.tree_storage, views.date_sql.
  • The forced public is load bearing, not gratuitous: Alias::__construct() defaults to non public and RemovePrivateAliasesPass would then delete the service outright. A fix has to keep the alias reachable without widening the API of a service that was deliberately private.
  • Existing issue: #3021299 Ensure that aliased/used backend overridable are not set to private (Active).

4. Lazy (proxied) services tagged backend_overridable cannot be overridden

  • ProxyServicesPass (line 86) copies the definition, tags and all, to drupal.proxy_original_service.&lt;id&gt; and registers a fresh, untagged proxy definition at the original ID.
  • BackendCompilerPass (line 88) then finds the tag on the renamed service and looks for &lt;driver&gt;.drupal.proxy_original_service.&lt;id&gt;, which nobody defines, so pgsql.batch.storage is silently ignored.
  • Affects router.dumper and batch.storage in core today; both are lazy: true, backend_overridable and have generated proxy classes.
  • Existing issue: #3461330 Lazy services (backed by proxy classes) can't be backend_overridable because the proxy service isn't tagged (Active); comment #5 already identifies the cause.

Comments

daffie created an issue. See original summary.

daffie’s picture

Issue summary: View changes

Disclamer: This is was created with the help of AI.

longwave’s picture

Re point 4 we are hoping to remove lazy proxies in #3514491: [meta] Replace lazy service proxy generation with service closures