Problem/Motivation

Currently the redirect is cached with the max-age of whatever variation we have active at the creation of the redirect. I.e.: the last one wins.

This is wrong as that can well play cache ping-pong and is not a deterministic outcome.

(See #3 and #4 for a practical example.)

Proposed resolution

Merge the max-age of the existing redirecting cache item plus that of the current render array that is causing the redirecting cache item to be updated.

Remaining tasks

Review.

User interface changes

None.

API changes

None.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

swentel’s picture

Status: Active » Needs review
FileSize
784 bytes

So, is it really only this ?

Fabianx’s picture

Yes, it is. We probably should add some tests though this being a bug ...

Wim Leers’s picture

Status: Needs review » Needs work
Issue tags: +Needs issue summary update

This will be able to copy/paste the test coverage added in #2493047: Cache redirects should be stored in the same cache bin and adjust it.


What I'm missing here is a thorough explanation for why we want to cache contexts permanently.

E.g.:

  1. a block is render cached by contexts A, B and C, with a max-age of 3600, and is using a cache redirect.
  2. context C is present because an access checker returned an access result with context C and max-age 3600
  3. after 3600 seconds have passed, the access checker no longer returns context C and max-age 3600, but context D, without a max-age

Then my question is: why should context C be permanently included in the cache redirect?

Fabianx’s picture

The problem is that currently the last set 'wins'.

So if we wanted to support that, we would need to take the mergeMaxAge() of all the max-ages that could be present and track those somehow, which is way more complicated than just making it permanent.

Wim Leers’s picture

Aha! Good point. The last max-age indeed always wins.

But we can easily retrieve the previous max-age: if the cache item's expired === -1, then it was Cache::PERMANENT. Otherwise, it is expire - created. Then we can use Cache::mergeMaxAges().

Or what am I missing?

Wim Leers’s picture

#2493047: Cache redirects should be stored in the same cache bin landed, which makes it much easier to write the necessary test coverage in this issue.

Wim Leers’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests
FileSize
11.87 KB

Et voila. A simple, elegant patch, thanks to all of the refactoring that went into RenderCache. And thanks to the test coverage that has been refined in #2493047: Cache redirects should be stored in the same cache bin and other issues, adding the necessary test coverage is also incredibly easy :)

Wim Leers’s picture

Title: #cache_redirect cache entries should be cached CACHE_PERMANENT » #cache_redirect cache items should have an 'expire' timestamp that matches the merged max-age

Update per #3 + #4.

Wim Leers’s picture

Issue summary: View changes
Issue tags: -Needs issue summary update

Status: Needs review » Needs work

The last submitted patch, 7: cache_redirect_max_age-2463581-7.patch, failed testing.

Wim Leers’s picture

Status: Needs work » Needs review
FileSize
11.88 KB
Fabianx’s picture

Status: Needs review » Reviewed & tested by the community

RTBC, looks great to me! :)

catch’s picture

Status: Reviewed & tested by the community » Needs review
+++ b/core/lib/Drupal/Core/Render/RenderCache.php
@@ -234,14 +228,16 @@ public function set(array &$elements, array $pre_bubbling_elements) {
+            'contexts' => $redirect_cacheability_updated->getCacheContexts(),
             // The union of the current element's and stored cache tags.
-            'tags' => Cache::mergeTags($stored_cache_tags, $data['#cache']['tags']),
+            'tags' => $redirect_cacheability_updated->getCacheTags(),
+            // The union of the current element's and stored cache max-ages.
+            'max-age' => $redirect_cacheability_updated->getCacheMaxAge(),
             // The same cache bin as the one for the actual render cache items.
             'bin' => $bin,
           ],
         ];

This could use additional documentation I think.

Based on comment #3, the redirect cache item always needs to have a TTL that is the same as the shortest redirected cache item at any one time - so that it expires when any of them do (in case things change on the expiry).

What we're essentially doing is bubbling max ages of cache contexts to cache redirect items - that's a lot of concepts to keep straight all at once.

Wim Leers’s picture

Status: Needs review » Reviewed & tested by the community

#13 It's just merging the cacheability metadata of the existing cache redirect (if any) with what would be written to the updated cache redirect. HEAD is already doing this for cache contexts and cache tags. All this patch does, is also do it for max-age. And hence, just do it for all bits of cacheability metadata. That's why this patch is able to simplify things.

Back to RTBC for more maintainer feedback.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 11: cache_redirect_max_age-2463581-11.patch, failed testing.

Status: Needs work » Needs review
Wim Leers’s picture

Status: Needs review » Reviewed & tested by the community

Test failures were not reproducible locally. Betting it was a testbot thing.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 11: cache_redirect_max_age-2463581-11.patch, failed testing.

Wim Leers’s picture

Status: Needs work » Reviewed & tested by the community
FileSize
11.89 KB

Was broken by #2511472: Refactor all usages of drupal_render()/Renderer::render() that break #2450993.

Rebased, conflict automatically resolved by git.

catch’s picture

Status: Reviewed & tested by the community » Needs review

@Wim yes I understand #14 but I think we should add extra docs explaining why exactly we have to do it.

Wim Leers’s picture

Status: Needs review » Reviewed & tested by the community
FileSize
12.45 KB
1.36 KB

Done.

catch’s picture

Status: Reviewed & tested by the community » Fixed

Committed/pushed to 8.0.x, thanks!

  • catch committed 6b371cc on 8.0.x
    Issue #2463581 by Wim Leers, swentel: #cache_redirect cache items should...

Status: Fixed » Closed (fixed)

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