The difference between a Memory Cache vs all other distributed caches is that they need to use serialization, so you need to ensure everything you’re trying to cache is serializable. Redis uses JSON, so check it can be de/serialized with JSON.
What are these API wrappers for? Don’t serialize the JSON yourself, it should be up to the cache provider what it uses to serialize the body. Your set is going to be double encoding a JSON string.
What’s a complete stand-alone example of cache set/get entry that fails when using the ICacheClient APIs directly? (i.e. instead of your wrappers).
You are right, then the only problem was to use Cache.Replace instead of Cache.Set.
I think Memory and Redis clients have different behavior for Cache.Replace().
So I already removed my wrappers and everything it’s working fine.
Moving on, when I was using Memory Cache I used to have a static field in my base class: BaseLogic to hold a reference to ICacheClient.
After yesterday’s refactoring I turned this static field to be an instance field (of course I had to refactor in cascade other things).
I would like to get this field back to static, would you recommend to handle Cache like this? I am not sure it could work, maybe connections to Redis are disposed after time?
The reason I want it to be static is because sometimes I cannot inyect my BaseLogic dependencies because of reference cycle, so with a static Cache I would be still able to clear cache from a static method.
The registered ICacheClient is already accessible statically via the singleton HostContext.Cache, should you need to, you can also access the Memory Cache with HostContext.LocalCache.
Note: it’s only possible to access the Cache statically because it supports registration as a singleton, e,g. you wouldn’t be able to access any transient dependencies statically.
Then, after loop, I am using Debug Console to retrieve Cache.GetKeysStartingWith(CACHE_GET_PAGED()), which at this point should be empty but get same result as above.
using System;
using ServiceStack;
using ServiceStack.Text;
using ServiceStack.Redis;
using ServiceStack.DataAnnotations;
var redisManager = new RedisManagerPool("localhost:6379");
var redis = redisManager.GetClient();
redis.FlushAll();
var cache = redisManager.GetCacheClient();
cache.Set("siafracc_QUERY_Deposit__Query_Deposit_10_1", "A");
cache.Set("siafracc_QUERY_Deposit__0_1___CUSTOM", "A");
var keys = cache.GetKeysStartingWith("siafracc_QUERY_Deposit");
cache.RemoveAll(keys);
var newKeys = cache.GetKeysStartingWith("siafracc_QUERY_Deposit");
"oldKeys:".Print();
keys.PrintDump();
"newKeys:".Print();
newKeys.PrintDump();
The issue here is because the keys returned from GetKeysStartingWith() include the prefix so when you pass the prefixed keys to RemoveAll it’s adding another prefix resulting in trying to remove keys that don’t exist.
This existing behavior is the same in Redis & Memory Cache Client WithPrefix as seen in this gist.
As this issue is more likely to occur than using conflicting keys with the same prefix I’ve updated CacheClientWithPrefix to only add prefix to keys when it doesn’t already exist in this commit.