Problem/Motivation
This blocks #2466585: Decouple cache implementation from the renderer and expose as renderCache service
and #2469431: BigPipe for auth users: first send+render the cheap parts of the page, then the expensive parts
It is possible to corrupt the redirect cache by not varying cache contexts, but cache keys and trying to bubble that.
Proposed resolution
- Fix it by throwing a LogicException as it is a hard requirement that keys are not changed afterwards.
- Instead we could also opt to use the keys of the pre_bubbling_elements always.
- This refactors from pre_bubbling_cid to pre_bubbling_elements so that #keys are available for comparison and its a needed pre-step, too.
It also fixes cases where keys are suddenly available, but never before, so leading to unreachable cache entries.
Remaining tasks
- Review
- Commit
User interface changes
* None
API changes
* None
Beta phase evaluation
Issue category | Bug because functionality is broken |
---|---|
Issue priority | Normal bugfix |
Prioritized changes | The main goal of this issue is fixing a side effect of the cache bubbling system that could be gotten wrong. Therefore: Correctness and DX. |
Disruption | Only internal changes, not disruptive at all. |
Comment | File | Size | Author |
---|---|---|---|
#24 | interdiff.txt | 3.12 KB | effulgentsia |
#24 | changing_cache_keys-2469277-24.patch | 6.12 KB | effulgentsia |
#21 | changing_cache_keys-2469277-21.patch | 6.77 KB | Fabianx |
#21 | interdiff.txt | 622 bytes | Fabianx |
Comments
Comment #1
Fabianx CreditAttribution: Fabianx for Acquia commentedThis is both a bugfix as well as a requirement for placeholders / BigPipe (split out to get early reviews on it).
Comment #2
Fabianx CreditAttribution: Fabianx for Acquia commented- Fixed with a test
- Added unrelated @todo that I found while looking at the code (could also be removed)
- Exception message might need work
Comment #3
Fabianx CreditAttribution: Fabianx for Acquia commentedComment #5
Fabianx CreditAttribution: Fabianx for Acquia commentedThis blocks #2466585: Decouple cache implementation from the renderer and expose as renderCache service as that issue will be simpler once $pre_bubbling_elements is used for cacheSet() as second argument and we don't want to change API for that.
It also blocks #2469431: BigPipe for auth users: first send+render the cheap parts of the page, then the expensive parts, but that is just in proof-of-concept stage.
Hence increasing priority.
Comment #6
Wim LeersTest review:
s/does not/cannot/
Nit: s/llama::bar/llama:bar/
80 cols.
I expected this to only be overriding
keys
, but it's also overridingcontexts
?Code review:
That's not actually true, we support that. Since #2382667: #post_render_callback's that result from other #post_render_calback are not processed . Test coverage at
\Drupal\Tests\Core\Render\RendererPostRenderCacheTest::testRenderRecursivePostRenderCache()
.I'd think this also costs us extra memory. Is this really necessary?
Can't we instead: 1) keep
$pre_bubbling_cid
, 2) add$pre_bubbling_cache_keys
(or even just $cache_keys)?i.e. keep the same logic, but track the original cache keys and continue to use that, thus ignoring any cache keys set by
#pre_render
callbacks?Comment #7
Wim LeersComment #8
Fabianx CreditAttribution: Fabianx for Acquia commentedTest review notes:
1. Will fix
2. Will fix
3. Will fix
4. Will ...
Hold on ;)
Yes, if nothing else is bubbled the smart code in cacheSet won't overwrite the shared cache entry ;).
I think I will add a comment there, why overwrite foo is needed.
Code reviews:
1. The cache hit case is not covered (I have a test proving that), I will open a separate issue for that and apply the test-only patch.
2. Discussed in IRC
We came to the conclusion we only need the original $elements['#cache'] for now.
Comment #9
Fabianx CreditAttribution: Fabianx for Acquia commentedOpened #2470715: cacheGet-case: #post_render_callback's that result from other #post_render_calback are not processed as follow-up, fixed all things.
New patch attached.
Comment #10
YesCT CreditAttribution: YesCT commentedComment #11
YesCT CreditAttribution: YesCT commentedOh, r.1 stands for ..
role 1
----
I didn't understand everything, but looks like most of the items from @Wim Leers 's #6 were addressed, except @Fabianx mentioned "I think I will add a comment there, why overwrite foo is needed." and I do not see that change.
---
Is "Overwrite the #cache entry with new data." a copy and paste error? Because this does is called "NoOverwrite" and it is the same comment as in bubblingCacheOverwritePrerender()
Comment #12
YesCT CreditAttribution: YesCT commentedComment #13
Fabianx CreditAttribution: Fabianx for Acquia commentedThanks for the review, YesCT! And yes I indeed missed implementing my comment!
Comment #14
Fabianx CreditAttribution: Fabianx for Acquia commentedAnd fixed the issues from #12.
Comment #15
Fabianx CreditAttribution: Fabianx for Acquia commentedTagging for dev days
Comment #16
Wim Leerss/set/track/
s/elements/elements' #cache/
Let's use strict comparison.
s/cannot/may not/
s/added/additional/
The pre-bubbling cacheability metadata.
Calculate the pre-bubbling CID.
s/Setup/Set up/
These are never executed because the exception is triggered by the
::render()
call. Let's remove them.Comment #17
marcvangendSeems like a novice re-roll, I'll do it.
Comment #18
marcvangendHere's a patch with all changes proposed in #16.
Comment #19
Wim Leers@marcvangend: can you post an interdiff? :) Thanks!
Comment #20
Fabianx CreditAttribution: Fabianx for Acquia commentedThanks, addressed all feedback. (should be the same as marc's)
Comment #21
Fabianx CreditAttribution: Fabianx for Acquia commentedThanks to marc's patch (which will fail tests due to missing update to the Exception) I found a coding style, line too long error in mine ...
Comment #23
Wim LeersThanks for #21, I was going to mark it NW for that :)
Comment #24
effulgentsia CreditAttribution: effulgentsia at Acquia commentedPatch looks great, but the test seems to run a bunch of lines of code without asserting anything related to them. Since the fix that we ended up with here is to simply disallow changing #cache['keys'] mid-rendering (completely independently of anything having to do with contexts), how about simplifying the test to only testing that? See patch.
I also expanded the docs of the $pre_bubbling_elements parameter in cacheSet().
Comment #25
Fabianx CreditAttribution: Fabianx for Acquia commentedThe interdiff looks great to me, therefore back to RTBC.
Yes, indeed we only need to test wanted behavior. Not the reasons why.
Thanks so much!
Comment #27
effulgentsia CreditAttribution: effulgentsia at Acquia commentedCommitted and pushed to 8.0.x. Thanks all! (Yay, my first commit)
I don't think this needs a change record, because if a D7 or D8 module was changing #cache['keys'] after the initial cache get, it was broken anyway. This issue just changes it from being broken silently to having an explicit exception.
Comment #28
Fabianx CreditAttribution: Fabianx for Acquia commentedCongratulations on the first commit!
Comment #30
vincenzodb CreditAttribution: vincenzodb as a volunteer commentedMaybe the problem of this bug report (https://www.drupal.org/node/2589703) is related with changes in this issue.
Comment #31
Fabianx CreditAttribution: Fabianx for Acquia commented#30: This issue revealed the bug that was present in #2589703: Override number of items to display in contextual filter doesn't work.
So this issue is just the bearer of the bad news / Exception. It is not the cause of it :).
Comment #32
vincenzodb CreditAttribution: vincenzodb as a volunteer commentedOk, I've started my period with 'maybe' :)