Comments

xjm’s picture

Issue tags: +beta blocker

Beta blocker as a blocker for #2151459: Enable node render caching.

amateescu’s picture

Status: Active » Needs review
StatusFileSize
new2.92 KB

This should do it.

berdir’s picture

This just adds the raw number, could this potentially conflict with other similar things? Should the cache key be something like "comment-pager-$page" instead?

amateescu’s picture

It cannot confict with other things because these keys are imploded with ':' to form the cache id. I guess adding 'comment-pager-' before the number would be just for cosmetic purposes, but we can do it if you want :)

berdir’s picture

Yes, but the key is added conditionally. What if there's another numeric key after it that's conditional too? So you'd have ....:1:1:... and sometimes just ...:1:... and then it could be either of those and you'd have the same cache id?

Not very likely, but there have been crazier bugs :)

amateescu’s picture

StatusFileSize
new2.94 KB
new765 bytes

Hah, ok, colour me convinced.

wim leers’s picture

Issue tags: +Spark, +sprint
StatusFileSize
new4.59 KB
new2.73 KB

The one concern I have is that if people change the "Comments per page" setting, then the cache wouldn't be cleared. There are two potential solutions:

  1. Embed the number of comments per page in the cache key.
  2. Employ cache tags to ensure that when the "comments per page" setting is changed (for a given comment field instance — not everywhere!), the corresponding cache entries are deleted.

Option 1 seems the simplest and most efficient solution (per-comment field instance cache tags… that doesn't sound very efficient), so that's what I went with.
I ran into two problems when retrieving the per_page comment field instance setting:

  1. Getting the commented entity's bundle requires entity loading (see the first @todo I added)!
  2. Getting the commented entity's comment field name requires string parsing (see the second @todo I added).

Both could be solved by including the necessary data in the comment entity as additional properties. Are there reasons to not do that? Then CommentViewBuilder::getBuildDefaults() would become simple again.
So the current patch needs refinement, but I believe the logical changes are sound.

Note that this also means that we must adjust the cache keys even if there isn't any ?page=X URL query, because if the number of comments per page is changed, then "page zero" (for which there would not be any comment pager-related identifier in the cache keys/ID) won't be updated.
(This also shows how Berdir's #5 remark was very important — we could've ended up with two numeric keys just for comments, yet other modules might contribute to it too! Any externally added values to cache keys should be uniquely identified, otherwise they may be misinterpreted.)

Finally: is test coverage a necessity or a nice-to-have?

amateescu’s picture

Wow, overengineering much? :)

Option 1 can lead to too many (potentially stale) cache entries. And I don't understand what's the deal with "per-comment field instance cache tags… that doesn't sound very efficient" for option 2.

There are at least a couple comment field instance settings that can affect the render cache, not just 'comments per page': threading, possibly 'allow comment title'.

So the simplest solution seems to be to invalidate the render cache of all entities of the bundle(s) where the comment field instance is attached.

That being said, I see now that I was terribly wrong in my initial approach. CommentViewBuilder doesn't have anything to do with this, the extra cache key needs to be added to the 'parent' entity, the one that contains the comments, not to the comments themselves.

wim leers’s picture

I don't see how this is overengineering? This is about correctness. The code seems overengineered for sure, but that's because most necessary metadata is missing.

You're right though that what I proposed still misses to react to other comment settings changes :/ And that's when I realized I've been incredibly DUMB for not seeing that the $entity_type . '_view' cache tag is already taking care of all this :/ I'm just overcomplicating things. I guess that's what you meant, then?

So #6 was indeed already all we needed to add. Except that it's indeed appending its cache key to the wrong entity. I'm working on fixing that.

amateescu’s picture

Yeah, I guess overcomplicating would've been a better term :/

wim leers’s picture

StatusFileSize
new1.22 KB
new4.26 KB

The solution is simple and elegant :)

Multiple comment field pagers hell :)

Sadly, it's complicated by the fact that #731724: Convert comment settings into a field to make them work with CMI and non-node entities made it possible to have multiple comment fields per entity type… yet it failed to update the pager to ensure each comment then has its unique pager. That may seem like an exotic edge case, but without unique pagers, we cannot update the render cache key correctly either! Sadly, that in turn seems to require pretty extensive changes to all of Drupal core's pager logic contained in pager.inc, which only allows one to assign a numeric identifier to a pager, to allow for multiple pagers on a page. But that's problematic too, because it makes it impossible (AFAICT) for us to figure out which pager belongs to which comments reliably.
So, the current sad reality is that the one ?page=X query will control all comment pagers simultaneously. And if one set of comments requires e.g. 2 pages and the other requires 5 pages… then you'll only be able to view 2 pages of either set of comments!
In other words: pager handling in general looks like it needs to be refactored. But that's obviously out of scope.
So, for dealing with all that, I opened a new issue at #2155387: Multiple comment fields per entity are supported, but break horribly when they need pagers.

andypost’s picture

I'd like to point about ability to have more formatters fo comment field...
Initially the idea was to move per-page and threading settings to formatter layer, and there should be a @todo in code, but I faced with paging issue and cache for each view mode so delayed this.

So probably moving this settings to formatter level should solve cache granularity but pagers still suck, #33809: Make pagers not suck

The last submitted patch, 11: 2151457-11.patch, failed testing.

wim leers’s picture

StatusFileSize
new1.25 KB
new807 bytes

Should be green now.

The last submitted patch, 14: 2151457-14.patch, failed testing.

berdir’s picture

+++ b/core/modules/comment/comment.module
@@ -454,6 +454,23 @@ function theme_comment_block($variables) {
+      }
+    }
...
+    $request = \Drupal::request();
+    foreach ($entity->getProperties() as $field_name => $field) {
+      // @todo Support multiple unique comment pagers once
+      //       https://drupal.org/node/2155387 lands.
+      if (isset($build[$field_name]) && $field->getFieldDefinition()->getType() === 'comment' && $request->query->has('page')) {
+        $build['#cache']['keys'][] = $field_name . '-pager-' . $request->query->get('page');

You should use foreach ($entity->getPropertyDefinitions() as $definition) here, getProperties() might have to instantiate a lot of field item and list classes, especially as you don't need $field at all. You could also use $definition->getName() instead of $field_name, not sure what's better readable.

amateescu’s picture

Should be green now.

Famous last words :D

berdir’s picture

Yes. *Never* write that in a comment. Even if you only made a single comment change, after that comment, the patch isn't going to apply anymore, the bot will explode or the world will end, but the patch will *not* be green :)

amateescu’s picture

We should create a text filter that replaces those phrases with something like "$user thinks this patch will be green. HAHA!" :P

wim leers’s picture

But but but … it was a legitimate failure and I fixed it locally! :(

Thanks for the advice, Berdir, I'll fix that :)

wim leers’s picture

Status: Needs review » Postponed
StatusFileSize
new1.81 KB
new1.65 KB
new1.12 KB

In this reroll:

  1. Addressed Berdir's feedback in #16.
  2. Now addressed the whole pager problem because larowlan is awesome: he fixed the whole pager problem last night already: #2155387: Multiple comment fields per entity are supported, but break horribly when they need pagers. larowlan++.
    I'm postponing this patch on that patch, though.
  3. In addressing that, I temporarily already enabled node/comment render caching, this caused me to find that when you update comment settings (e.g. enable/disable comment threading), render cached comments aren't being deleted (and CommentPagerTest detected that problem). A simple fix ensures that CommentViewBuilder::resetCache() gets called, which fixes the problem.
    (That change could either be part of this patch or the patch in #2151459: Enable node render caching, but I think we might as well fix it here.)
  4. #2031725: Move all entity display interfaces to the core component is the reason for the failed test, so rerolled against HEAD.
amateescu’s picture

Status: Postponed » Needs review

The last submitted patch, 21: 2151457-21.patch, failed testing.

The last submitted patch, 21: 2151457-21.patch, failed testing.

berdir’s picture

21: 2151457-21.patch queued for re-testing.

amateescu’s picture

Status: Needs review » Reviewed & tested by the community

I hope people won't frown upon rtbc-ing stuff I worked on, the patch cannot get any simpler :)

msonnabaum’s picture

Issue summary: View changes
Status: Reviewed & tested by the community » Needs review
StatusFileSize
new1.72 KB

Actually, I think it can get *slightly* simpler.

Using the request and calling pager_find_page was a bit awkward. This just uses get() with the default value instead of has().

msonnabaum’s picture

Issue summary: View changes
amateescu’s picture

Except that's not what we want..

\Drupal::request()->query->get('page') returns a string of page numbers imploded with "," if we have multiple pagers.

msonnabaum’s picture

Status: Needs review » Reviewed & tested by the community

Damn, you're right. So ignore #27, #21 is still RTBC

So I still think that's really unfortunate the way it is, but I don't see another way without moving the pager function into a new class where we can also do the has(), but that can easily be done in a followup.

webchick’s picture

Assigned: Unassigned » catch

This feels catch-ish to me.

catch’s picture

+++ b/core/modules/comment/comment.module
@@ -454,6 +457,24 @@ function theme_comment_block($variables) {
+      if (isset($build[$field_name]) && $definition->getType() === 'comment' && $request->query->has('page')) {

Could we put the $request->query->has('page') first? Then we can bail out before checking the property conditions if there isn't one.

catch’s picture

Assigned: catch » Unassigned
Status: Reviewed & tested by the community » Needs review
wim leers’s picture

Assigned: Unassigned » catch
Status: Needs review » Reviewed & tested by the community
StatusFileSize
new1.82 KB
new1.23 KB

Good point. I can move that condition even higher though! :)

Interdiff against #21.

catch’s picture

Status: Reviewed & tested by the community » Fixed

Committed/pushed to 8.x, thanks!

wim leers’s picture

Assigned: catch » wim leers
Issue tags: -sprint

Thanks!

Status: Fixed » Closed (fixed)

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