Problem/Motivation

#2428563-20: Introduce parameter-dependent cache contexts

See #3.

Proposed resolution

See #3.

Remaining tasks

Do it.

User interface changes

None.

API changes

None.

Beta phase evaluation

Reference: https://www.drupal.org/core/beta-changes
Issue category Task, because this is a hardening against a theoretical bug that would only occur under very special circumstances.
Issue priority Normal because very unlikely circumstances, but the hardening is still important.
Prioritized changes The main goal of this issue is to be a follow-up from major / critical tasks - when cache contexts had been introduced (that issue was open since then) and to reduce fragility in that currently theoretically two cache contexts could return the same value and then theoretically a cache item could be wrongly retrieved. This hardens against this case and also as non-prioritized side-effect improves DX.
Disruption Almost zero disruption. For 99% of developers, zero disruption. The sole exception: the very few tests that actually test that caching of something that is rendered is working by hardcoding a cache ID. Those are very easy to update, as the patch shows.
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

cosmicdreams’s picture

Hi I just found this issue. Please forgive the naive questions:

1. Does CacheContext order matter? Some implementations sort their contexts, some append a new context to the end of a list. There are a lot the send a static value.

2. Does #2428563-20: Introduce parameter-dependent cache contexts Primarily discuss a change to the CacheContext tests?

3. What are the next steps here?

Wim Leers’s picture

Status: Active » Closed (works as designed)

AFAICT this is about this bit in #2428563-20: Introduce parameter-dependent cache contexts:

+++ b/core/tests/Drupal/Tests/Core/Cache/CacheContextsTest.php
@@ -17,20 +19,19 @@
+      'foo',
+      'baz:parameter',
+    ]);
-    $expected = ['bar'];
+    $expected = ['bar', 'baz.cnenzrgre'];
     $this->assertEquals($expected, $new_keys);

It confuses me that I put in baz then ':' and receive baz and '.'.

Should we not standardize that?

e.g. it might be needed (not sure where) to calculate from a CID back to cache contexts.

There's no need to standardize: what matters is that we get back a string, that somehow uniquely identifies this specific cache context. If we're going to also impose a strong structure on the value of the cache context, we're A) not gaining anything noteworthy, B) making things more complex.

What matters is that given a certain cache context, you get back a certain string of data. That's it. As long as that string makes sense within the context (heh…) of that cache context, that's fine.

That final bit, about calculating the cache contexts from a CID, I think a small desire to be able to do that, is what caused this confusion (and this very issue). But there is no way that that is possible. It's perfectly plausible that two different cache contexts return the exact same value. e.g.
#cache => ['keys' => ['foo', 'bar'], 'contexts' => ['color_of_the_day', 'user.favorite_color']] may very well result in a CID of foo:bar:blue:blue. How are you ever going to know which belongs to which?


#1:

  1. No, cache contexts are always a set.
  2. IDK, see above.
  3. IDK, see above.

AFAICT, it's safe to close this. Feel free to reopen if I was wrong.

Fabianx’s picture

Status: Closed (works as designed) » Active
Issue tags: +DX (Developer Experience)

And that was my exact use-case:

#cache => ['keys' => ['foo', 'bar'], 'contexts' => ['color_of_the_day', 'user.favorite_color']]

if cache contexts are standardized to return the value we can do:

foo:bar:color_of_the_day=blue:user.favorite_color=blue

OR

foo:bar:color_of_the_day.blue:user.favorite_color.blue

OR

foo:bar:color_of_the_day,blue:user.favorite_color,blue

OR

...

to help with debuggability instead of every cache context having to take care of that (and some do, others don't).

At least looking at DB tables.

r.* or theme.bartik was always nicely visible of where it came from while for 'blue' it would not be ...

But adding:

theme=[theme] we now would end up with:

theme=theme.bartik, which does not hurt, but is a little redundant.

Does that make my intent more clear?

Wim Leers’s picture

Title: Cache Contexts do not just return the values from getContext(), this can be confusing » When mapping cache contexts to cache keys, include the cache context ID for easier debugging
Assigned: Unassigned » Wim Leers
Issue summary: View changes

Yes, that hugely clarifies things.

Will post a patch tomorrow

Wim Leers’s picture

Assigned: Wim Leers » Unassigned
Status: Active » Needs review
FileSize
5.76 KB

Unit tests pass, a targeted selection of integration tests pass. But quite possibly there will still be some failures. Let's see what testbot has to say!

Fabianx’s picture

Looks great to me. Lets ensure using a database inspector does show those [] cases and that we don't need additional escaping, when using e.g. a WHERE query, besides that:

Great idea with the [token]=value :)!

Wim Leers’s picture

Lets ensure using a database inspector does show those [] cases and that we don't need additional escaping

That's indeed a boon for DX. Manually checked, and confirmed that this works without any nasty surprises.

Status: Needs review » Needs work

The last submitted patch, 5: 2430397-5.patch, failed testing.

Wim Leers’s picture

Status: Needs work » Needs review
FAILED: [[SimpleTest]]: [PHP 5.4 MySQL] Setup environment: failed to clear checkout directory.

Testbot, you're really driving me insane.

Wim Leers queued 5: 2430397-5.patch for re-testing.

Status: Needs review » Needs work

The last submitted patch, 5: 2430397-5.patch, failed testing.

Wim Leers’s picture

Status: Needs work » Needs review

FAILED: [[SimpleTest]]: [PHP 5.4 MySQL] Setup environment: failed to clear checkout directory.

Re-testing again.

Wim Leers queued 5: 2430397-5.patch for re-testing.

Status: Needs review » Needs work

The last submitted patch, 5: 2430397-5.patch, failed testing.

Status: Needs work » Needs review

Fabianx queued 5: 2430397-5.patch for re-testing.

Status: Needs review » Needs work

The last submitted patch, 5: 2430397-5.patch, failed testing.

Status: Needs work » Needs review

Fabianx queued 5: 2430397-5.patch for re-testing.

Status: Needs review » Needs work

The last submitted patch, 5: 2430397-5.patch, failed testing.

Wim Leers’s picture

Assigned: Unassigned » Wim Leers

Ahh, finally sane failures :) Fixing!

Wim Leers’s picture

Assigned: Wim Leers » Unassigned
Status: Needs work » Needs review
FileSize
10.48 KB
4.73 KB

Should be green & RTBC'able.

Fabianx’s picture

Status: Needs review » Reviewed & tested by the community

LOVE IT!

The last interdiff already shows why this is really awesome! :)

alexpott’s picture

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

This issue is a task so we need to outline how it fits within the allowable Drupal 8 beta criteria. Can someone add Drupal 8 beta phase evaluation template to the issue summary.

Wim Leers’s picture

Issue summary: View changes
Status: Needs work » Reviewed & tested by the community
Issue tags: -Needs beta evaluation

Beta evaluation added. Sorry for not having done it already!

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 20: 2430397-20.patch, failed testing.

Wim Leers’s picture

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

Rebased. No conflicts.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 25: 2430397-25.patch, failed testing.

Wim Leers’s picture

Status: Needs work » Reviewed & tested by the community
FileSize
10.49 KB
alexpott’s picture

Status: Reviewed & tested by the community » Needs work

The change makes a lot of sense but the beta evaluation needs work since DX is not a permitted reason for a change.

Fabianx’s picture

Category: Task » Bug report
Issue summary: View changes
Status: Needs work » Reviewed & tested by the community

Wanted to re-classify as bug, even if rare, it is possible for a cache context to return the same value and then it could happen that the wrong item is retrieved, which could lead to cache mismatch, because it depends on the order. (it is a rare occurence, but similar to config's getCacheSuffix()).

But I can't think of how to write the test coverage for that (and if ther really is a bug), but it reduces fragility in that it hardens the cache keys.

Fabianx’s picture

Category: Bug report » Task

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 27: 2430397-27.patch, failed testing.

yched’s picture

Well, it's not only about DX, right, but also site-builder understability / debuggability of what happens on the render cache ?
Also, disruption is null anyway ?

Anyway, big +1 on that change :-)

Wim Leers’s picture

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

This is a straight reroll.


Well, it's not only about DX, right, but also site-builder understability / debuggability of what happens on the render cache ?

I'd argue that's DX? :) How many site builders are going to analyze the render cache? Aren't they developers at that point?

Also, disruption is null anyway ?

Yes, with the exception if very very minor disruption in tests (as the patch shows, and the beta evaluation indicates).

Anyway, big +1 on that change :-)

Yay :)

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 33: 2430397-33.patch, failed testing.

Fabianx’s picture

Issue tags: +Needs reroll
Wim Leers’s picture

Status: Needs work » Needs review
Issue tags: -Needs reroll
FileSize
7.15 KB

#2493033: Make 'user.permissions' a required cache context landed yesterday and caused the conflicts resulting in the test failure.

But! It actually fixed things in a generic way, so the patch here simply becomes smaller :)

Fabianx’s picture

Status: Needs review » Reviewed & tested by the community

Back to RTBC

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 36: 2430397-36.patch, failed testing.

Wim Leers’s picture

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

Conflicted with #2351015: URL generation does not bubble cache contexts, which landed yesterday. Easy conflict resolution.

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed ba1b14e and pushed to 8.0.x. Thanks!

Thanks for adding the beta evaluation.

  • alexpott committed ba1b14e on 8.0.x
    Issue #2430397 by Wim Leers, Fabianx: When mapping cache contexts to...
Wim Leers’s picture

Status: Fixed » Closed (fixed)

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

Josh Waihi’s picture

/**
   * {@inheritdoc}
   */
  public function getContext($role = NULL) {
    // User 1 does not actually have any special behavior for roles; this is
    // added as additional security and backwards compatibility protection for
    // SA-CORE-2015-002.
    // @todo Remove in Drupal 9.0.0.
    if ($this->user->id() == 1) {
      return 'is-super-user';
    }
    if ($role === NULL) {
      return implode(',', $this->user->getRoles());
    }
    else {
      return (in_array($role, $this->user->getRoles()) ? '0' : '1');
    }
  }

Is this function really suppose to return a 0 if $role is in the user roles? Because it produces stranges things like user.roles:authenticated=1 for anonymous pages.