Wednesday 21 October 2015

CacheCow: Invalidate cache for different resource routing

CacheCow is a great tool we can use In ASP.Net WebApi projects to maintain cache with SQL Server persistence.  You can view how to implement CacheCow with SQL Server in this post.

However, there is a problem in the default implementation of invalidating cache if we have different kind of GET requests.

eg : Assume our GET request is http://myhost/api/customers. So a POST, PUT,PATCH or DELETE requests for same request http://myhost/api/customers would invalidate the cache.

But what if we have different formations of GET requests.

Eg :

GET : http://myhost/api/customers_country/SriLanka

GET : http://myhost/api/customers_city/Colombo

So any update request to  http://myhost/api/customers would not invalidate cache of  aforementioned GET requests.

Following is a very simple way of invalidate cache based on the root routing value.

I'm using hard coded sql here because this is a separate entity to my other business entities.


 
 public class CacheCowHackService : ICacheCowHackService
    {
        public int InvalidateEntityCache(string parentPattern)
        {
            int noOfRowDeleted;
            using (var ctx = new MyContext())
            {
                //Delete command
                noOfRowDeleted = ctx.Database.ExecuteSqlCommand(
                    $"delete from CacheState where RoutePattern LIKE '%{parentPattern}%'");

            }
            return noOfRowDeleted;
        }
    }

What all we need to do is call this method when ever there is an update to a resource.
 
public VehicleViewModel Create(VehicleViewModel model)
        {
            var id = Guid.NewGuid();
            model.Id = id;

            using (var transactionScope = new TransactionScope())
            {
                ......
                var entity = VehicleMap.ModelToEntity(model);
               ....
                _vehicleService.Add(entity);
                entity = _vehicleService.GetSingle(x => x.Id == id);
                model = VehicleMap.EntityToModel(entity);
                CacheCowHack.InvalidateEntityCache(Const.VehicleRoute);
                transactionScope.Complete();
                return model;
            }
        }


No comments:

Post a Comment