From 6efbde45ac05efcb4e04acad74a31e65237f57c2 Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Mon, 29 Sep 2014 17:47:32 -0700 Subject: [PATCH] Finishing Redis cache provider --- .../AzureRedisOutputCacheStorageProvider.cs | 73 +++++++++++++++---- 1 file changed, 59 insertions(+), 14 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.Azure/Services/Caching/Output/AzureRedisOutputCacheStorageProvider.cs b/src/Orchard.Web/Modules/Orchard.Azure/Services/Caching/Output/AzureRedisOutputCacheStorageProvider.cs index 2291115cc..3b1647d94 100644 --- a/src/Orchard.Web/Modules/Orchard.Azure/Services/Caching/Output/AzureRedisOutputCacheStorageProvider.cs +++ b/src/Orchard.Web/Modules/Orchard.Azure/Services/Caching/Output/AzureRedisOutputCacheStorageProvider.cs @@ -28,6 +28,7 @@ namespace Orchard.Azure.Services.Caching.Output { private readonly ICacheManager _cacheManager; private readonly ShellSettings _shellSettings; private readonly IPlatformConfigurationAccessor _pca; + private HashSet _keysCache; public AzureRedisCacheStorageProvider( ShellSettings shellSettings, @@ -73,35 +74,43 @@ namespace Orchard.Azure.Services.Caching.Output { public IDatabase Cache { get { - - var connectionMultiplexer = _connectionMultiplexers.GetOrAdd(CacheConfiguration, cfg => { - Logger.Debug("Creating a new cache client ({0})", CacheConfiguration.GetHashCode()); - var connectionString = cfg.HostIdentifier + ",password=" + cfg.AuthorizationToken; - return ConnectionMultiplexer.Connect(connectionString); - }); - return connectionMultiplexer.GetDatabase(); + return GetConnection().GetDatabase(); } } + private ConnectionMultiplexer GetConnection() { + var connectionMultiplexer = _connectionMultiplexers.GetOrAdd(CacheConfiguration, cfg => { + Logger.Debug("Creating a new cache client ({0})", CacheConfiguration.GetHashCode()); + var connectionString = cfg.HostIdentifier + ",password=" + cfg.AuthorizationToken; + return ConnectionMultiplexer.Connect(connectionString); + }); + + + return connectionMultiplexer; + } + public void Set(string key, CacheItem cacheItem) { if (cacheItem.ValidFor <= 0) { return; } var value = JsonConvert.SerializeObject(cacheItem); - Cache.StringSet(key, value, TimeSpan.FromSeconds(cacheItem.ValidFor)); + Cache.StringSet(GetLocalizedKey(key), value, TimeSpan.FromSeconds(cacheItem.ValidFor)); } - + public void Remove(string key) { - Cache.StringSet(key, String.Empty, TimeSpan.MinValue); + Cache.KeyDelete(GetLocalizedKey(key)); } public void RemoveAll() { + foreach (var key in GetAllKeys()) { + Remove(key); + } } public CacheItem GetCacheItem(string key) { - string value = Cache.StringGet(key); + string value = Cache.StringGet(GetLocalizedKey(key)); if(String.IsNullOrEmpty(value)) { return null; } @@ -110,12 +119,48 @@ namespace Orchard.Azure.Services.Caching.Output { } public IEnumerable GetCacheItems(int skip, int count) { - - return Enumerable.Empty(); + foreach (var key in GetAllKeys().Skip(skip).Take(count)) { + var cacheItem = GetCacheItem(key); + // the item could have expired in the meantime + if (cacheItem != null) { + yield return cacheItem; + } + } } public int GetCacheItemsCount() { - return 0; + return GetAllKeys().Count(); + } + + /// + /// Creates a namespaced key to support multiple tenants on top of a single Redis connection. + /// + /// The key to localized. + /// A localized key based on the tenant name. + private string GetLocalizedKey(string key) { + return _shellSettings.Name + ":" + key; + } + + /// + /// Returns all the keys for the current tenant. + /// + /// The keys for the current tenant. + private IEnumerable GetAllKeys() { + // prevent the same request from computing the list twice (count + list) + if (_keysCache == null) { + _keysCache = new HashSet(); + var prefix = GetLocalizedKey(""); + + var connection = GetConnection(); + foreach (var endPoint in connection.GetEndPoints()) { + var server = GetConnection().GetServer(endPoint); + foreach (var key in server.Keys(pattern: GetLocalizedKey("*"))) { + _keysCache.Add(key.ToString().Substring(prefix.Length)); + } + } + } + + return _keysCache; } } } \ No newline at end of file