Skip to content

Commit db8c5af

Browse files
amiru3famirsolhi
andauthored
MemoryPack Serializer (#438)
* MemoryPack serializer * some cleanups Co-authored-by: amirsolhi <a.solhi@alibaba.ir>
1 parent 4cc0ab9 commit db8c5af

File tree

12 files changed

+338
-44
lines changed

12 files changed

+338
-44
lines changed

EasyCaching.sln

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Microsoft Visual Studio Solution File, Format Version 12.00
1+
Microsoft Visual Studio Solution File, Format Version 12.00
22
# Visual Studio Version 17
33
VisualStudioVersion = 17.2.32616.157
44
MinimumVisualStudioVersion = 10.0.40219.1
@@ -76,6 +76,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EasyCaching.Bus.Zookeeper",
7676
EndProject
7777
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EasyCaching.FasterKv", "src\EasyCaching.FasterKv\EasyCaching.FasterKv.csproj", "{7191E567-38DF-4879-82E1-73EC618AFCAC}"
7878
EndProject
79+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EasyCaching.Serialization.MemoryPack", "serialization\EasyCaching.Serialization.MemoryPack\EasyCaching.Serialization.MemoryPack.csproj", "{EEF22C21-F380-4980-B72C-F14488369333}"
80+
EndProject
7981
Global
8082
GlobalSection(SolutionConfigurationPlatforms) = preSolution
8183
Debug|Any CPU = Debug|Any CPU
@@ -202,6 +204,10 @@ Global
202204
{7191E567-38DF-4879-82E1-73EC618AFCAC}.Debug|Any CPU.Build.0 = Debug|Any CPU
203205
{7191E567-38DF-4879-82E1-73EC618AFCAC}.Release|Any CPU.ActiveCfg = Release|Any CPU
204206
{7191E567-38DF-4879-82E1-73EC618AFCAC}.Release|Any CPU.Build.0 = Release|Any CPU
207+
{EEF22C21-F380-4980-B72C-F14488369333}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
208+
{EEF22C21-F380-4980-B72C-F14488369333}.Debug|Any CPU.Build.0 = Debug|Any CPU
209+
{EEF22C21-F380-4980-B72C-F14488369333}.Release|Any CPU.ActiveCfg = Release|Any CPU
210+
{EEF22C21-F380-4980-B72C-F14488369333}.Release|Any CPU.Build.0 = Release|Any CPU
205211
EndGlobalSection
206212
GlobalSection(SolutionProperties) = preSolution
207213
HideSolutionNode = FALSE
@@ -237,6 +243,7 @@ Global
237243
{F7FBADEB-D766-4595-949A-07104B52692C} = {B337509B-75F9-4851-821F-9BBE87C4E4BC}
238244
{5E488583-391E-4E15-83C1-7301B4FE79AE} = {B337509B-75F9-4851-821F-9BBE87C4E4BC}
239245
{7191E567-38DF-4879-82E1-73EC618AFCAC} = {A0F5CC7E-155F-4726-8DEB-E966950B3FE9}
246+
{EEF22C21-F380-4980-B72C-F14488369333} = {15070C49-A507-4844-BCFE-D319CFBC9A63}
240247
EndGlobalSection
241248
GlobalSection(ExtensibilityGlobals) = postSolution
242249
SolutionGuid = {63A57886-054B-476C-AAE1-8D7C8917682E}

sample/EasyCaching.Demo.ConsoleApp/EasyCaching.Demo.ConsoleApp.csproj

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,13 @@
2020
<ProjectReference Include="..\..\src\EasyCaching.Memcached\EasyCaching.Memcached.csproj" />
2121
<ProjectReference Include="..\..\src\EasyCaching.Redis\EasyCaching.Redis.csproj" />
2222
<ProjectReference Include="..\..\src\EasyCaching.ResponseCaching\EasyCaching.ResponseCaching.csproj" />
23+
<ProjectReference Include="..\..\src\EasyCaching.SQLite\EasyCaching.SQLite.csproj" />
24+
</ItemGroup>
25+
26+
<ItemGroup>
2327
<ProjectReference Include="..\..\serialization\EasyCaching.Serialization.Json\EasyCaching.Serialization.Json.csproj" />
2428
<ProjectReference Include="..\..\serialization\EasyCaching.Serialization.MessagePack\EasyCaching.Serialization.MessagePack.csproj" />
2529
<ProjectReference Include="..\..\serialization\EasyCaching.Serialization.Protobuf\EasyCaching.Serialization.Protobuf.csproj" />
26-
<ProjectReference Include="..\..\src\EasyCaching.SQLite\EasyCaching.SQLite.csproj" />
30+
<ProjectReference Include="..\..\serialization\EasyCaching.Serialization.MemoryPack\EasyCaching.Serialization.MemoryPack.csproj" />
2731
</ItemGroup>
28-
2932
</Project>
Lines changed: 51 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
using System.Threading.Tasks;
1+
using EasyCaching.Serialization.MemoryPack;
22

33
namespace EasyCaching.Demo.ConsoleApp
44
{
55
using EasyCaching.Core;
66
using EasyCaching.SQLite;
7+
using MemoryPack;
78
using Microsoft.Extensions.DependencyInjection;
89
using System;
910

@@ -16,15 +17,18 @@ static void Main(string[] args)
1617
IServiceCollection services = new ServiceCollection();
1718
services.AddEasyCaching(option =>
1819
{
20+
option.WithMemoryPack(configure =>
21+
{
22+
}, "mempack");
23+
1924
option.UseInMemory("m1");
2025

21-
// option.UseRedis(config =>
22-
// {
23-
// config.DBConfig = new Redis.RedisDBOptions { Configuration = "localhost" };
24-
// config.SerializerName = "json";
25-
// }, "r1");
26-
//
27-
26+
option.UseRedis((options) =>
27+
{
28+
options.SerializerName = "mempack";
29+
options.DBConfig.Endpoints.Add(new Core.Configurations.ServerEndPoint("localhost", 6388));
30+
}, "r1");
31+
2832
option.UseSQLite(c =>
2933
{
3034
c.DBConfig = new SQLiteDBOptions
@@ -43,7 +47,7 @@ static void Main(string[] args)
4347

4448
IServiceProvider serviceProvider = services.BuildServiceProvider();
4549
var factory = serviceProvider.GetService<IEasyCachingProviderFactory>();
46-
50+
4751
// var redisCache = factory.GetCachingProvider("r1");
4852
//
4953
// redisCache.Set<Product>("rkey", new Product() { Name = "test" }, TimeSpan.FromSeconds(20));
@@ -55,41 +59,63 @@ static void Main(string[] args)
5559
// Console.WriteLine($"redis cache get value, {redisVal.HasValue} {redisVal.IsNull} {redisVal.Value}");
5660

5761

58-
59-
var mCache = factory.GetCachingProvider("m1");
60-
61-
mCache.Set<Product>("mkey1", new Product() { Name = "test" }, TimeSpan.FromSeconds(20));
6262

63-
var mVal1 = mCache.Get<Product>("mkey1");
63+
var rCache = factory.GetCachingProvider("r1");
64+
65+
var prod = new Product()
66+
{
67+
Name = "Name1",
68+
Lastname = "Lastname1",
69+
Inner = new()
70+
{
71+
Name = "Name2",
72+
Lastname = "Lastname2"
73+
}
74+
};
75+
76+
prod.Inner.Inner = prod;
77+
rCache.Set<Product>("mkey1", prod, TimeSpan.FromSeconds(20));
78+
79+
var mVal1 = rCache.Get<Product>("mkey1");
80+
81+
rCache.Set<string>("mkey", "mvalue", TimeSpan.FromSeconds(20));
82+
83+
var mVal = rCache.Get<string>("mkey");
84+
85+
var mAllKey = rCache.GetAllKeysByPrefix("mk");
6486

65-
mCache.Set<string>("mkey", "mvalue", TimeSpan.FromSeconds(20));
66-
67-
var mVal = mCache.Get<string>("mkey");
68-
69-
var mAllKey = mCache.GetAllKeysByPrefix("mk");
70-
7187
Console.WriteLine($"in-memory cache get value, {mVal.HasValue} {mVal.IsNull} {mVal.Value} ");
7288

73-
89+
7490
var sCache = factory.GetCachingProvider("s1");
7591

76-
92+
7793
sCache.Set<string>("skey", "svalue", TimeSpan.FromSeconds(20));
7894

79-
95+
8096
var sVal = sCache.Get<string>("skey");
8197

82-
98+
8399
Console.WriteLine($"sqlite cache get value, {sVal.HasValue} {sVal.IsNull} {sVal.Value} ");
84100

85101
Console.ReadKey();
86102
}
87103
}
88104

89-
public class Product
105+
[MemoryPackable(GenerateType.CircularReference)]
106+
public partial class Product
90107
{
91108

109+
[MemoryPackOrder(0)]
92110
public string Name { get; set; }
111+
112+
[MemoryPackOrder(1)]
113+
114+
public string Lastname { get; set; }
115+
116+
[MemoryPackOrder(2)]
117+
118+
public Product Inner { set; get; }
93119
}
94120
}
95121

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using MemoryPack;
2+
3+
namespace EasyCaching.Serialization.MemoryPack;
4+
5+
/// <summary>
6+
/// EasyCaching memory pack serializer options.
7+
/// </summary>
8+
public record EasyCachingMemPackSerializerOptions
9+
{
10+
public StringEncoding StringEncoding { set; get; }
11+
}
12+
13+
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using MemoryPack;
2+
using EasyCaching.Core.Configurations;
3+
using EasyCaching.Serialization.Json;
4+
5+
namespace EasyCaching.Serialization.MemoryPack;
6+
7+
/// <summary>
8+
/// Easy caching options extensions.
9+
/// </summary>
10+
public static class EasyCachingOptionsExtensions
11+
{
12+
/// <summary>
13+
/// Withs the memory pack serializer.
14+
/// </summary>
15+
/// <param name="options">Options.</param>
16+
/// <param name="name">The name of this serializer instance.</param>
17+
public static EasyCachingOptions WithMemoryPack(this EasyCachingOptions options, string name = "mempack")
18+
{
19+
options.RegisterExtension(new MemoryPackOptionsExtension(name, null));
20+
21+
return options;
22+
}
23+
24+
/// <summary>
25+
/// Withs the memory pack serializer.
26+
/// </summary>
27+
/// <param name="options">Options.</param>
28+
/// <param name="configure">Configure serializer settings.</param>
29+
/// <param name="name">The name of this serializer instance.</param>
30+
public static EasyCachingOptions WithMemoryPack(this EasyCachingOptions options, Action<EasyCachingMemPackSerializerOptions> serializerOptions, string name)
31+
{
32+
options.RegisterExtension(new MemoryPackOptionsExtension(name, serializerOptions));
33+
34+
return options;
35+
}
36+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
namespace EasyCaching.Serialization.Json;
2+
3+
using System;
4+
using EasyCaching.Core.Configurations;
5+
using EasyCaching.Core.Serialization;
6+
using EasyCaching.Serialization.MemoryPack;
7+
using global::MemoryPack;
8+
using Microsoft.Extensions.DependencyInjection;
9+
10+
/// <summary>
11+
/// MemoryPack options extension.
12+
/// </summary>
13+
internal sealed class MemoryPackOptionsExtension : IEasyCachingOptionsExtension
14+
{
15+
/// <summary>
16+
/// The name.
17+
/// </summary>
18+
private readonly string _name;
19+
20+
/// <summary>
21+
/// The configure.
22+
/// </summary>
23+
private readonly Action<EasyCachingMemPackSerializerOptions> _configure;
24+
25+
/// <summary>
26+
/// Initializes a new instance of the <see cref="T:EasyCaching.Serialization.MemoryPack.MemoryPackOptionsExtension"/> class.
27+
/// </summary>
28+
/// <param name="name">Name.</param>
29+
/// <param name="configure">Configure.</param>
30+
public MemoryPackOptionsExtension(string name, Action<EasyCachingMemPackSerializerOptions> configure)
31+
{
32+
this._name = name;
33+
this._configure = configure;
34+
}
35+
36+
/// <summary>
37+
/// Adds the services.
38+
/// </summary>
39+
/// <param name="services">Services.</param>
40+
public void AddServices(IServiceCollection services)
41+
{
42+
Action<EasyCachingMemPackSerializerOptions> configure = _configure ?? (_ => { });
43+
44+
services.AddOptions();
45+
services.Configure(_name, configure);
46+
47+
services.AddSingleton<IEasyCachingSerializer, DefaultMemoryPackSerializer>(x =>
48+
{
49+
var optionsMon = x.GetRequiredService<Microsoft.Extensions.Options.IOptionsMonitor<EasyCachingMemPackSerializerOptions>>();
50+
var easyCachingOptions = optionsMon.Get(_name);
51+
var options = new MemoryPackSerializerOptions { StringEncoding = easyCachingOptions.StringEncoding };
52+
return new DefaultMemoryPackSerializer(_name, options);
53+
});
54+
}
55+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using EasyCaching.Core.Serialization;
2+
using MemoryPack;
3+
4+
namespace EasyCaching.Serialization.MemoryPack;
5+
6+
/// <summary>
7+
/// Default MemoryPack serializer
8+
/// </summary>
9+
public class DefaultMemoryPackSerializer : IEasyCachingSerializer
10+
{
11+
private readonly string _name;
12+
private readonly MemoryPackSerializerOptions _memoryPackSerializerOptions;
13+
14+
public string Name => _name;
15+
16+
public DefaultMemoryPackSerializer(string name, MemoryPackSerializerOptions options = null)
17+
{
18+
_name = name;
19+
_memoryPackSerializerOptions = options;
20+
}
21+
22+
public T Deserialize<T>(byte[] bytes) => MemoryPackSerializer.Deserialize<T>(bytes, _memoryPackSerializerOptions);
23+
public object Deserialize(byte[] bytes, Type type) => MemoryPackSerializer.Deserialize(type, bytes, _memoryPackSerializerOptions);
24+
public object DeserializeObject(ArraySegment<byte> value) => throw new NotImplementedException("this is not supported in MemoryPack serializer");
25+
public byte[] Serialize<T>(T value) => MemoryPackSerializer.Serialize(value, _memoryPackSerializerOptions);
26+
27+
public ArraySegment<byte> SerializeObject(object obj)
28+
{
29+
var bytes = MemoryPackSerializer.Serialize(obj.GetType(), obj, _memoryPackSerializerOptions);
30+
return new ArraySegment<byte>(bytes);
31+
}
32+
}
33+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net6.0</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
</PropertyGroup>
7+
<ItemGroup>
8+
<ProjectReference Include="..\..\src\EasyCaching.Core\EasyCaching.Core.csproj" />
9+
</ItemGroup>
10+
<ItemGroup>
11+
<PackageReference Include="MemoryPack" Version="1.9.7" />
12+
</ItemGroup>
13+
</Project>

test/EasyCaching.UnitTests/CachingTests/BaseCachingProviderTest.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -765,7 +765,7 @@ public async Task Remove_Cached_Value_Async_Should_Succeed()
765765
var cacheValue = "value";
766766

767767
await _provider.SetAsync(cacheKey, cacheValue, _defaultTs);
768-
var valBeforeRemove = await _provider.GetAsync<string>(cacheKey, null, _defaultTs);
768+
var valBeforeRemove = await _provider.GetAsync<string>(cacheKey, () => null, _defaultTs);
769769
Assert.NotNull(valBeforeRemove);
770770

771771
await _provider.RemoveAsync(cacheKey);
@@ -870,15 +870,15 @@ protected virtual async Task RemoveByPrefixAsync_Should_Succeed()
870870
}
871871

872872
#endregion
873-
873+
874874
#region RemoveByPattern/RemoveByPatternAsync
875875

876876
[Fact]
877877
public virtual void RemoveByPattern_Should_Succeed()
878878
{
879879
SetCacheItem("garden:pots:flowers", "ok");
880880
SetCacheItem("garden:pots:flowers:test", "ok");
881-
SetCacheItem("garden:flowerspots:test", "ok" );
881+
SetCacheItem("garden:flowerspots:test", "ok");
882882
SetCacheItem("boo:foo", "ok");
883883
SetCacheItem("boo:test:foo", "ok");
884884
SetCacheItem("sky:birds:bar", "ok");
@@ -933,13 +933,13 @@ public virtual void RemoveByPattern_Should_Succeed()
933933
Assert.False(val15.HasValue);
934934
Assert.False(val16.HasValue);
935935
}
936-
936+
937937
[Fact]
938938
public virtual async Task RemoveByPatternAsync_Should_Succeed()
939939
{
940940
SetCacheItem("garden:pots:flowers", "ok");
941941
SetCacheItem("garden:pots:flowers:test", "ok");
942-
SetCacheItem("garden:flowerspots:test", "ok" );
942+
SetCacheItem("garden:flowerspots:test", "ok");
943943
SetCacheItem("boo:foo", "ok");
944944
SetCacheItem("boo:test:foo", "ok");
945945
SetCacheItem("sky:birds:bar", "ok");

0 commit comments

Comments
 (0)