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.

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:

Comments

znerol’s picture

Status: Active » Needs review
StatusFileSize
new4.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

StatusFileSize
new5.03 KB
new2.7 KB

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

StatusFileSize
new5.11 KB

Reroll

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
StatusFileSize
new8.44 KB
new4.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
StatusFileSize
new8.53 KB
new1.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
StatusFileSize
new8.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
StatusFileSize
new8.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

Status: Needs work » Needs review
StatusFileSize
new10.68 KB
new1.57 KB

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

StatusFileSize
new11.34 KB
new1.06 KB

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
StatusFileSize
new17.49 KB
new6.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
StatusFileSize
new18.47 KB
new8.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

StatusFileSize
new12.32 KB

Re-rolled patch #40.
Please review.

longwave’s picture

@Gauravmahlawat thanks, but #41 is missing the TwigDebugMarkupTest that was converted from a functional to a kernel test.

I opened a merge request instead of using the patch workflow, fixed the test and coding standards issues, and deleted the old test.

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.

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

StatusFileSize
new23.5 KB

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

StatusFileSize
new23.97 KB

Debasing patch #56

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

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.

longwave’s picture

Status: Needs work » Needs review

Trying to revive this. Not sure if we can remove the tag entirely yet, but MR!15404 redoes this work including combining initializeContainer() and resetContainer(), which largely do the same thing.

oily’s picture

Created a draft CR. Needs work.

needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new90 bytes

The Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".

This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

smustgrave’s picture

Status: Needs work » Needs review

Bot probably picked the wrong MR

znerol’s picture

Thanks for reviving this. It looks like the PHPUnit Kernel fails are legit. Something seems to be wrong with the package manager PostApplyEvent.

oily’s picture

I think I might be PHPCS'ing on wrong MR? Can we hide one? Just saw the 'take-2' on the end of the name of the bottom one. Sounds like it is the 'live' one?

dcam changed the visibility of the branch 2368263-remove-persist-11.x to hidden.

dcam’s picture

Status: Needs review » Needs work

I think I might be PHPCS'ing on wrong MR? Can we hide one? Just saw the 'take-2' on the end of the name of the bottom one. Sounds like it is the 'live' one?

Yes. I hid the older MR. I'm not sure if that was the right call or not, but it's easy to un-hide it if necessary.

I'm setting the status to Needs Work because there are still test failures that must be corrected, as mentioned in #79.

oily’s picture

Have removed the kernel test assertions that were failing. Not sure if that is what was the right way to fix the tests. But the kernel tests are passing.

There are 2 functional tests failing. Looking at LanguageNegotiationContentEntityTest.php that fails at line 148, there is earlier inside the test function a container rebuild at line 113. Not sure how that is fixed?