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
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. |
Comment | File | Size | Author |
---|
Issue fork drupal-2368263
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
Comment #1
znerol CreditAttribution: znerol commentedComment #2
jibranCan 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.
Comment #3
znerol CreditAttribution: znerol commentedThe
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).Comment #4
dawehnerJust 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?
Comment #5
znerol CreditAttribution: znerol commentedThis 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
@alexpot #2285621-13: Remove persist-tag and replace it with a container.state_recorder service
@catch #2285621-14: Remove persist-tag and replace it with a container.state_recorder service
Comment #6
dawehnerDon't we just need to register the last one? Just curious. We also do have
RequestContext::fromRequestStack
Just curious, can't we also manually take over the synthetic services? Classloader, kernel and service container should be available from within the DrupalKernel
Comment #7
znerol CreditAttribution: znerol commentedPeople 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
andclass_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?
Comment #8
znerol CreditAttribution: znerol commentedImplements #7. Also addresses #6.1.
Comment #9
Fabianx CreditAttribution: Fabianx as a volunteer commentedI think we should do that.
Keeping just the request stack sounds good to me.
Probably needs a re-roll.
Comment #10
znerol CreditAttribution: znerol commentedReroll
Comment #11
dawehner+1 for not trying to maintain the existing object but instead start with a new one.
Comment #12
Fabianx CreditAttribution: Fabianx as a volunteer commentedRTBC + 1
Comment #13
znerol CreditAttribution: znerol commentedComment #14
jibranCode 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.I think we can explain here why we have to restore 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?This can be done in a single loop?
I think this needs a comment as explained in #6.1
Comment #15
znerol CreditAttribution: znerol commentedLet'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.Comment #16
znerol CreditAttribution: znerol commentedI 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.Comment #18
Fabianx CreditAttribution: Fabianx as a volunteer commentedWould the above initialize the session and the below then being true?
Would it make sense to first check the session, then the request stack?
Comment #19
znerol CreditAttribution: znerol commentedIndeed, the request stack needs to be rebuilt before the session is initialized. So the proper sequence is:
Comment #21
znerol CreditAttribution: znerol commentedReupload. Test failures in
UncaughtExceptionTest
should be gone due to #2540538: Behavior of testErrorContainer() and testExceptionContainer() is unpredictable. Those inExternalFormUrlTest
will be gone as soon as #2505339: Stop using getMainRequest() to build $form['#action'] is in.Comment #26
dawehnerThis is just a reroll for now.
Comment #31
amateescu CreditAttribution: amateescu for Pfizer, Inc. commentedHere's another reroll and a couple more fixes.
Comment #33
amateescu CreditAttribution: amateescu for Pfizer, Inc. commentedThis should fix all the kernel tests, but the fail in
TwigDebugMarkupTest
is a bit beyond me..Comment #34
dawehnerRebuilding a container in place is always gonna be tricky. Instead I converted to test to a kernel test
Comment #40
longwaveRerolled 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.
Comment #41
Gauravvvv CreditAttribution: Gauravvvv at OpenSense Labs for DrupalFit commentedRe-rolled patch #40.
Please review.
Comment #43
longwave@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.
Comment #44
longwaveUnsure 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.
Comment #46
longwaveComment #50
andypostComment #51
andypostRelated #3300306-6: Drupal ContainerBuilder allows mutation of non-synthetic services explains why it's now required
Comment #53
neclimdulRebased and synced some small changes. Couple deprecation and some Symfony 6 stuff conflicted.
Comment #54
neclimdulLooking 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%...
Comment #55
andypostI bet no way to make it in to 9.5 so moving to 10.1, MR needs rebase
Comment #56
ravi.shankar CreditAttribution: ravi.shankar at OpenSense Labs commentedAdded a patch for Drupal 10.1.x.
Comment #57
andypost@neclimdul what do you mean with BC? We getting rid of tag, no way to provide BC
Comment #58
catchWe 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?).
Comment #59
andypost@neclimdul maybe we get rid of synthetic services in follow-up? Then BC will be easier
Comment #60
neclimdulSorry, 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.
Comment #61
andypostThanks, that's where I stuck - we can't provide BC - only a deprecation warning
Comment #62
mglamanI 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.Comment #64
vacho CreditAttribution: vacho at Skilld commentedDebasing patch #56
Comment #65
longwaveGiven #58 should we split this into two issues? Deprecate the persist service tag in 10.3, and then remove it in 11.0?
Comment #67
longwaveRebased 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.
Comment #68
longwaveShould 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?Comment #69
smustgrave CreditAttribution: smustgrave commentedHiding 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.
Comment #71
andypostPolished a bit new code
Re#68
Looking at
UpdateKernel
andInstallerKernel
I see both overridinginitializeContainer()
but calling parent, so I think it's ok to keep it inDrupalKernel
Comment #72
andypostreroll after #3419987: Fix Container::reset() and provide DrupalKernel::resetContainer()