Try our conversational search powered by Generative AI!

How to burst GetContentResult() cache?

Vote:
 

Currenlty, we are caching the query results for 2 hours using GetContentResult() and looking for a way to burst the GetContentResult() cache to fetch latest results.  
We are using EPiserver.CMS.FIND 13.2.6.

#263510
Edited, Sep 22, 2021 6:47
Vote:
 

Firstly I would not suggest using GetContentResult as this reloads data from the IContentRepository causing a database hit on each result. This affects performance and uses lots of resources.

You can read about it in my blog https://world.optimizely.com/blogs/scott-reed/dates/2019/3/episerver-find---performance-reloading-custom-data-and-getcontent-vs-getcontentresult/ 

You should just use the GetResult and use projections.

Caching wise if you use StaticallyCacheFor off the back of the search you can pass in a cache dependeny which you can invalidate. Read here https://world.optimizely.com/forum/developer-forum/Search/Thread-Container/2015/8/invalidate-cached-results-of-quotstaticallycacheforquot/ 

#263523
Edited, Sep 22, 2021 12:31
Gaurav Bhatia - Sep 23, 2021 10:57
Thanks Scott for your suggestion. I'll try to use GetResult wherever I can. But currently, we need to somehow burst GetContentResult() caching. Any idea how to burst?
The example (https://world.optimizely.com/forum/developer-forum/Search/Thread-Container/2015/8/invalidate-cached-results-of-quotstaticallycacheforquot/ ) you shared is having GetResult().
Scott Reed - Sep 23, 2021 11:13
That example is just there as nobody tends to use GetContentResult due to the issues I mentioned. StaticallyCacheFor comes before the GetResult / GetContentResult. StaticallyCacheFor is the standard way of caching your S&N queries so if you're not using that what are you using?
Scott Reed - Sep 23, 2021 11:14
As with all posts on here posting code is always a good idea. So I'd post an example of the code you're using
Gaurav Bhatia - Sep 23, 2021 12:16
Like mentioned in this article (https://vimvq1987.com/beware-of-getcontentresult/). We are using the StaticallyCacheFor with 10 min cache time in our query, but GetContentResult() 1 min default cache time is overriding the StaticallyCacheFor cache time and the query results are cached for just 1 min.
my query is something like this

var searchQuery = _searchClient.Search()
searchQuery = searchQuery .PublishedInLanguage(language)
.FilterOnReadAccess()
.StaticallyCacheFor(TimeSpan.FromMinutes(10))
IContentResult contentResult = searchQuery .GetContentResult()

My goal is to increase the FIND cache time to 2 hours and for that, I need to pass 2 hours time in the GetContentResult() method because currently, it's ignoring StaticallyCacheFor time. I also need to make sure that whenever a page is published, it should burst the GetContentResult() cache and fetch the latest results.
I hope this is helpful.
Scott Reed - Sep 23, 2021 12:22
Firstly I'd say what is the specific use case that means you need to use GetContentResult() and not load the data directly from the index with GetResult()? Reflecting on the code and as talked about in Quan's post the .StaticallyCacheFor is overridden which means you can't pass in a cache dependency as talked about in the article I shared. So at the moment it's hard for you to achieve the burst caching. I don't know how at least. But I know if it was me I'd swap out to GetResult() where you don't have the issue and can control a cache dependency and get the benefit of not calling the DB to reload content which is bad.
Vote:
 

@Scott: I agree on advise to go with GetResult and projection, since you then also limit data sent over the wire. But... this phase: "I would not suggest using GetContentResult as this reloads data from the IContentRepository causing a database hit on each result. This affects performance and uses lots of resources."

Optimizely CMS automatically caches objects that are requested from the API, such as content instances through IContentRepository. The object cache is an in-memory cache and stores only read-only objects for better performance. So the database will not be hit on each result.

#264227
Edited, Sep 30, 2021 18:17
Scott Reed - Sep 30, 2021 18:37
I think you've misunderstood what I was highlighting. I'm not talking about the memory caching I'm well aware of that as we've been discussing in the thread above, I'm talking about when there's either a hit or the cache has expired. In those circumstances there's a database load. I would still always have the memory cache via StaticallyCacheFor on top of using projections and loading data directly from the index.
Vote:
 

It should automatically invalidate the cache (I guess what you meant for "burst") if you publish a content. Did you check if the newly published content gets indexed properly?

#264396
Oct 04, 2021 8:57
Gaurav Bhatia - Oct 04, 2021 9:14
Yes, we checked, but still getting cache results. It's not invalidating the cache.
Quan Mai - Oct 04, 2021 9:22
Did you test on same machine, or in different ones?
Gaurav Bhatia - Oct 04, 2021 9:23
Same machine with different browsers
Vote:
 

Hmm, It is more complicated than I thought. Apparently GetContentResult caches the search result with the dependency to IContentCacheKeyCreator.RootKeyName. So it means it is most likely not properly invalidated when you publish a content. You can, in theory, remove that cache key to invalidate the search result cache, but it also invalidates all content cache, so that is really a nuke option. Hmm, I will need to talk with Search team about this 

#264404
Oct 04, 2021 10:34
Scott Reed - Oct 04, 2021 10:44
indeed, this was one of the reasons I suggested rewriting to GetResult as I couldn't see a way of invalidating specific cache items with the fact that it's just the rootkey. And as the GetContentResult is just a wrapper on top of GetResult that reloads data from via IContentRespository I felt it would be an easy switch.
Vote:
 

@scott : I am trying to add cacheDependency in StaticallyCacheFor() as suggested in your blog, and then invalidate it on publish event of a page, but cache is not getting stored in HttpRuntimeCache. Hence I am unable to invalidate it as well. Below is the code -

var searchQuery = _searchClient.Search()
searchQuery = searchQuery .PublishedInLanguage(language)
.FilterOnReadAccess()

var cacheDependency = new CacheDependency(null, new[] { CacheKeys.searchKey })
var queryResults = searchQuery .StaticallyCacheFor(TimeSpan.FromMinutes(5), cacheDependency) .GetResult()
var keyValue= HttpRuntime .Cache .Get(CacheKeys.searchKey)

keyValue is coming null, and hence not getting removed when I try this on publish event of the page -

HttpRuntime.Cache.Remove(CacheKeys.searchKey);

Is there anything else that needs to be added? I am currently using FIND v 13.2.6.
Any suggestions would be helpful. Thanks!

#264771
Edited, Oct 08, 2021 14:39
Priyanka - Oct 11, 2021 10:41
Update: I found that we need to insert the key first in cache, if it doesn't exists. Then only, cacheDependency will treat it as an existing cache Key. Reference - https://stackoverflow.com/questions/4271235/asp-net-cachedependency-object-question
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.