I am storing lists of json data in redis and accessing it using the ServiceStack c# client. I am essentially managing my own foreign keys, where I store a zrange
of ids and I use an interface internal to my application to pull the id's from the zrange
and then fetch the underlying json objects from Redis and package them as a list to return to other parts of my application.
I am using the PooledRedisClientManager
as I anticipate Redis to be hosted on a different server from the server executing the code.
I am doing all my development work locally on Windows 8, using the MSOpenTech Redis server. Currently my biggest challenge is that client connections are not being closed.
My Redis persister is being injected with an instance of IRedisClientManager
(IoC is CastleWindsor). This code executes in the context of an azure worker role.
This is how I am fetching items from a zrange:
public class MyRedisPersister<T> : IResourcePersister<T>
{
IRedisClientManager _mgr;
public MyRedisPersister(IRedisClientManager mgr)
{
_mgr = mgr;
}
public IResourceList<T> Get<T>(string key, int offset, int count) where T
{
using (var redis = _clientManager.GetClient())
{
var itemKeys = redis.GetRangeFromSortedSet(key, offset, offset + count - 1).ToList();
var totalItems = redis.GetSortedSetCount(key);
if (itemKeys.Count == 0)
{
return new ResourceList<T>
{
Items = new List<T>(),
Offset = 0,
PageSize = 0,
TotalItems = 0,
TotalPages = 0
};
}
else
{
return new ResourceList<T>
{
Items = itemKeys.Select(k => redis.Get<T>(k)).ToList(),
Offset = offset,
PageSize = count,
TotalItems = totalItems,
TotalPages = (int) Math.Ceiling((float) totalItems/count)
};
}
}
}
}
This is the code I use to register the IRedisClientManager
var mgr = new PooledRedisClientManager(100, 10, "localhost:6379");
container.Register(Component.For<IRedisClientsManager>().Instance(mgr).LifeStyle.Singleton);
Any help would be greatly appreciated.
Currently my biggest challenge is that client connections are not being closed.
You are using the 'PooledRedisClientManager' so my understanding is that the client connections should not be closed, just put into the pool for reuse. It looks like your pool size is 100 connections.
You can try using
var mgr = new BasicRedisClientManager("localhost:6379")
which should dispose of the client.
edit The below approach is not recommended - you should take a dependency on the IRedisClientsManager and wrap all redis client calls inside a using() block, otherwise you will be bitten by gremlins.
I've been having similar problems getting Windsor to play nicely with the PooledRedisClientsManager, in the end this seemed to work:
container.Register(
Component.For<IRedisClientsManager>()
.Instance(redisClients)
.LifestyleSingleton(),
Component.For<IRedisClient>()
.UsingFactoryMethod(c => c.Resolve<IRedisClientsManager>().GetClient(),
managedExternally: true));
}
The managedExternally parameter tells Windsor to not try to apply decommissioning concerns to the IRedisClients and let the PooledRedisClientsManager handle recycling.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With