-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement mapping of HttpResponseMessage to CachedResponse to fix #152 (
#153) * changed name to cache options to fix issue #146 * Add acceptance test that exposes JSON deserialization bug from issue #146 - Create InMemoryJsonHandle for CacheManager that mimics DictionaryHandle but uses ICacheSerializer to serialize/deserialize values instead of saving references - Add CacheManager.Serialization.Json package - Add StartupWithCustomCacheHandle class that extends Startup and overrides ConfigureServices to register InMemoryJsonHandle - Add GivenOcelotIsRunningUsingConsulToStoreConfigAndJsonSerializedCache method to initiate Ocelot with StartupWithCustomCacheHandle - Add test should_return_response_200_with_simple_url_when_using_jsonserialized_cache * Create Acceptance test that exposes issue #152 - Add GivenOcelotIsRunningUsingJsonSerializedCache() that initializes Ocelot with InMemoryJsonHandle - Add should_return_cached_response_when_using_jsonserialized_cache test * Change Consul port to 9502 on should_return_response_200_with_simple_url_when_using_jsonserialized_cache() test * Implement mapping of HttpResponseMessage to CachedResponse to enable distributed caching - Add CachedResponse class that holds HttpResponse data - Add mapping methods in OutputCacheMiddleware to create HttpResponseMessage from CachedResponse and vice versa - Replace HttpResponseMessage with CachedResponse in services registrations - Replace HttpResponseMessage with CachedResponse in OutputCacheController's IOcelotCache * Fix unit tests for OutputCacheMiddleware and OutputCacheController by replacing HttpResponseMessage with CachedResponse * Add .editorconfig with default identation settings (spaces with size 4) * Re-format broken files with new identation settings * Add Startup_WithConsul_And_CustomCacheHandle class - Use Startup_WithConsul_And_CustomCacheHandle in GivenOcelotIsRunningUsingConsulToStoreConfigAndJsonSerializedCache step * Do minor cleanups - Rename StartupWithCustomCacheHandle to Startup_WithCustomCacheHandle for better readability - Remove cachemanager settings Action in Startup since it is not used anymore * Drop Task in CreateHttpResponseMessage - unnecessary overhead * Make setters private in CachedResponse - Rework CreateCachedResponse to use new CachedResponse constructor
- Loading branch information
1 parent
3b27bb3
commit 48b5a32
Showing
15 changed files
with
401 additions
and
46 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
root = true | ||
|
||
[*] | ||
end_of_line = crlf | ||
insert_final_newline = true | ||
|
||
[*.cs] | ||
indent_style = space | ||
indent_size = 4 |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
using System.Collections.Generic; | ||
using System.Net; | ||
|
||
namespace Ocelot.Cache | ||
{ | ||
public class CachedResponse | ||
{ | ||
public CachedResponse( | ||
HttpStatusCode statusCode = HttpStatusCode.OK, | ||
Dictionary<string, IEnumerable<string>> headers = null, | ||
string body = null | ||
) | ||
{ | ||
StatusCode = statusCode; | ||
Headers = headers ?? new Dictionary<string, IEnumerable<string>>(); | ||
Body = body ?? ""; | ||
} | ||
|
||
public HttpStatusCode StatusCode { get; private set; } | ||
|
||
public Dictionary<string, IEnumerable<string>> Headers { get; private set; } | ||
|
||
public string Body { get; private set; } | ||
} | ||
} |
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
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
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
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
137 changes: 137 additions & 0 deletions
137
test/Ocelot.AcceptanceTests/Caching/InMemoryJsonHandle.cs
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
using CacheManager.Core; | ||
using CacheManager.Core.Internal; | ||
using CacheManager.Core.Logging; | ||
using System; | ||
using System.Collections.Concurrent; | ||
using System.Linq; | ||
using static CacheManager.Core.Utility.Guard; | ||
|
||
namespace Ocelot.AcceptanceTests.Caching | ||
{ | ||
public class InMemoryJsonHandle<TCacheValue> : BaseCacheHandle<TCacheValue> | ||
{ | ||
private readonly ICacheSerializer _serializer; | ||
private readonly ConcurrentDictionary<string, Tuple<Type, byte[]>> _cache; | ||
|
||
public InMemoryJsonHandle( | ||
ICacheManagerConfiguration managerConfiguration, | ||
CacheHandleConfiguration configuration, | ||
ICacheSerializer serializer, | ||
ILoggerFactory loggerFactory) : base(managerConfiguration, configuration) | ||
{ | ||
_cache = new ConcurrentDictionary<string, Tuple<Type, byte[]>>(); | ||
_serializer = serializer; | ||
Logger = loggerFactory.CreateLogger(this); | ||
} | ||
|
||
public override int Count => _cache.Count; | ||
|
||
protected override ILogger Logger { get; } | ||
|
||
public override void Clear() => _cache.Clear(); | ||
|
||
public override void ClearRegion(string region) | ||
{ | ||
NotNullOrWhiteSpace(region, nameof(region)); | ||
|
||
var key = string.Concat(region, ":"); | ||
foreach (var item in _cache.Where(p => p.Key.StartsWith(key, StringComparison.OrdinalIgnoreCase))) | ||
{ | ||
_cache.TryRemove(item.Key, out Tuple<Type, byte[]> val); | ||
} | ||
} | ||
|
||
public override bool Exists(string key) | ||
{ | ||
NotNullOrWhiteSpace(key, nameof(key)); | ||
|
||
return _cache.ContainsKey(key); | ||
} | ||
|
||
public override bool Exists(string key, string region) | ||
{ | ||
NotNullOrWhiteSpace(region, nameof(region)); | ||
var fullKey = GetKey(key, region); | ||
return _cache.ContainsKey(fullKey); | ||
} | ||
|
||
protected override bool AddInternalPrepared(CacheItem<TCacheValue> item) | ||
{ | ||
NotNull(item, nameof(item)); | ||
|
||
var key = GetKey(item.Key, item.Region); | ||
|
||
var serializedItem = _serializer.SerializeCacheItem(item); | ||
|
||
return _cache.TryAdd(key, new Tuple<Type, byte[]>(item.Value.GetType(), serializedItem)); | ||
} | ||
|
||
protected override CacheItem<TCacheValue> GetCacheItemInternal(string key) => GetCacheItemInternal(key, null); | ||
|
||
protected override CacheItem<TCacheValue> GetCacheItemInternal(string key, string region) | ||
{ | ||
var fullKey = GetKey(key, region); | ||
|
||
CacheItem<TCacheValue> deserializedResult = null; | ||
|
||
if (_cache.TryGetValue(fullKey, out Tuple<Type, byte[]> result)) | ||
{ | ||
deserializedResult = _serializer.DeserializeCacheItem<TCacheValue>(result.Item2, result.Item1); | ||
|
||
if (deserializedResult.ExpirationMode != ExpirationMode.None && IsExpired(deserializedResult, DateTime.UtcNow)) | ||
{ | ||
_cache.TryRemove(fullKey, out Tuple<Type, byte[]> removeResult); | ||
TriggerCacheSpecificRemove(key, region, CacheItemRemovedReason.Expired, deserializedResult.Value); | ||
return null; | ||
} | ||
} | ||
|
||
return deserializedResult; | ||
} | ||
|
||
protected override void PutInternalPrepared(CacheItem<TCacheValue> item) | ||
{ | ||
NotNull(item, nameof(item)); | ||
|
||
var serializedItem = _serializer.SerializeCacheItem<TCacheValue>(item); | ||
|
||
_cache[GetKey(item.Key, item.Region)] = new Tuple<Type, byte[]>(item.Value.GetType(), serializedItem); | ||
} | ||
|
||
protected override bool RemoveInternal(string key) => RemoveInternal(key, null); | ||
|
||
protected override bool RemoveInternal(string key, string region) | ||
{ | ||
var fullKey = GetKey(key, region); | ||
return _cache.TryRemove(fullKey, out Tuple<Type, byte[]> val); | ||
} | ||
|
||
private static string GetKey(string key, string region) | ||
{ | ||
NotNullOrWhiteSpace(key, nameof(key)); | ||
|
||
if (string.IsNullOrWhiteSpace(region)) | ||
{ | ||
return key; | ||
} | ||
|
||
return string.Concat(region, ":", key); | ||
} | ||
|
||
private static bool IsExpired(CacheItem<TCacheValue> item, DateTime now) | ||
{ | ||
if (item.ExpirationMode == ExpirationMode.Absolute | ||
&& item.CreatedUtc.Add(item.ExpirationTimeout) < now) | ||
{ | ||
return true; | ||
} | ||
else if (item.ExpirationMode == ExpirationMode.Sliding | ||
&& item.LastAccessedUtc.Add(item.ExpirationTimeout) < now) | ||
{ | ||
return true; | ||
} | ||
|
||
return false; | ||
} | ||
} | ||
} |
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
Oops, something went wrong.