Problem/Motivation

The persist service tag and its associated functionality has been the source of many nasty issues. The number of persisting services has been reduced by #2190665: Remove persist flag from services that do not need it, #2277481: Remove persist flag from container.namespaces service and #2272987: Do not persist session manager and now only two of them remain (request_stack and router.request_context). Let's remove them now.

Proposed resolution

Remove support for the persist service tag and instead manually set up the request stack after a container rebuild. Also remove support for persisting synthetic services across container rebuilds because this feature is unused since the removal of the request service.

Remaining tasks

Address #68

User interface changes

None.

API changes

Removal of the persist service tag.

Beta phase evaluation

Reference: https://www.drupal.org/core/beta-changes
Issue category Task
Issue priority Major
Disruption Disruptive for contributed and custom modules because it will require a BC break for code relying on persist services.
CommentFileSizeAuthor
#64 2368263-64.patch23.97 KBvacho
#56 2368263-56.patch23.5 KBravi.shankar
#41 2368263-41.patch12.32 KBGauravvvv
#40 raw-interdiff.2368263.34-40.txt8.16 KBlongwave
#40 2368263-40.patch18.47 KBlongwave
#34 interdiff-2368263.txt6.14 KBdawehner
#34 2368263-34.patch17.49 KBdawehner
#33 interdiff-33.txt1.06 KBamateescu
#33 2368263-33.patch11.34 KBamateescu
#31 interdiff-31.txt1.57 KBamateescu
#31 2368263-31.patch10.68 KBamateescu
#26 2368263-26.patch8.41 KBdawehner
#21 remove_the_persist-2368263-21.patch8.53 KBznerol
#19 interdiff.txt1.94 KBznerol
#19 remove_the_persist-2368263-19.patch8.53 KBznerol
#15 interdiff.txt4.57 KBznerol
#15 remove_the_persist-2368263-15.patch8.44 KBznerol
#10 remove_the_persist-2368263-10.patch5.11 KBznerol
#8 interdiff.txt2.7 KBznerol
#8 2368263-remove-persist-7.diff5.03 KBznerol
#1 2368263-remove-persist.diff4.2 KBznerol

Issue fork drupal-2368263

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:

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

znerol’s picture

Status: Active » Needs review
FileSize
4.2 KB
jibran’s picture

Can you please explain the problem space here? Why it is important? What are the nasty issues? Why does it exist in Symfony world and not Drupal world? Are we not going to support in D8 at all? Is it still possible for contrib to create a persist service? I hope these are not frustrating questions.
And thanks for all the awesome work in the issue queue.

znerol’s picture

Why does it exist in Symfony

The persist service tag is only present in Drupal, not in Symfony. It was introduced to work around issues when rebuilding the container (which is also something unique to Drupal).

dawehner’s picture

Just to let me understand it correctly, the purpose of the issue is to remove the API functioanlity but rather hardcode the two services during rebuild?

znerol’s picture

This looks stupid, isn't it? Let me phrase it like that: Ideally we would not persist anything across the container rebuild. The current request (including its parents) is the single global thing we regrettably need to keep.

I've tried to introduce an API for keeping service state across container rebuilds. Comments over there include:

@fabpot #2285621-10: Remove persist-tag and replace it with a container.state_recorder service

So, my point is that whatever you do here, it's going to be wrong for most cases. That's why instead of trying to replace it, it should be removed. From my understanding, persisted objects are only useful when some modules are added from the UI (and updateModules() is called). But in this case, why not flush the cache and immediately redirect the user so that you get a fresh container for the very next request?

@alexpot #2285621-13: Remove persist-tag and replace it with a container.state_recorder service

I've been trying to remove persisted services for ages.

@catch #2285621-14: Remove persist-tag and replace it with a container.state_recorder service

Getting rid of persisted services altogether sounds great if we can do it.

dawehner’s picture

  1. +++ b/core/lib/Drupal/Core/DrupalKernel.php
    @@ -988,6 +988,22 @@ protected function attachSynthetic(ContainerInterface $container) {
    +      while ($request = array_shift($requests)) {
    ...
    +        $container->get('router.request_context')->fromRequest($request);
    

    Don't we just need to register the last one? Just curious. We also do have RequestContext::fromRequestStack

  2. +++ b/core/lib/Drupal/Core/DrupalKernel.php
    @@ -1071,17 +1087,16 @@ protected function compileContainer() {
    +      if ($definition->isSynthetic()) {
    

    Just curious, can't we also manually take over the synthetic services? Classloader, kernel and service container should be available from within the DrupalKernel

znerol’s picture

People over at Symfony tend to regard synthetic services as being deprecated (had a short conversation in IRC with some contributors about that). Also it does not seem that anyone has a use-case for them anymore (thanks to request stack), except for kernel and class_loader which are special cased anyway. Therefore I'm tending to just ditch the code which tries to carry over synthetic services upon container rebuilds. This does not mean that Drupal will not support synthetic services at all, but references will not be kept automagically when the container is rebuilt.

What do you think?

znerol’s picture

Implements #7. Also addresses #6.1.

Fabianx’s picture

Priority: Normal » Major
Issue tags: +Needs reroll

I think we should do that.

Keeping just the request stack sounds good to me.

Probably needs a re-roll.

znerol’s picture

dawehner’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: -Needs reroll
+++ b/core/lib/Drupal/Core/DrupalKernel.php
@@ -1059,6 +1028,25 @@ protected function attachSynthetic(ContainerInterface $container) {
+      while ($request = array_shift($requests)) {
+        $container->get('request_stack')->push($request);
+      }

+1 for not trying to maintain the existing object but instead start with a new one.

Fabianx’s picture

RTBC + 1

znerol’s picture

Issue summary: View changes
jibran’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: -Needs issue summary update +Needs change record

Code changes look good. The patch could use some comments. Thanks for providing the complete context. IS summary is not updated with api changes. This is a task so needs a beta evaluation. Also, we are removing a functionality so we can update some old change record and perhaps add a new one for this.

  1. +++ b/core/lib/Drupal/Core/DrupalKernel.php
    @@ -1059,6 +1028,25 @@ protected function attachSynthetic(ContainerInterface $container) {
    +    // Restore request stack.
    

    I think we can explain here why we have to restore request stack?

  2. +++ b/core/lib/Drupal/Core/DrupalKernel.php
    @@ -1059,6 +1028,25 @@ protected function attachSynthetic(ContainerInterface $container) {
    +      $original_request_stack = clone $this->container->get('request_stack');
    

    By directly looking at the code I can't tell that $this->container is an old container so can we please add a comment here as well?

  3. +++ b/core/lib/Drupal/Core/DrupalKernel.php
    @@ -1059,6 +1028,25 @@ protected function attachSynthetic(ContainerInterface $container) {
    +      while ($request = $original_request_stack->pop()) {
    +        $requests[] = $request;
    +      }
    ...
    +      while ($request = array_shift($requests)) {
    +        $container->get('request_stack')->push($request);
    +      }
    

    This can be done in a single loop?

  4. +++ b/core/lib/Drupal/Core/DrupalKernel.php
    @@ -1059,6 +1028,25 @@ protected function attachSynthetic(ContainerInterface $container) {
    +      if ($request) {
    +        $container->get('router.request_context')->fromRequest($request);
    

    I think this needs a comment as explained in #6.1

znerol’s picture

Status: Needs work » Needs review
FileSize
8.44 KB
4.57 KB

Let's try to extract the state restoring logic to its own method. This makes it possible to document it properly and at the same time tidy up initializeContainer() quite a bit.

znerol’s picture

I think that the persist tag was introduced here #1187726-72: Add caching for configuration / rework config object loading (Was: Memory usage and i/o from config objects) but that issue does not have any change record. Also I do not find any documentation about it.

Status: Needs review » Needs work

The last submitted patch, 15: remove_the_persist-2368263-15.patch, failed testing.

Fabianx’s picture

+++ b/core/lib/Drupal/Core/DrupalKernel.php
@@ -1059,10 +994,63 @@ protected function attachSynthetic(ContainerInterface $container) {
+        if ($request->hasSession()) {
+          $request->setSession($container->get('session'));
+        }
...
+    if ($this->container->initialized('session')) {

Would the above initialize the session and the below then being true?

Would it make sense to first check the session, then the request stack?

znerol’s picture

Status: Needs work » Needs review
FileSize
8.53 KB
1.94 KB

Indeed, the request stack needs to be rebuilt before the session is initialized. So the proper sequence is:

  1. Restore the request stack.
  2. Restart the session
  3. Refresh the session on the request(s)

Status: Needs review » Needs work

The last submitted patch, 19: remove_the_persist-2368263-19.patch, failed testing.

znerol’s picture

Status: Needs work » Needs review
FileSize
8.53 KB

Reupload. Test failures in UncaughtExceptionTest should be gone due to #2540538: Behavior of testErrorContainer() and testExceptionContainer() is unpredictable. Those in ExternalFormUrlTest will be gone as soon as #2505339: Stop using getMainRequest() to build $form['#action'] is in.

Status: Needs review » Needs work

The last submitted patch, 21: remove_the_persist-2368263-21.patch, failed testing.

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

dawehner’s picture

Status: Needs work » Needs review
FileSize
8.41 KB

This is just a reroll for now.

Status: Needs review » Needs work

The last submitted patch, 26: 2368263-26.patch, failed testing.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

amateescu’s picture

Here's another reroll and a couple more fixes.

Status: Needs review » Needs work

The last submitted patch, 31: 2368263-31.patch, failed testing. View results

amateescu’s picture

This should fix all the kernel tests, but the fail in TwigDebugMarkupTest is a bit beyond me..

dawehner’s picture

Version: 8.6.x-dev » 8.7.x-dev
Status: Needs work » Needs review
FileSize
17.49 KB
6.14 KB

Rebuilding a container in place is always gonna be tricky. Instead I converted to test to a kernel test

Status: Needs review » Needs work

The last submitted patch, 34: 2368263-34.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

longwave’s picture

Status: Needs work » Needs review
FileSize
18.47 KB
8.16 KB

Rerolled for 9.2.x, raw interdiff attached. The messenger messages are now persisted across rebuilds, I've tried to update that code to match the new method.

Gauravvvv’s picture

Re-rolled patch #40.
Please review.

longwave’s picture

longwave’s picture

Unsure why the template order is slightly different in the kernel test vs the functional test - the XSS injected template name appears in a different position in the list, which is why the test assertions have changed slightly.

Status: Needs review » Needs work

The last submitted patch, 41: 2368263-41.patch, failed testing. View results

longwave’s picture

Status: Needs work » Needs review

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

andypost’s picture

andypost’s picture

neclimdul made their first commit to this issue’s fork.

neclimdul’s picture

Rebased and synced some small changes. Couple deprecation and some Symfony 6 stuff conflicted.

neclimdul’s picture

Status: Needs review » Needs work

Looking at the patch and there's no BC. That made sense when the patch was written against 8.0 beta but guess that's not true anymore. :(

I'd expect this to still not be very disruptive but seems there are a handful of actual modules using it.
https://git.drupalcode.org/search?group_id=2&scope=blobs&search=%22name%...

andypost’s picture

Version: 9.5.x-dev » 10.1.x-dev

I bet no way to make it in to 9.5 so moving to 10.1, MR needs rebase

ravi.shankar’s picture

Added a patch for Drupal 10.1.x.

andypost’s picture

@neclimdul what do you mean with BC? We getting rid of tag, no way to provide BC

catch’s picture

We can't provide backwards compatibility in Drupal 10, but we could potentially have a 9.5.x-only patch that triggers a deprecation when the persist tag is used.

We could also have a similar warning in Drupal 10 that just informs people the persist tag is a no-op (or throws an exception even?).

andypost’s picture

@neclimdul maybe we get rid of synthetic services in follow-up? Then BC will be easier

neclimdul’s picture

Sorry, I see the confusion. I meant what catch said, there isn't a version of this that says "Hey, you're using persist on your service and that's not going to do anything in 10.x" or what ever deprecation schedule this fits into.

andypost’s picture

Thanks, that's where I stuck - we can't provide BC - only a deprecation warning

mglaman’s picture

I just hit this in #3278493: Make it easier for theme builders to enable Twig debugging and disable render cache. How Drupal\Core\KeyValueStore\KeyValueMemoryFactory is tried to be persisted causes tests to break because the service isn't persisted.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

vacho’s picture

longwave’s picture

Given #58 should we split this into two issues? Deprecate the persist service tag in 10.3, and then remove it in 11.0?

longwave’s picture

Status: Needs work » Needs review

Rebased against 11.x in a new branch on MR!6658. Locally the functional version of TwigDebugMarkupTest passes, so I removed the conversion to a kernel test here.

longwave’s picture

Should restoreServiceState() be decoupled from the kernel? Each persistent service could be responsible for transferring its data from the old to the new one, via an intermediate service that collects persist services tags and calls each service to do the work?

smustgrave’s picture

Issue summary: View changes
Status: Needs review » Needs work

Hiding patches for clarity

Added #68 to remaining tasks

Moving to NW for change record unless you are waiting for an answer to 68 first, if that's the case can put back in review. But I didn't get that vibe that was the case.

andypost changed the visibility of the branch 2368263-remove-the-persist to hidden.

andypost’s picture

Polished a bit new code

Re#68

Looking at UpdateKernel and InstallerKernel I see both overriding initializeContainer() but calling parent, so I think it's ok to keep it in DrupalKernel

andypost’s picture