Created
August 13, 2015 15:03
-
-
Save kwal/4472b1355f104b86e344 to your computer and use it in GitHub Desktop.
Redis Cache
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 Newtonsoft.Json; | |
using NLog; | |
using StackExchange.Redis; | |
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
public class RedisCache : ICache | |
{ | |
private readonly IConfiguration _config; | |
private readonly ILogger _logger; | |
private readonly IConnectionMultiplexer _redis; | |
public RedisCache( | |
IConfiguration config, | |
ILogger logger, | |
IConnectionMultiplexer connection) | |
{ | |
_config = config; | |
_logger = logger; | |
_redis = connection; | |
} | |
public T GetOrAdd<T>(string key, Func<T> expression, TimeSpan? expiration = null) where T : class | |
{ | |
if (expression == null) | |
{ | |
throw new ArgumentNullException("expression"); | |
} | |
IDatabase db = null; | |
var fullKey = BuildFullKey<T>(key); | |
if (_redis.IsConnected) | |
{ | |
try | |
{ | |
db = _redis.GetDatabase(); | |
var cacheResult = db.StringGet(fullKey); | |
if (cacheResult.HasValue) | |
{ | |
return JsonConvert.DeserializeObject<T>(cacheResult); | |
} | |
} | |
catch (TimeoutException ex) | |
{ | |
_logger.Warn(ex); | |
} | |
} | |
T result = expression(); | |
if (db != null && result != null) | |
{ | |
db.StringSet(fullKey, JsonConvert.SerializeObject(result), expiration, flags: CommandFlags.FireAndForget); | |
} | |
return result; | |
} | |
public IEnumerable<T> GetOrAdd<T>(string key, Func<IEnumerable<T>> expression, TimeSpan? expiration = null) where T : class | |
{ | |
if (expression == null) | |
{ | |
throw new ArgumentNullException("expression"); | |
} | |
IDatabase db = null; | |
var fullKey = BuildFullKey<T>(key); | |
if (_redis.IsConnected) | |
{ | |
try | |
{ | |
db = _redis.GetDatabase(); | |
if (db.KeyExists(fullKey)) | |
{ | |
var cacheResult = db.SetMembers(fullKey); | |
if (cacheResult != null) | |
{ | |
return cacheResult.Select(x => JsonConvert.DeserializeObject<T>(x)).ToList(); | |
} | |
} | |
} | |
catch (TimeoutException ex) | |
{ | |
_logger.Warn(ex); | |
} | |
} | |
IEnumerable<T> results = expression(); | |
if (db != null && results != null) | |
{ | |
var values = results.Select(x => (RedisValue)JsonConvert.SerializeObject(x)).ToArray(); | |
db.SetAdd(fullKey, values, flags: CommandFlags.FireAndForget); | |
db.KeyExpire(fullKey, expiration, flags: CommandFlags.FireAndForget); | |
} | |
return results; | |
} | |
public void AddOrUpdate<T>(string key, T value, TimeSpan? expiration = null) where T : class | |
{ | |
if (String.IsNullOrWhiteSpace(key)) | |
{ | |
throw new ArgumentException("Must be non-empty", "key"); | |
} | |
if (value == null) | |
{ | |
throw new ArgumentNullException("value"); | |
} | |
IDatabase db = null; | |
var fullKey = BuildFullKey<T>(key); | |
if (_redis.IsConnected) | |
{ | |
try | |
{ | |
db = _redis.GetDatabase(); | |
db.StringSet(fullKey, JsonConvert.SerializeObject(value), expiration); | |
} | |
catch (TimeoutException ex) | |
{ | |
_logger.Warn(ex); | |
} | |
} | |
} | |
public void Remove<T>(string key) where T : class | |
{ | |
if (String.IsNullOrWhiteSpace(key)) | |
{ | |
throw new ArgumentException("Must be non-empty", "key"); | |
} | |
IDatabase db = null; | |
var fullKey = BuildFullKey<T>(key); | |
if (_redis.IsConnected) | |
{ | |
try | |
{ | |
db = _redis.GetDatabase(); | |
db.KeyDelete(fullKey); | |
} | |
catch (TimeoutException ex) | |
{ | |
_logger.Warn(ex); | |
} | |
} | |
} | |
private string BuildFullKey<T>(string key) | |
{ | |
return String.Format("{0}:{1}:{2}", _config.CachePrefix, typeof(T).Name, key); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment