liubiao4123 / servicestack

Automatically exported from code.google.com/p/servicestack
0 stars 0 forks source link

Enable caching on a ServiceClientBase #33

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
I'm trying to implement transparent caching in my service client. In order to 
accomplish this, I've now duplicated the ServiceClientBase code, but I guess 
some extra extensibility could facilitate this better.

Only making ServiceClientBase.Send<TResponse>(object request) virtual would 
already suffice. In the overridden version, one could create a unique cache key 
for the request, and do the following:

public override TResponse Send<TResponse>(object request)
{
  var cacheKey = request.GetCacheKey();

  if (cache.Exists(cacheKey))
    return cache[cacheKey];

  var result = base.Send(request);

  cache[cacheKey] = result;
}

Btw, I'm using ICacheClient and it's such a breeze to switch between Redis, Xml 
files or even just memory in the blink of an eye :)

Original issue reported on code.google.com by GrimaceO...@gmail.com on 25 Aug 2010 at 8:03

GoogleCodeExporter commented 8 years ago
No problems, ServiceClientBase with virtual method attached.

Yeah ICacheClient was nice helped us seamlessly migrate to a different caching 
providers pretty easily as well.

If you're doing server-side caching you should check out 
'RequestContext.ToOptimizedResultUsingCache' as seen in:
http://code.google.com/p/servicestack/source/browse/trunk/ServiceStack.Examples/
ServiceStack.Examples.ServiceInterface/GetNorthwindCustomerOrdersCachedService.c
s
Basically writes the most optimal result (e.g. gzipped xml/json or serialized 
xml/json) which whenever a cache exists avoids any serialization.

If your doing caching using the ICacheClient you may want to check out 
CacheManager:
http://code.google.com/p/servicestack/source/browse/trunk/Common/ServiceStack.Co
mmon/ServiceStack.CacheAccess.Providers/CacheManager.cs

As it has a nice API that lets you do stuff like:

return cacheManager.Resolve(cacheKey, () => { 
  return base.Send<T>(request);
});

which will send and cache the result and return the cache result from then on.

- Demis

Original comment by demis.be...@gmail.com on 25 Aug 2010 at 8:29

Attachments:

GoogleCodeExporter commented 8 years ago
It's getting a bit boring, but thanks once again for etc...

Nice tip about the ToOptimizedResultUsingCache. That's really an elegant 
solution!

The more time I spend with ServiceStack, the more I'm fond of it's hidden gems, 
and the more I realize how difficult it is to convey that to others. Anyway, 
I'm glad you chose to make this an Open Source project. Thanks again.

Original comment by GrimaceO...@gmail.com on 25 Aug 2010 at 8:48

GoogleCodeExporter commented 8 years ago
Yeah no worries I glad you find it useful as well.

Send me a link if you ever get anything deployed on the Internet somewhere, its 
would be good to see what other people are doing with it.

Cheers,
Demis

Original comment by demis.be...@gmail.com on 25 Aug 2010 at 8:55

GoogleCodeExporter commented 8 years ago
There seems to be one issues when trying to combine the 
ServiceClientBase.SendRequest<T> with ICacheManager.Resolve<T>

The second one has a class restriction on the template parameter (and I think I 
know why).

I'm not yet sure how to solve that, but I was thinking along the lines of how 
you handle the QueryStringSerializer with statically initialized callbacks (you 
might want to patent that). Any thoughts about this?

Original comment by GrimaceO...@gmail.com on 25 Aug 2010 at 9:22

GoogleCodeExporter commented 8 years ago
Yeah that's the problem with cascading generic restrictions not mixing very 
well. Ultimately it's valid restriction as both methods should only be taking 
DTO's or POCO's anyway. 

A quick solution for you would be to add another method to your subclass with 
this restriction which will then happily call your base method that doesn't 
have one:

public TResponse CacheSend<TResponse>(object request)
    where TResponse : class 
{
    return base.Send<TResponse>(request);
}

Although its appropriate to include this restriction on IServiceClient (which 
will also fix this), it would likely be invasive and introduce compile-errors 
in other parts of ServiceStack including tests so will need to do an Audit of 
code before I can do this.

Original comment by demis.be...@gmail.com on 25 Aug 2010 at 9:39