dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.43k stars 10.02k forks source link

Cache invalidation #2622

Open aspnet-hello opened 6 years ago

aspnet-hello commented 6 years ago

From @JunTaoLuo on Thursday, September 15, 2016 2:15:48 PM

Currently we only set the absolute timeouts for cache entries. There is no mechanism to explicitly invalidate a cache entry before expiry. Also, how would applications/users interact with this feature?

Note that invalidation is required by the RFC for unsafe methods, e.g. a successful PUT should invalidate any previous cached resources at the same URI.

Copied from original issue: aspnet/ResponseCaching#38

aspnet-hello commented 6 years ago

From @refactorthis on Friday, March 31, 2017 9:38:12 AM

endpoints that mutate state should invalidate the previous cached item by default as you mention. It would also be beneficial to have the ability to inject a service that allows invalidating cached items on demand. For example an event received over a bus may mutate the objects state which would require invalidation. This may however be out of scope and better handled by abstracting the cache to a different layer?

aspnet-hello commented 6 years ago

From @muratg on Thursday, May 25, 2017 3:42:26 PM

@glennc If we want to do this in the future, we should get together and agree on a design.

aspnet-hello commented 6 years ago

From @justintubbs on Wednesday, August 9, 2017 12:19:14 PM

Any update on this? Cache invalidation would be a killer feature both for REST API interactions, but also SignalR or other types of event buffers/message queues that cause the underlying data to mutate.

xantari commented 4 years ago

How is this not solved yet? This is a common use case:

  1. Server caches result of page
  2. We receive a cache eviction event notification from a headless CMS
  3. We should be able to clear the response output cache and load the new CMS data!
mjrousos commented 4 years ago

@muratg @glennc, just checking in. Any updates on this one? I'm working with a customer whose scenario sounds similar to @xantari's. Being able to invalidate items from the cache would make response caching a lot more useful in that scenario.

JunTaoLuo commented 3 years ago

This is something we'd want to keep in mind when designing Output Cache: https://github.com/dotnet/aspnetcore/issues/2627.

xantari commented 3 years ago

Our current workaround to this limitation so that we can still have the extreme performance that response output caching provides when surfacing our headless CMS data is that we have set our response output cache to 2 hours.

This poses several problems for our content management system (CMS) editors however. It has the following ramifications:

  1. Edits to pages in the headless CMS are not reflected to end users for up to 2 hours as we can't immediately evict the changed pages.
  2. We can't cache the page indefinitely which would increase server performance. Instead we load it every 2 hours as it's the only way to render page changes due to the inability to evict items from the response output cache.

Ideally this issue would be solved and we would just set the response output cache to something like 24 or 48 hours and our servers would just be sitting idle since the servers wouldn't have to think about rendering new pages anymore unless it receives a cache eviction notification that tells the system it needs to evict the response output cache and the next hit to that page would go through the normal MVC rendering process.

catalin-ifacts commented 3 years ago

OMG, I am stunned. No ResponseCache invalidation în .NET Core? November 2021 here..... !@#$@!#

oezoezoe commented 2 years ago

Below a simplefied workaround we use:

[ApiController]
    [Route("[controller]")]
    public class TimeController : ControllerBase
    {
        private int _version = 0;

        [HttpGet]
        public IActionResult Get()
        {
            return RedirectToAction("GetInternal", new { version = _version });
        }

        [HttpGet("{version:int}")]
        [ApiExplorerSettings(IgnoreApi = true)]
        [ResponseCache(Duration = 3600, VaryByQueryKeys = new[] { "version" })]
        public async Task<IActionResult> GetInternal(int version)
        {
            await Task.Delay(2000);
            return Ok(DateTime.Now);
        }

        [HttpPut]
        public IActionResult ClearCache()
        {
            _version++;
            return Ok();
        }
    }

The consumer can use the normal get method and via a different call the version gets updated and thereby invalidating the old version.

xantari commented 1 year ago

Not sure, but is this now solved via #27387 in .net 7?