Problem/Motivation
Add a custom block to your site. View a page with it. Then look at your {cache_render} table. You'll see an entry for the block (entity_view:block:BLOCK_ID:...
) that does not include roles in that cache ID, even though that's a context specified in EntityViewBuilder::getBuildDefaults() as something that should apply to 'block_content' entities. The problem is that BlockContent specifies render_cache = FALSE
in order to not cache the content entity, since the block itself is cached, but EntityViewBuilder::getBuildDefaults() only adds the 'contexts' if the entity itself is render cacheable, which is wrong, because contexts need to bubble up to parent elements, so should be added regardless, just like tags.
Proposed resolution
- Fix EntityViewBuilder to add 'contexts' outside of the isRenderCacheable() if statement, just like 'tags'.
Remaining tasks
Commit.
User interface changes
API changes
Comment | File | Size | Author |
---|---|---|---|
#57 | interdiff.txt | 3.94 KB | Wim Leers |
#57 | block-content-block-cache-2396333-57.patch | 7 KB | Wim Leers |
#54 | interdiff.txt | 766 bytes | effulgentsia |
#54 | block-content-block-cache-2396333-54.patch | 3.62 KB | effulgentsia |
#53 | block-content-block-cache-2396333-53-test-only.patch | 2.76 KB | effulgentsia |
Comments
Comment #1
effulgentsia CreditAttribution: effulgentsia commentedPer the issue summary, I'm not sure whether to postpone this on #2099137: Entity/field access and node grants not taken into account with core cache contexts or whether to implement getRequiredCacheContexts() as returning the same contexts currently hard-coded in EntityViewBuilder::getBuildDefaults(). Thoughts?
Comment #2
jibranBlockContentBlock belongs to block_content module.
Comment #3
effulgentsia CreditAttribution: effulgentsia commentedConfirmed with the branch maintainers that this is indeed critical.
Comment #4
larowlanis this in fact active? or postponed on #2099137: Entity/field access and node grants not taken into account with core cache contexts
if it is active, I should be able to look at it on the weekend
Comment #5
effulgentsia CreditAttribution: effulgentsia commentedI think it makes sense to proceed with the "or" part of #1, since that can be done quickly (and a test added), and then improve the implementation of that method as part of #2099137: Entity/field access and node grants not taken into account with core cache contexts.
Perhaps a bonus that could be done here though is instead of duplicating the contexts that are hard-coded in getBuildDefaults(), move that out into a method somewhere that both EntityViewBuilder and BlockContentBlock have access to. Unless we're opposed to introducing a public method that might go away once the other issue is done.
Comment #6
effulgentsia CreditAttribution: effulgentsia commentedHm, how about just adding a public EntityViewBuilder::getCacheContexts() method with the same signature as getBuildDefaults() has? I think we'll be able to then keep that API working in #2099137: Entity/field access and node grants not taken into account with core cache contexts, just improve its implementation over there. I might be wrong about that, but that's my best guess at this time.
Comment #7
larowlanAre we sure this is still an issue?
Following steps to reproduce in IS I did the following:
Created a block content block
Placed it in sidebar
Viewed the homepage
Selected distinct cid from cache_render
Here's what I get
The entity_view:block:block_id (fooey in this case) has both timezone and role in it.
Screenshot:
Comment #8
larowlanDoh, I had my patch applied - which is attached.
So just needs a test here.
Comment #10
larowlanHere's a failing test
Comment #12
jibranI think this covers #5. We should update proposed resolution in IS with current tasks.
Comment #13
larowlanUpdated IS
Comment #14
Wim LeersQuick review.
string[]
If it's an array with those keys, it's not just cache contexts. I think this comment is wrong?
Must be
array_merge()
, since keys are numeric.Must all be plural.
Comment #15
larowlanThanks @WimLeers, all great catches, you can see I changed my mind over time, but didn't go back to rectify.
#14
Comment #17
larowlandoh
Comment #19
Wim LeersShould have an
@see
to\Drupal\Core\Entity\EntityViewBuilder::getBuildDefaults()
.Better yet, I'd argue that the default cache contexts embedded in that method should actually be moved into a
\Drupal\Core\Entity\EntityViewBuilder::getCacheContexts()
method, so that each entity type's builder can easily override it (that's not an API change!), so thatBlockContentBlock
can then call that.Then there is no duplication of logic (and duplication of the list of cache contexts to use), which always comes with that unavoidable brittleness.
You can then still create a
public getBlockCacheContexts()
, which would just return whatever the (inherited)protected getCacheContexts()
returns, to allowBlockContentBlock
to use it.All of this can be simplified: it can be turned into a check that checks whether a render cache item with the expected cache ID exists. See
\Drupal\system\Tests\Entity\EntityCacheTagsTestBase::verifyRenderCache()
and its callers for examples.Comment #20
larowlanfixes warnings, not started on #19 yet
Comment #21
larowlanComment #22
larowlan19.1 I think that is what #2099137: Entity/field access and node grants not taken into account with core cache contexts is for - @effulgentsia said we could move ahead here provided the solution was compatible with the approach there. I can tackle it here instead - please advise?
19.2 - done
Comment #26
larowlanpasses locally, so figure trying something different
Comment #27
larowlan@WimLeers or @effulgentsia can you advise if I should be tackling 19.1 here or in the related issue
Comment #29
larowlanlarowlan--
Comment #31
larowlanright, so I'm out of ideas - this passes locally
Comment #32
webchickSorry, just doing some house-cleaning. Since D8 cacheability is a subset of Performance, adding the more common tag as well.
Comment #33
tim.plunkett@larowlan this passes locally for you because you're in Australia/Sydney, but I'm in America/Los_Angeles, and the testbots probably are too.
Comment #34
larowlanThanks Tim
/me feels like a nuffy for not picking that up
Comment #35
webchickThanks for the vocabulary lesson. :D
Comment #36
Wim LeersWe're now solving this generically at #2429257: Bubble cache contexts.
Let's revisit this once that has landed, just to make sure.
Comment #37
Wim Leers#2429287: [meta] Finalize the cache contexts API & DX/usage, enable a leap forward in performance landed, this is now unblocked.
Comment #38
Wim LeersWanted to do a straight reroll of the patch, but just remove all the hunks that fixed the problem, to see if #2429257: Bubble cache contexts on its own fixed this.
But #2428633: Remove unnecessary BlockContentFieldTest removed
BlockContentFieldTest
. Not sure what the new best place for a test is.I believe larowlan wants to take a shot at this.
Comment #39
BerdirI'd just bring the test back, possibly as a simplified and renamed version, we don't need the configurable field stuff and so on anymore I think.
Comment #40
larowlanyep that's my plan, hoping to work on this in transit to DrupalSouth (in 7 hrs or so)
Comment #41
effulgentsia CreditAttribution: effulgentsia commentedManually tested HEAD, and found it still fails, but differently than the issue summary says:
That latter entry no longer exists due to #2284917: In-place editing of custom blocks broken *again* (because attributes and contextual links of custom blocks are lost).
But, EntityViewBuilder::getBuildDefaults() only adds contexts if isRenderCacheable() is true, which seems wrong, since even if it's not cacheable on its own, we still need the contexts to bubble up. Leaving this issue critical for that reason.
Additionally, even if this issue can be fixed by making the bubbling work, I think this is a case where we should still do something similar to what #33 does and get that info into the block without relying on bubbling, because:
However, neither of the above points justify a "critical" priority, so if we want to limit the scope of this issue to just solving the part that is and punt the rest to a non-critical follow-up, that's fine too.
Comment #42
effulgentsia CreditAttribution: effulgentsia commentedApparently, we already have an issue for this: #2428805: Remove the ability to configure a block's cache contexts
Comment #43
Wim LeersI don't think you wanted to link to #2284917: In-place editing of custom blocks broken *again* (because attributes and contextual links of custom blocks are lost)?
I noticed that too.
Comment #44
Wim LeersTo clarify, that's because we split up
#cache[keys]
into#cache[keys]
+#cache[contexts]
, but then failed to move#cache[contexts]
to the place where#cache[tags]
is set, which runs unconditionally. We simply split it up and kept it in the same branch of code.That's how this happened.
Comment #45
effulgentsia CreditAttribution: effulgentsia commentedI did. That's the issue that added
render_cache = FALSE
toBlockContent
.Comment #46
Wim LeersAh, that makes sense :)
Comment #47
larowlanso started on test on plane, but getting
"cache_context.timezone" is not a valid cache context ID."
exceptionComment #49
dawehnerit should be just 'timezone'. Ran into the same problem earlier.
Comment #50
larowlanRight but that's in HEAD?
Comment #51
larowlanComment #53
effulgentsia CreditAttribution: effulgentsia commentedDifferent testing approach. Here's just a test-only to prove it fails on HEAD.
Comment #54
effulgentsia CreditAttribution: effulgentsia commentedIn #41, I argued that we should do this approach based on a belief that it would be more performant and a concern about the block cache settings UI. However, the latter will be removed in #2428805: Remove the ability to configure a block's cache contexts and looking at the above code, that hardly seems more performant than a cache get from a #cache_redirect. Therefore, here's this alternate fix, as alluded to in #41.
Comment #57
Wim LeersLet's put these on separate lines.
Fixed that, and fixed the test failures.
Comment #58
Fabianx CreditAttribution: Fabianx commentedThanks for the extensive test coverage.
The problem indeed was the conditional vs. non-conditional execution of the code path.
This is RTBC.
Comment #59
Fabianx CreditAttribution: Fabianx commentedIt would be great to get an IS update so that it matches the patch.
Comment #60
effulgentsia CreditAttribution: effulgentsia commentedUpdated summary.
Comment #61
Fabianx CreditAttribution: Fabianx commentedThanks, effulgentsia! IS looks great now!
Comment #62
catchGreat how cache context bubbling makes an issue like this straightforward.
Committed/pushed to 8.0.x, thanks!
Comment #64
larowlanThanks all