Persisted services are causing lots of problems since if any other service is injected into a persisted service it has to be persisted to0 - however nothing mandates this. We should remove persisted services since afaik they were a work around for the problems of rebuilding the container due to a module enable in the middle of a request. We no longer have these problems.

For example the config.factory service - the event dispatcher is not persisted. This means that if the container is rebuilt and new events are adding listening to the configuration events then they will not fire.

This has been discussed before by @effulgentsia and @chx - with the latter okay with removing see #1885780: Remove persistence of config.factory across kernel reboots. One point raised by @effulgentsia is that synthetic services need to be persisted - but our only synthetic service (request) has special logic in the container build to manage this.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

alexpott’s picture

Status: Active » Needs review
FileSize
1.32 KB

Let's see what breaks.

Status: Needs review » Needs work

The last submitted patch, 1: 2190665.1.patch, failed testing.

alexpott’s picture

Status: Needs work » Needs review

1: 2190665.1.patch queued for re-testing.

dawehner’s picture

Do you remember the reason why it was done in the first place. Was that related with performance?

Status: Needs review » Needs work

The last submitted patch, 1: 2190665.1.patch, failed testing.

The last submitted patch, 1: 2190665.1.patch, failed testing.

alexpott’s picture

Status: Needs work » Needs review
FileSize
8.05 KB
10.27 KB

So all of the tests where failing because they installed / uninstalled modules and continue to use a previously built container. Fixing is easy. Therefore I think we have no use for persisted services anymore.

alexpott’s picture

FileSize
3.78 KB
14.15 KB

And lets remove all the persist code from DrupalKernel

longwave’s picture

Title: Remove peristed services » Remove persisted services
tstoeckler’s picture

Are we using $this->container in tests now? I didn't keep up with where we stand with that ATM. If that's currently correct then this is RTBC.

alexpott’s picture

#10 all of that is just copy and pastes and we still don't have an rtbc on the issue to say don't use it.

Berdir’s picture

I don't remember the original discussions in detail, but I think should get @effulgentsia in here, he probably remembers the most about what and why we did this.

effulgentsia’s picture

The concept of service persisting was introduced to handle the situation of needing a service object to be the same object (not a newly instantiated one) after a call to module_enable() or module_disable() as it was prior to that call. The original use case of that was #1187726-72: Add caching for configuration / rework config object loading (Was: Memory usage and i/o from config objects). I'm not sure what chx means in that comment by "unsynced", but just hypothesizing, perhaps it's related to a situation of having a modified but unsaved $config object around prior to calling module_(en|dis)able(), and then calling ->save() on it resulted in a weird mismatch between the factory object that created it and the new factory object in the container. Possibly similar weirdnesses for config storage services.

I ran into a similar/related issue in #1878512-2: Clean up Simpletest's kernel/container preparation/rebuild logic now that the kernel is responsive to module enabling, where event subscribers added dynamically to $container->get('event_dispatcher') would become lost if the event_dispatcher service got re-instantiated following a module enable/disable.

It's possible that these specific issues either already have or can be fixed in some way other than having a 'persist' facility. Or that we need to make the persist facility less brittle per the issue summary. Not sure yet which direction makes more sense.

alexpott’s picture

FileSize
9.4 KB

Well currently the event_dispatcher is not persisted. This causes interesting issues for modules that add event listeners for config. After a module enable the new event listeners will not be called because the config factory has an out of date event dispatcher - and one of the first things done after enabling a module is writing config :)

I think persisted services are unnecessary - as can be seen by the green patch which just removes the code and fixes some bad assumptions in tests. And I think they are a dangerous confusion - if the container is rebuilt all the services should be it has just be synchronised with each other.

Rerolled patch and removed changes to Drupal\language\Tests\LanguageNegotiationInfoTest as the necessary changes have been made in #2171683: Remove all Simpletest overrides and rely on native multi-site functionality instead

alexpott’s picture

If a process really is

needing a service object to be the same object

then it should get the service before the module enable and store it somewhere using hook_module_preinstall - although I really can not see why you'd want to do this.

Status: Needs review » Needs work

The last submitted patch, 14: 2190665.14.patch, failed testing.

alexpott’s picture

Status: Needs work » Needs review
FileSize
974 bytes
10.36 KB

Fixed remaining test failure.

alexpott’s picture

Issue summary: View changes
alexpott’s picture

Issue summary: View changes
FileSize
6.48 KB

If it helps to get this patch in I'm happy to remove the unnecessary usage of persistence first... patch attached leaves the ability to persist services.

sun’s picture

If a process really is

needing a service object to be the same object

then it should get the service before the module enable and store it somewhere using hook_module_preinstall - although I really can not see why you'd want to do this.

One example that I ran into is #2205295: Objectify session handler — the SessionHandler needs to be exposed as a service, because we need to manually write and close the session when the HttpKernel terminates, but yet, session handling is a native global state construct of PHP core and the single SessionHandler instance is registered with PHP core when the session is initialized.

A kernel rebuild/reboot would cause a new SessionHandler instance to be instantiated and terminated, which is different to the original that was registered, and in turn, the session would be written + closed more than once per request. Especially in a batched installation of multiple modules, we'd create as many new SessionHandler instances as the # of modules being installed.

A similar problem space exists for stream wrappers, which are also global state construct of PHP core. The current plan foresees to discover/collect and register all custom stream wrappers when the kernel boots, and to unregister them when it shuts down. Thus far, I missed to account for the kernel rebuild case in the proposed concept, so it is possible that we're facing similar requirements there.

In summary, there appear to be good arguments for removing the 'persist' tag from current core services, but I'm not sure whether we really are in a position to drop the concept entirely, because there appear to be discrete edge-cases (native global state constructs in PHP core) that need it.

That said, a viable alternative might be to hard-code the persisting logic for those PHP core edge-cases directly into the kernel rebuild process. (OTOH, I assume such code would look almost identically to the current persist code...)

Berdir’s picture

What about as a separate step, removing persist from the config system only and leave the concept? In a separate issue. I think that's what @alexpott cares about the most?

alexpott’s picture

@Berdir that's the patch in #19 :)

effulgentsia’s picture

Status: Needs review » Reviewed & tested by the community

Seems like there's agreement then.

Berdir’s picture

Title: Remove persisted services » Remove persist flag from services that do not need it
+++ b/core/core.services.yml
@@ -178,8 +172,6 @@ services:
   container.namespaces:
     class: ArrayObject
     arguments: [ '%container.namespaces%' ]
-    tags:
-      - { name: persist }
   default_plugin_manager:

It also changes this :)

The only reason we made container.namespaces an ArrayObject and a "service" instead of a array/parameter as it was initially was, was to benefit from the persist flag.

Without the persist flag, that's pretty useless :)

Changing it back would require changing all @container.namespaces to %container.namespaces% and changing all the type hints from \Traversable back to array. Not sure if we want to do that...

Also updated the issue title, the summary might need an update too?

alexpott’s picture

FileSize
456 bytes
6.32 KB

Rerolled and re-instated persistence of container.namespaces I still think persistence is a really bad idea but I care about it much more in the config service stack.

catch’s picture

Status: Reviewed & tested by the community » Fixed

Committed/pushed to 8.x, thanks!

Status: Fixed » Closed (fixed)

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

znerol’s picture

Filed #2277481: Remove persist flag from container.namespaces service.

Re #20: It is in fact not necessary to retain the session-manager instance across container rebuilds: #2272987: Do not persist session manager

znerol’s picture