This was a problem because it limited the re-usability of the consuming controller/service. Such a service might provide a method that used the injected IRedisClient to interact with the Redis instance. The IRedisClient implements IDisposable and should be wrapped in a using statement in order to release the resource and close the channel when it is has completed the task. In doing so, you make the method on the service non-idempotent: it has the side-effect of changing the state of the service by disposing of its injected IRedisClient instance. You are only able to successfully call the service method once, calling it a second time throws an exception.
The solution is fairly simple. Instead of having the service depend directly on the IRedisClient, the service instead needs to depend on the IRedisClientsManager. This then allows the service to call the GetClient() method on the IRedisClientsManager itself and create an instance of IRedisClient every time the method is called. Idempotency is achieved because a client of the service can call the method any number of times and not cause any unintended side-effects. The state of the service is no longer affected by disposing of its only instance of IRedisClient. The IRedisClient instances that are created are still disposed of, but the service has the ability to create a new one for itself.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Configuration; | |
using ServiceStack.Redis; | |
using StructureMap; | |
using StructureMap.Configuration.DSL; | |
namespace Example.IoC | |
{ | |
public class InfrastructureRegistry : Registry | |
{ | |
public InfrastructureRegistry() | |
{ | |
Scan(scan => | |
{ | |
scan.TheCallingAssembly(); | |
scan.WithDefaultConventions(); | |
}); | |
For<IRedisClientsManager>().Singleton().Use(() => | |
{ | |
var redisHost = ConfigurationManager.AppSettings["redisHost"]; | |
return new PooledRedisClientManager(redisHost) { ConnectTimeout = 1000 }; | |
}); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using ServiceStack.Redis; | |
namespace Example.Infrastructure | |
{ | |
public class DbManager : IDbManager | |
{ | |
private readonly IRedisClientsManager _redisClientsManager; | |
public DbManager(IRedisClientsManager redisClientsManager) | |
{ | |
_redisClientsManager = redisClientsManager; | |
} | |
public void ClearCache() | |
{ | |
using (var redisClient = _redisClientsManager.GetClient()) | |
{ | |
redisClient.FlushAll(); | |
} | |
} | |
} | |
} |