Skip to content

Commit 25fcbd3

Browse files
committed
Introduce MessagePack serializer
1 parent cdc827f commit 25fcbd3

File tree

18 files changed

+329
-224
lines changed

18 files changed

+329
-224
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ This is a .NET Core client library for Memcached migrated from [EnyimMemcached](
1212
"Address": "memcached",
1313
"Port": 11211
1414
}
15-
]
15+
],
16+
"Transcoder": "MessagePackTranscoder"
1617
}
1718
}
1819
```

sample/SampleWebApp/Controllers/HomeController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public async Task<IActionResult> Index()
4848

4949
public async Task<IActionResult> Postbody()
5050
{
51-
var postbody = (await _blogPostService.GetRecent(10)).First()?.Body;
51+
var postbody = (await _blogPostService.GetRecent(10)).First().Value.FirstOrDefault()?.Body;
5252
await _postbodyMemcachedClient.AddAsync(PostbodyCacheKey, postbody, 10);
5353
var result = await _postbodyMemcachedClient.GetAsync<string>(PostbodyCacheKey);
5454
return result.Success ? Ok() : StatusCode(500);

sample/SampleWebApp/Services/BlogPostService.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,21 @@ namespace Enyim.Caching.SampleWebApp.Services
88
{
99
public class BlogPostService : IBlogPostService
1010
{
11-
public async ValueTask<IEnumerable<BlogPost>> GetRecent(int itemCount)
11+
public async ValueTask<Dictionary<string, List<BlogPost>>> GetRecent(int itemCount)
1212
{
13-
return new List<BlogPost> { new BlogPost { Title = "Hello World", Body = "EnyimCachingCore" } };
13+
var dict = new Dictionary<string, List<BlogPost>>();
14+
var posts = new List<BlogPost>
15+
{
16+
new BlogPost
17+
{
18+
Title = "Hello World",
19+
Body = "EnyimCachingCore"
20+
}
21+
};
22+
23+
dict.Add(DateTime.Today.ToString("yyyy-MM-dd"), posts);
24+
25+
return dict;
1426
}
1527
}
1628
}

sample/SampleWebApp/Services/IBlogPostService.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@ namespace Enyim.Caching.SampleWebApp.Services
88
{
99
public interface IBlogPostService
1010
{
11-
ValueTask<IEnumerable<BlogPost>> GetRecent(int itemCount);
11+
ValueTask<Dictionary<string, List<BlogPost>>> GetRecent(int itemCount);
1212
}
1313
}

sample/SampleWebApp/appsettings.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
"deadTimeout": "00:00:15",
1515
"queueTimeout": "00:00:00.150"
1616
},
17-
"suppressException": "false"
18-
//"Transcoder": "BinaryFormatterTranscoder"
17+
"suppressException": "false",
18+
"Transcoder": "MessagePackTranscoder"
1919
//,
2020
//"KeyTransformer": "Enyim.Caching.Memcached.SHA1KeyTransformer"
2121
//,
@@ -44,7 +44,7 @@
4444
"Default": "Warning",
4545
"System": "Warning",
4646
"Microsoft": "Warning",
47-
"Enyim": "Debug"
47+
"Enyim": "Warning"
4848
}
4949
}
5050
}

src/Enyim.Caching/Configuration/MemcachedClientConfiguration.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using Microsoft.Extensions.Configuration;
1010
using System.Linq;
1111
using System.Net.Sockets;
12+
using Enyim.Caching.Memcached.Transcoders;
1213

1314
namespace Enyim.Caching.Configuration
1415
{
@@ -150,8 +151,14 @@ public MemcachedClientConfiguration(
150151
{
151152
try
152153
{
153-
if (options.Transcoder == "BinaryFormatterTranscoder")
154+
if (options.Transcoder == nameof(BinaryFormatterTranscoder))
155+
{
154156
options.Transcoder = "Enyim.Caching.Memcached.Transcoders.BinaryFormatterTranscoder";
157+
}
158+
else if (options.Transcoder == nameof(MessagePackTranscoder))
159+
{
160+
options.Transcoder = "Enyim.Caching.Memcached.Transcoders.MessagePackTranscoder";
161+
}
155162

156163
var transcoderType = Type.GetType(options.Transcoder);
157164
if (transcoderType != null)
@@ -168,7 +175,7 @@ public MemcachedClientConfiguration(
168175
else if (transcoder != null)
169176
{
170177
_transcoder = transcoder;
171-
_logger.LogDebug($"Use Transcoder Type : '{transcoder.ToString()}'");
178+
_logger.LogDebug($"Use Transcoder Type : '{transcoder}'");
172179
}
173180

174181
if (options.NodeLocatorFactory != null)

src/Enyim.Caching/Enyim.Caching.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,8 @@
4242
</ItemGroup>
4343
</Otherwise>
4444
</Choose>
45+
46+
<ItemGroup>
47+
<PackageReference Include="MessagePack" Version="2.4.59" />
48+
</ItemGroup>
4549
</Project>

src/Enyim.Caching/IMemcachedClient.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,18 @@ public interface IMemcachedClient : IDisposable
2929
Task<bool> ReplaceAsync(string key, object value, uint cacheSeconds);
3030
Task<bool> ReplaceAsync(string key, object value, TimeSpan timeSpan);
3131

32+
[Obsolete("Use GetAsync<T> instead")]
3233
Task<IGetOperationResult> GetAsync(string key);
3334
Task<IGetOperationResult<T>> GetAsync<T>(string key);
3435
Task<T> GetValueAsync<T>(string key);
3536
Task<T> GetValueOrCreateAsync<T>(string key, int cacheSeconds, Func<Task<T>> generator);
37+
[Obsolete("Use Get<T> instead")]
3638
object Get(string key);
3739
T Get<T>(string key);
3840
IDictionary<string, T> Get<T>(IEnumerable<string> keys);
3941
Task<IDictionary<string, T>> GetAsync<T>(IEnumerable<string> keys);
4042

43+
[Obsolete("Use TryGet<T> instead")]
4144
bool TryGet(string key, out object value);
4245
bool TryGet<T>(string key, out T value);
4346
bool TryGetWithCas(string key, out CasResult<object> value);
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
using MessagePack;
2+
using MessagePack.Resolvers;
3+
using Microsoft.Extensions.Options;
4+
using Newtonsoft.Json.Bson;
5+
using Newtonsoft.Json.Linq;
6+
using System;
7+
using System.Collections;
8+
using System.Collections.Generic;
9+
using System.Collections.Immutable;
10+
using System.IO;
11+
using System.Reflection;
12+
using System.Runtime.CompilerServices;
13+
using System.Text;
14+
15+
namespace Enyim.Caching.Memcached.Transcoders
16+
{
17+
public class MessagePackTranscoder : DefaultTranscoder
18+
{
19+
private readonly MessagePackSerializerOptions _options;
20+
21+
public MessagePackTranscoder() : this(CreateDefaultOptions())
22+
{
23+
}
24+
25+
public MessagePackTranscoder(MessagePackSerializerOptions options)
26+
{
27+
_options = options ?? CreateDefaultOptions();
28+
}
29+
30+
protected override ArraySegment<byte> SerializeObject(object value)
31+
{
32+
var bytes = MessagePackSerializer.Serialize(value, _options);
33+
return new ArraySegment<byte>(bytes, 0, bytes.Length);
34+
}
35+
36+
protected override object DeserializeObject(ArraySegment<byte> value)
37+
{
38+
throw new NotSupportedException("Does not support typeless deserialization. Please use generic api.");
39+
}
40+
41+
public override T Deserialize<T>(CacheItem item)
42+
{
43+
if (typeof(T).GetTypeCode() != TypeCode.Object || typeof(T) == typeof(byte[]))
44+
{
45+
var value = Deserialize(item);
46+
if (value != null)
47+
{
48+
if (typeof(T) == typeof(Guid))
49+
{
50+
return (T)(object)new Guid((string)value);
51+
}
52+
else
53+
{
54+
return (T)value;
55+
}
56+
}
57+
else
58+
{
59+
return default;
60+
}
61+
}
62+
63+
return MessagePackSerializer.Deserialize<T>(item.Data, _options);
64+
}
65+
66+
private static MessagePackSerializerOptions CreateDefaultOptions()
67+
{
68+
var resolver = CompositeResolver.Create(
69+
NativeDateTimeResolver.Instance,
70+
NativeGuidResolver.Instance,
71+
NativeDecimalResolver.Instance,
72+
ContractlessStandardResolverAllowPrivate.Instance,
73+
ContractlessStandardResolver.Instance);
74+
return MessagePackSerializerOptions.Standard.WithResolver(resolver);
75+
}
76+
}
77+
}

test/DistributedCacheTests/appsettings.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"Address": "memcached",
66
"Port": 11211
77
}
8-
]
8+
],
9+
"Transcoder": "MessagePackTranscoder"
910
}
1011
}

test/Enyim.Caching.Tests/MemcachedClientCasTests.cs

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,33 +6,31 @@
66

77
namespace Enyim.Caching.Tests
88
{
9-
109
public class MemcachedClientCasTests : MemcachedClientTestsBase
11-
{
12-
13-
[Fact]
14-
public void When_Storing_Item_With_Valid_Cas_Result_Is_Successful()
15-
{
16-
var key = GetUniqueKey("cas");
17-
var value = GetRandomString();
18-
var storeResult = Store(StoreMode.Add, key, value);
19-
StoreAssertPass(storeResult);
10+
{
11+
[Fact]
12+
public void When_Storing_Item_With_Valid_Cas_Result_Is_Successful()
13+
{
14+
var key = GetUniqueKey("cas");
15+
var value = GetRandomString();
16+
var storeResult = Store(StoreMode.Add, key, value);
17+
StoreAssertPass(storeResult);
2018

21-
var casResult = _client.ExecuteCas(StoreMode.Set, key, value, storeResult.Cas);
22-
StoreAssertPass(casResult);
23-
}
19+
var casResult = _client.ExecuteCas(StoreMode.Set, key, value, storeResult.Cas);
20+
StoreAssertPass(casResult);
21+
}
2422

25-
[Fact]
26-
public void When_Storing_Item_With_Invalid_Cas_Result_Is_Not_Successful()
27-
{
28-
var key = GetUniqueKey("cas");
29-
var value = GetRandomString();
30-
var storeResult = Store(StoreMode.Add, key, value);
31-
StoreAssertPass(storeResult);
23+
[Fact]
24+
public void When_Storing_Item_With_Invalid_Cas_Result_Is_Not_Successful()
25+
{
26+
var key = GetUniqueKey("cas");
27+
var value = GetRandomString();
28+
var storeResult = Store(StoreMode.Add, key, value);
29+
StoreAssertPass(storeResult);
3230

33-
var casResult = _client.ExecuteCas(StoreMode.Set, key, value, storeResult.Cas - 1);
34-
StoreAssertFail(casResult);
35-
}
31+
var casResult = _client.ExecuteCas(StoreMode.Set, key, value, storeResult.Cas - 1);
32+
StoreAssertFail(casResult);
33+
}
3634

3735

3836
[Fact]
@@ -49,7 +47,7 @@ public async Task When_Storing_Item_With_Valid_Cas_Result_Is_Successful_Async()
4947
var storeResult = Store(StoreMode.Add, key, comment);
5048
StoreAssertPass(storeResult);
5149

52-
var casResult1 = await _client.GetAsync(key);
50+
var casResult1 = await _client.GetAsync<Comment>(key);
5351
GetAssertPass(casResult1, comment);
5452

5553
var casResult2 = await _client.GetAsync<Comment>(key);

0 commit comments

Comments
 (0)