Search code examples
cachingservicestackservicestack.redis

ServiceStack Caching


I am looking to cache an expensive query using ServiceStack.

My idea is as follows

Step 1: Cache entire database view to Redis which expires after a day

Step 2: When client calls API route "/cached/balances/{Date}", the service only returns a subset of the cached database view.

To implement this, I am using

Request and Response Models

[Route("/balances", "GET", Notes = "A call to Db which extracts the entire Db balance view")]
public class GetBalances : IReturn<GetBalancesResponse>
{

}

[Route("/cached/balances/{Date}", "GET", Notes = "Gets a subsection of cached balanced")]
public class GetCachedBalances : IReturn<GetBalancesResponse>
{
     public int Date { get; set;} 
     public int? EntityId { get; set;} 
}

public class GetBalancesResponse
{
    public List<BalanceView> Result { get; set; }
}

Service Interface

 public object Any(GetBalances request)
 {
    var balances = Db.Select<BalanceView>();
    return new GetBalancesResponse {Result = balances };
 }

 public object Any(GetCachedBalances request)
 {
       GetBalances balancesRequest = request.ConvertTo<GetBalances>();

     // get the cached response
      var allBalances = (CompressedResult)base.Request.ToOptimizedResultUsingCache(
                this.CacheClient, "urn:balances", () => {
                    var service = this.ResolveService<BalanceServices>();
                    return (GetBalancesResponse)service.Any(balanceRequest);
                });

            // filter the results -> this does not work!
            var filterBalances = response.Response.ConvertTo<GetBalancesResponse>().Result.Where(Ar => Ar.Date == request.Date && (Ar.EntityId == request.EntityId || request.EntityId == null)); 

    return new GetBalancesResponse {Result = filteredBalances};
 }

The filtering of balances does not work as I cannot seem to convert the compressed result to the ResponseDto.


Solution

  • I may have an answer to my own question.

    The ServiceInterface GetCachedBalances can be filtered as per below

      public object Any(GetCachedBalances request)
      {
         GetBalances balancesRequest = request.ConvertTo<GetBalances>();
    
         // cache everything
         var filteredCachedResponse = (CompressedResult)base.Request.ToOptimizedResultUsingCache(
                this.CacheClient, "urn:balances", () => {
                    var service = this.ResolveService<BalanceServices>();
                    return ((GetBalancesResponse)service.Any(balanceRequest)).Result.Where(Ar => Ar.Date == request.Date && (Ar.EntityId == request.EntityId || request.EntityId == null));
                });
    
         // filter cached response
         var filteredResponse = base.Cache.Get<GetBalanceResponse>("urn:balances").
                        Result.Where(Ar => Ar.Date == request.Date && (Ar.EntityId == request.EntityId || request.EntityId == null));
    
          return filteredResponse;
       }