Caching dependent on CMS pagetypes / content

ZZ
ZZ
Vote:
 

HI,

Is it possible to make caching dependent on single or multiple pagetypes. Or may be on whole CMS, that's if any page, block or asset changes, then the caching should be reset.

Right now I am caching for few minutes, but if the caching could be dependent on content change then I would probably be able to cache for a longer period.

The method which I am using ->

var result = await _synchronizedObjectInstanceCache.ReadThrough(
                cacheKey, async () => await CreateObject(currentPage),
                x => new CacheEvictionPolicy(
                    TimeSpan.FromMinutes(CachingInMinutes),
                    CacheTimeoutType.Absolute,
                    Enumerable.Empty<string>(),
                    new[] { _contentCacheKeyCreator.RootKeyName }),
                ReadStrategy.Wait);

  

#257225
Jun 28, 2021 7:57
Vote:
 

You cache based upon the content dependencies, it's not per page type it's more of a tree of content references

For example if you were caching say a view model on a page but that viewmodel was loading data from another page which was linked by a PageReference on that page type. You'd cache against both of those content references.

Here's a method I've got it a help that allows you to cache on a set of ContentReferences

        /// <summary>
        /// Gets or inserts an item in the cache based upon either itself as an Episerver content chance dependency or a number of others.
        /// </summary>
        /// <typeparam name="T">The type of object</typeparam>
        /// <param name="key">The key.</param>
        /// <param name="readValue">The read value.</param>
        /// <param name="keyDependency">The key dependency.</param>
        /// <param name="dependencies">The dependencies.</param>
        /// <param name="cacheKeyKeyMode">The cache mode.</param>
        /// <returns></returns>
        public T GetOrInsert<T>(string key, Func<T> readValue, ContentReference keyDependency, IList<ContentReference> dependencies = null, CacheKeyMode cacheKeyKeyMode = CacheKeyMode.BasedOnAllDependencies) where T : class
        {
            var cacheKey = GetCacheKey(key, keyDependency, dependencies);
            var keyDependencyArray = new[] {_contentCacheKeyCreator.CreateCommonCacheKey(keyDependency)};
            var evictionPolicy = dependencies != null && dependencies.Count > 0 ?
                new CacheEvictionPolicy(dependencies.Select(r => _contentCacheKeyCreator.CreateCommonCacheKey(r)).Union(keyDependencyArray)) : 
                new CacheEvictionPolicy(keyDependencyArray);
            return _synchronizedObjectInstanceCache.ReadThrough(cacheKey, readValue, x => evictionPolicy, ReadStrategy.Wait);
        }
        /// <summary>
        /// Gets the cache key for permutations as required.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="keyDependency">The key dependency.</param>
        /// <param name="dependencies">The dependencies.</param>
        /// <param name="cacheKeyKeyMode">The cache key key mode.</param>
        /// <returns>The cache key</returns>
        private string GetCacheKey(string key, ContentReference keyDependency, IList<ContentReference> dependencies, CacheKeyMode cacheKeyKeyMode = CacheKeyMode.BasedOnAllDependencies)
        {
            return cacheKeyKeyMode == CacheKeyMode.BasedOnAllDependencies && dependencies != null && dependencies.Count > 0 ?
                GetCacheKey(key, dependencies.Union(new[] { keyDependency }).ToList()) :
                GetCacheKey(key, keyDependency);
        }
#257230
Edited, Jun 28, 2021 10:31
Scott Reed - Jun 28, 2021 10:33
This is a good article on how the keys work for content dependencies https://stefanolsen.com/posts/caching-custom-data-that-depends-on-episerver-content/
ZZ
Vote:
 

The issue I am facing is that I don't have content references. Its more of search result. Thats why I am thinking to cache the result object until new pages of that types is created or existing get change. 


The other way around could be dependent on CMS so any change any where page / blok , asset could reset the caching. 


Thanks for your input 

#257234
Jun 28, 2021 10:48
Vote:
 

Why don't you have content references. If you're using anything that searches Episerver content you should have? Or if you're custom indexing some content in Search & Navigation (find) you could store an extra field.

You can hook in to the ContentEvents system and manually clear your cache keys but I'd suggest if you do anything like that you work out how often the cache invalidation occurs as sometimes in those processes if it's too much then there's little point in the caching process in the first place.

#257235
Jun 28, 2021 10:58
ZZ
Vote:
 

We are not using EPiServer find. We are having our custom search engine.  

Is there any caching method the would reset caching if any page / blok modifiet, added etc. ? 

#257236
Jun 28, 2021 11:05
Vote:
 

Surely you have some control over the indexing solution? If you are searching against Episerver you'd expect that to be against IContent stored in the database therefore do you not indexing the ContentReferences, can you not change it?

Regarding "Is there any caching method the would reset caching if any page / blok modifiet, added etc. ?" That's what I mentioned in the second line of my last comment. Just manually evict the cached item based on the key using the IContentEvents instance and a InitalizationModule.

#257238
Jun 28, 2021 12:01
ZZ
Vote:
 

No, its searching against URls. And to change it is not approrpiate for just caching of a single searchresult. 

I was just clarifying if there is any built-in method that will invalidate caching if something changes in any page / block.

There is a "RootKeyName" in IContentCacheKeyCreator interface. Could that be used for resetting the cache object ?instead of ContentEventSystem. 

#257241
Jun 28, 2021 12:32
Vote:
 

Okay sure, there's very little information you're giving so I'm just trying to help. Obviously not understanding the context of the search makes a big difference.

The root key is for the cache of the content items, if you clear it the cache for all items will be cleared. I'd just create your own unique key which could be anything and then just clear that key on any content change with the aforementioned IContentEvents system

#257243
Jun 28, 2021 12:42
ZZ
Vote:
 

Thanks for your input.

I understand it totally, its not easy to understand the context of search without the full picture. 

It makes sense to clear the cache with the mentioned IContentEvet system.

If I have few different viewmodel / search objects unrelated to each other, would it be best to have unique key for everyone ? because then I have to clear all the keys on ContentEvents system. 

A common key / rootkey would be easy to clear as a single key on Content change? 

#257244
Jun 28, 2021 12:53
ZZ
Vote:
 

Thanks for your input.

I understand it totally, its not easy to understand the context of search without the full picture. 

It makes sense to clear the cache with the mentioned IContentEvet system.

If I have few different viewmodel / search objects unrelated to each other, would it be best to have unique key for everyone ? because then I have to clear all the keys on ContentEvents system. 

A common key / rootkey would be easy to clear as a single key on Content change? 

#257245
Jun 28, 2021 12:53
Vote:
 

It's really completely up to you. If the dependencies for all of them are the same you can create a common key, there's only really a need to have separate ones if the dependencies are either different or you expect it could change in the future. 

#257246
Jun 28, 2021 13:05
ZZ
Vote:
 

Thank for your detailed replies. I will go with a common key that will act like a master key for most of the caching objects. The caching will be removed via IContentEventSystem by using our unique master key.

#258477
Jul 05, 2021 14:07
* 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.