After #2753667: Improve Views cache plugin(s) and their cache metadata we have a search-api-specific views cache plugin that uses a search_api_list:[index] cache tag for invalidation. When this cache plugin is active, that tag helps invalidate the cached views data and bubbles-up to help with invalidation on page-level caching (internal and dynamic page caches). This is great.
However it may be best practice to disable views caching for certain search-api DB backends, such as solr. In this case the best choice would be the "None" views cache plugin, which sets no additional cache tags and sets a max-age of 0 to disable caching. The problem here is that the internal page cache ignores max-age and depends exclusively on tags for invalidation. As search api does not seem to add any content or index-specific tags to views output by default some views can end up in the internal page cache with no useful invalidation criteria, leading to permanently stale data. I assume this is a fairly common problem given that the internal page cache is enabled by default.
Perhaps it would be useful to add the search_api_list:[index] cache tag to views output unconditionally? It would appear that "standard" content views do something like this by always adding the node_list tag independent of the views cache plugin. This could allow for some "fallback" invalidation criteria that would otherwise have no impact for any caching layers that do respect a max-age setting of 0. This would of course not help with more complex caching situations that may simply be incompatible with the internal page cache (like asynchronous indexing in solr) but it could help produce more expected caching behavior for many other cases.
I suppose that this issue is tangled up in many other layers outside of search API (e.g #2499321 and #2352009), so this may not be nearly as straightforward as I think.
| Comment | File | Size | Author |
|---|---|---|---|
| #20 | 2905497-20--views_internal_page_cache_compat.patch | 3.89 KB | drunken monkey |
Comments
Comment #2
drunken monkeyOh god, is there never an end to this nightmare? Caching has practically become the new Views at this point …
I'm not sure what to do here, I have to admit. I'm long past understanding the caching layer. Your proposal does seem reasonable – if we can't bring the internal page cache to not cache our search results at all, then we should at least bring it to clear them at some point. And the
search_api_list:[index]seems the way to do that.However, I'd really appreciate some more input here from people who work with the cache layer before deciding anything here, lest I have to revert the whole thing a few weeks later.
Comment #3
borisson_I'm not sure if that's the best way to fix this issue. But it sounds like a good idea, can we write a test for this?
Comment #4
zerolab commentedWe have experienced search results cache issues on our project too. Pinged Wim Leers on Twitter - https://twitter.com/zerolab/status/905071088002093057. You definitely want input from either Wim Leers or FabianX on this.
Comment #5
webflo commentedI did some debugging on this matter today.
The "None" cache plugin returns the list cache tag by default. The information is derived from
::getEntityTableInfo(@see \Drupal\views\Plugin\views\cache\CachePluginBase::getCacheTags). These cache tags are crucial for cache invalidation and bubble all cache tags onto the page cache level.Search API Views have no
::getEntityTableInfo. The return values from this function is empty. Therefor no cache tags and page cache never invalidates.There are a few possible solutions
::getEntityTableInfowith the required info, even if the base table is not a real table.Comment #6
webflo commentedImplementation of #5-2. Not sure if this is the right thing to do. I thought we could get rid of SearchApiTagCache and SearchApiTimeCache because the Query class takes care the cache tags, but the logic in SearchApiCachePluginTrait is quite complex. Maybe #5-1 is better after all.
Comment #7
rjacobs commentedOut of curiosity how is this handled for normal entity (e.g. node) views? As far as I can tell the "node_list" tag is always added/bubbled-up independent of any views caching plugin options. I'm assuming that the entity API is dealing with this in some generic way that integrates with views? If so I certainly understand if those concepts are not reusable, I just can't find specific applications of the *_list tags outside of cache invalidation processes and core search plugins.
Comment #8
webflo commented@rjacobs The "None" Cache Plugins adds the list tag to the view.
Comment #9
webflo commentedHere is the None cache Plugin for Search API.
Comment #10
borisson_/s/tag-based/none/
I don't think these docs are correct.
This doesn't seem correct either, it should be: Never cache any of the results.
This implementation looks solid though, I think doing this is a good idea. It's probably also the most simple implementation we can do.
Comment #11
rjacobs commentedAh, ok. I guess
\Drupal\views\Plugin\views\cacheCachePluginBase::getCacheTags()must be taking care of that. I see the call to getListCacheTags() in there. That helps clear things up for me, thanks.So since the core "None" cache plugin is aggregating tags, then yes, the "None (Search API)" plugin concept seems like the logical analogous solution here. It looks like the core "Tag Based" plugin is always the default when a new view is created, so site builders need to take an extra step of switching this value to get predictable cache handling no matter what. They just need to be sure to choose the correct "None" option. All things considered that seems reasonable.
As @borisson_ noted in #10 it looks like the help text was copy-pasted from SearchApiTagCache. Perhaps something along the these lines would be more targeted?:
"No caching of Views data. This setting also helps enforce invalidation within caching layers external to views in a way that is compatible with search api. This is an appropriate choice for search api views that want to bypass views caching by still maintain basic compatibility with any page-level caches that may be enabled."
It's certainly tricky to explain what's going on here in a concise way.
Comment #12
drunken monkeyI don't think there's a need to be so specific and verbose here. "No caching of Views data." will be all the user is interested in.
We should just make sure to disable the normal "None" cache plugin for Search API views, as we already do for the others. (Though I think that hasn't really been working completely, at least lately?)
I think, though, that I actually like the approach of #6 better: just set the cache tag on the query. If that works the same, it seems like a simpler approach than even overriding the "None" cache plugin. It looks like that might even allow us to remove our
SearchApiTagCache::getCacheTags()override? Or am I mistaken? (And, might we need to instead overrideSearchApiTimeCache::getCacheTags()to remove that tag again? Seems like Core's time-based cache also has the normal entity list cache tags attached, so actually it seems that plugin would need to be fixed in any case, too.)Comment #13
idebr commented#2824640: Views cached results are not taking full cacheability metadata into account introduced cache tags in the Search API Query, making this change redundant.
Comment #14
drunken monkeyJust this line, or the whole issue?
Comment #15
idebr commentedMy apologies for the comment in #13. I scanned the related issue without checking for the implementation of cache tags. In fact, there is explicit test coverage that shows the index list tag is missing for the 'None' plugin in ViewsDisplayCachingTest.
I agree with #12 that adding the list tag on the query is the preferred approach here, since it saves us the headache of adding an upgrade path for existing Search API views that use the existing None plugin.
Attached patch implements the following changes compared to #6:
ViewsDisplayCachingTest still passes without changes to the Search API Time cache plugin, so it appears it is not necessary to remove the list tag again as suggested in #12
Comment #17
idebr commentedAttached patch implements the following changes:
Comment #19
lendudeTested on our project and the correct search_api_list cache tag now gets added to all pages that show Search API generated Views.
Comment #20
drunken monkeyThanks, great work! Also thanks @Lendude for testing.
Just two tiny corrections – if the test bot is happy with those then I’ll commit.
Comment #22
drunken monkeyCommitted.
Thanks a lot again, everyone!