Problem/Motivation

The Rendered entity field adds cache tags for a all entity display config entities associated with the entity type of the rendered entity. In other words, if the content (node) view is configured to display a Rendered entity field, the cache tags for all configured entity view displays for node types will be added to the view/view display config's cache metadata. On a site with many content types and entity displays/view modes, this will bubble up all those cache tags on pages where the view is rendered. This can lead to errors such as #2844620: Automatically split cache debug headers into multiple lines when they exceed 8k.

Since rendering the entity will bubble up cache tags that are invalidated whenever entity view displays are saved, it is not necessary for the Rendered Entity plugin to include cache tags for the entity view displays in getCacheTags() at all.

Steps to reproduce

  1. Create a few different content types
  2. Create a few different view modes for content
  3. Configure custom displays for some view modes across content types
  4. Create and configure a view to display content with a Rendered entity field. Add a filter for a single content type
  5. Create test content that will be displayed in the view
  6. Visit page with the view.
  7. If http.response.debug_cacheability_headers is true, note that there are tags in the HTTP header for all configured node entity displays.
  8. Alternatively check the relevant entry in the cache_page database table and observe the tags there

Proposed resolution

Change getCacheTags() in \Drupal\views\Plugin\views\field\RenderedEntity to return an empty array.

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

Issue fork drupal-3187770

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

godotislate created an issue. See original summary.

godotislate’s picture

Status: Active » Needs review
StatusFileSize
new894 bytes

Here's a patch where getCacheTags() returns an empty array to see how it does against tests.

Status: Needs review » Needs work

The last submitted patch, 2: 3187770-views-rendered-entity-no-cache-tags-2.patch, failed testing. View results

godotislate’s picture

I discovered that the entity render array does not have the entity view display config as a cache tag that bubbles up, unless the Layout Builder module is enabled. In that case, next step will be to amend the patch to include cache tags for the selected view mode. Update patch and tests hopefully soon.

godotislate’s picture

Status: Needs work » Needs review
godotislate’s picture

Issue summary: View changes
godotislate’s picture

Issue summary: View changes

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.

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

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new149 bytes

The Needs Review Queue Bot tested this issue. It either no longer applies to Drupal core, or fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".

Apart from a re-roll or rebase, this issue may need more work to address feedback in the issue or MR comments. To progress an issue, incorporate this feedback as part of the process of updating the issue. This helps other contributors to know what is outstanding.

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

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.

godotislate’s picture

Status: Needs work » Needs review

Rebased MR against 11.x and tweaked some comment language.

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: +Needs Review Queue Initiative

Seems test-only feature was ran

1) Drupal\Tests\views\Kernel\Handler\FieldRenderedEntityTest::testRenderedEntityWithoutField
This test did not perform any assertions
/builds/issue/drupal-3187770/core/tests/Drupal/Tests/Listeners/DrupalListener.php:65
/builds/issue/drupal-3187770/vendor/phpunit/phpunit/src/Framework/TestResult.php:452
/builds/issue/drupal-3187770/vendor/phpunit/phpunit/src/Framework/TestSuite.php:684
/builds/issue/drupal-3187770/vendor/phpunit/phpunit/src/TextUI/TestRunner.php:651
/builds/issue/drupal-3187770/vendor/phpunit/phpunit/src/TextUI/Command.php:144
/builds/issue/drupal-3187770/vendor/phpunit/phpunit/src/TextUI/Command.php:97
ERRORS!
Tests: 2, Assertions: 0, Errors: 2, Risky: 1.

Change itself makes sense and I don't see any issue myself.

Good work!

catch’s picture

Status: Reviewed & tested by the community » Needs review

I am probably missing something but I feel like I need to ask:

::render does this:

  /**
   * {@inheritdoc}
   */
  public function render(ResultRow $values) {
    $entity = $this->getEntity($values);
    if ($entity === NULL) {
      return '';
    }
    $entity = $this->getEntityTranslationByRelationship($entity, $values);
    $build = [];
    $access = $entity->access('view', NULL, TRUE);
    $build['#access'] = $access;
    if ($access->isAllowed()) {
      $view_builder = $this->entityTypeManager->getViewBuilder($this->getEntityTypeId());
      $build += $view_builder->view($entity, $this->options['view_mode'], $entity->language()->getId());
    }
    return $build;
  

This should add the entity display cache tags to the rendered, output anyway - isn't that enough?

godotislate’s picture

@catch I vaguely recall having a similar thought when I originally ran into this three years ago, and then discovering that the tags still needed to be identified in the plugin getCacheTags() code. If so, I don't remember why, so I'll have to look into it again and refresh my memory.

ETA. Never mind, the strikeout text in the IS talks about this. And my comment #4 says that those display cache tags aren't bubbling up? I will re-confirm.

catch’s picture

godotislate’s picture

I investigated some and found a couple things.

First, I installed Drupal with standard profile against latest 11.x-dev (#840a726). Then I set http.response.debug_cacheability_headers: true. I created and saved an article node, and viewed the cache tags in the page response, which are these:
block_view config:block.block.olivero_account_menu config:block.block.olivero_breadcrumbs config:block.block.olivero_content config:block.block.olivero_help config:block.block.olivero_main_menu config:block.block.olivero_messages config:block.block.olivero_page_title config:block.block.olivero_powered config:block.block.olivero_primary_admin_actions config:block.block.olivero_primary_local_tasks config:block.block.olivero_search_form_narrow config:block.block.olivero_search_form_wide config:block.block.olivero_secondary_local_tasks config:block.block.olivero_site_branding config:block.block.olivero_syndicate config:block_list config:search.settings config:system.menu.account config:system.menu.main config:system.site config:user.role.anonymous http_response local_task node:1 node_view rendered user:1. The cache tag for the entity view display is not included.

Next, I installed Layout Builder, but did not configure any entity view displays to use it. Reloading the article node, the cache tags are these: block_view config:block.block.olivero_account_menu config:block.block.olivero_breadcrumbs config:block.block.olivero_content config:block.block.olivero_help config:block.block.olivero_main_menu config:block.block.olivero_messages config:block.block.olivero_page_title config:block.block.olivero_powered config:block.block.olivero_primary_admin_actions config:block.block.olivero_primary_local_tasks config:block.block.olivero_search_form_narrow config:block.block.olivero_search_form_wide config:block.block.olivero_secondary_local_tasks config:block.block.olivero_site_branding config:block.block.olivero_syndicate config:block_list config:core.entity_view_display.node.article.default config:search.settings config:system.menu.account config:system.menu.main config:system.site config:user.role.anonymous http_response local_task node:1 node_view rendered user:1. The entity view display tag now is included.

Doing a little debugging, from what I can tell, the isApplicable() method in Drupal\layout_builder\Plugin\SectionStorage\OverridesSectionStorage and Drupal\layout_builder\Plugin\SectionStorage\DefaultsSectionStorage is adding the entity view display as cacheable dependency. Otherwise without Layout Builder enabled, the entity render array does not bubble any entity view display cache tags. Should there be an issue to add the entity view display as a cacheable dependency in \Drupal\Core\Entity\EntityViewBuilder::getBuildDefaults() or similar?

On the Views side, I noticed this in the docblock for Drupal\views\Entity\View::addCacheMetadata():

Cache metadata is set per view and per display, and ends up being stored in
   * the view's configuration. This allows Views to determine very efficiently:
   * - the max-age
   * - the cache contexts
   * - the cache tags
   *
   * In other words: this allows us to do the (expensive) work of initializing
   * Views plugins and handlers to determine their effect on the cacheability of
   * a view at save time rather than at runtime.

So, even if the entity render array does bubble the view display cache tags, it might still make sense to compute them in RenderedEntity::getCacheTags() so they get saved to the view config.

catch’s picture

On the Views side, I noticed this in the docblock for Drupal\views\Entity\View::addCacheMetadata():

This is what I think is probably outdated though - if the cache tags are bubbled, we don't need to ask the plugins explicitly for them at all.

Should there be an issue to add the entity view display as a cacheable dependency in \Drupal\Core\Entity\EntityViewBuilder::getBuildDefaults() or similar?

Something like that sounds good to me yes.

godotislate’s picture

Status: Needs review » Needs work

After some digging:
In Drupal\Core\Entity\Entity\EntityViewDisplay::postSave(), the entity view builder resets its cache, which means it invalidates everything tagged with {ENTITY_TYPE_ID}_view, where {ENTITY_TYPE_ID} is the ID of the entity type the view display is for. (So saving a entity view display for a node type will invalidate cached items tagged with node_view). In this case, is it necessary to even include entity view display cache tags at all? The {ENTITY_TYPE_ID}_view tag does get bubbled, so to the original raised question, it doesn't seem necessary for the Rendered Entity plugin at least to include any entity view display cache tags.

Should there be an issue to add the entity view display as a cacheable dependency in \Drupal\Core\Entity\EntityViewBuilder::getBuildDefaults() or similar?

Something like that sounds good to me yes.

This does raise a separate question: is invalidating {ENTITY_TYPE_ID}_view too broad on an entity view display save? If we do add tags for entity view displays to entity render arrays, should it be enough for the view display tags be invalidated and not invalidate {ENTITY_TYPE_ID}_view? Not sure of the ramifications for what seems to be a pretty significant change.

In any event, moving this back to needs work to update MR and Issue to reflect solution of not including display cache tags via the plugin.

godotislate’s picture

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

Updated MR to so that the RenderedEntity plugin returns empty array for getCacheTags() and rebased.

Updated IS to reflect new solution.

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community

Rebased to run test-only feature

1) Drupal\Tests\views\Kernel\Handler\FieldRenderedEntityTest::testRenderedEntityWithoutAndWithField
This test did not perform any assertions
/builds/issue/drupal-3187770/core/tests/Drupal/Tests/Listeners/DrupalListener.php:60
/builds/issue/drupal-3187770/vendor/phpunit/phpunit/src/Framework/TestResult.php:452
/builds/issue/drupal-3187770/vendor/phpunit/phpunit/src/Framework/TestSuite.php:684
/builds/issue/drupal-3187770/vendor/phpunit/phpunit/src/TextUI/TestRunner.php:651
/builds/issue/drupal-3187770/vendor/phpunit/phpunit/src/TextUI/Command.php:144
/builds/issue/drupal-3187770/vendor/phpunit/phpunit/src/TextUI/Command.php:97
ERRORS!
Tests: 1, Assertions: 0, Errors: 1, Risky: 1.

Issue summary seems complete and code change is small for the cache tags and has a good comment explaining why it's empty array.

Note rebase failure is a random nightwatch or javascript depending when you look at it.

catch’s picture

This does raise a separate question: is invalidating {ENTITY_TYPE_ID}_view too broad on an entity view display save? If we do add tags for entity view displays to entity render arrays, should it be enough for the view display tags be invalidated and not invalidate {ENTITY_TYPE_ID}_view? Not sure of the ramifications for what seems to be a pretty significant change.

It's quite a rare operation especially on production sites and it reduces the necessary cache tags by a lot, so for me it's the right balance yeah.

quietone’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs followup

I'm triaging RTBC issues. I read the IS and the comments. @godotislate, thanks for working on this and the investigative work done.

There is good discussion and explanation of the problem in #19 -> #24.

In #23 catch commented that a follow up issue is needed. I am adding the tag and setting this to needs work for that followup.

Also in #23 catch asked if the doc block for Drupal\views\Entity\View::addCacheMetadata() is outdated. That also needs some investigation, which can be in a separate issue. Although, maybe there already is one?

I did not read the MR or test it.

godotislate’s picture

Status: Needs work » Reviewed & tested by the community
Issue tags: -Needs followup

Per conversation with catch on Slack, because the ENTITY_TYPE_view cache tags are invalidated on entity view display save (see #24), there is no need to invalidate the individual cache tag for the display itself.

Created follow-up issue for the docblock in Drupal\views\Entity\View::addCacheMetadata(): https://www.drupal.org/project/drupal/issues/3409816

Moving this back to RTBC.

godotislate’s picture

Status: Reviewed & tested by the community » Needs review

Added post update hook with tests to update existing view configurations to remove rendered entity cache tags.

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community

Addition of update hook seems fine, ran locally without issue at least.

catch’s picture

Status: Reviewed & tested by the community » Needs work

Question on the MR.

godotislate’s picture

Status: Needs work » Needs review

Made changes per review question and rebased.

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community
catch’s picture

Status: Reviewed & tested by the community » Needs work

This looks good but it needs a rebase.

godotislate’s picture

Status: Needs work » Reviewed & tested by the community

Rebased for merge conflict.

  • catch committed 9586ced5 on 11.x
    Issue #3187770 by godotislate, smustgrave, catch, quietone: Views...
catch’s picture

Status: Reviewed & tested by the community » Fixed
Related issues: +#2241377: [meta] Profile/rationalise cache tags

Committed/pushed to 11.x (which will become 10.3.x too), thanks!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.