Skip to content

Commit 8beaac3

Browse files
committed
✨ redis provider support Hyperloglog
1 parent acafcf9 commit 8beaac3

File tree

6 files changed

+325
-11
lines changed

6 files changed

+325
-11
lines changed

build/releasenotes.props

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,7 @@
1919
7. Modify some extension methods' namespace.
2020
</EasyCachingMemcachedPackageNotes>
2121
<EasyCachingRedisPackageNotes>
22-
1. Make Interceptors and response caching Support .netcore3.0.
23-
2. Remove WithServices method to support console apps.
24-
3. Improve RabbitMQ bus.
25-
4. Add deep clone for memory cache provider.
26-
5. Support multi instances of hybrid provider.
27-
6. Upgrading dependencies.
28-
7. Modify some extension methods' namespace.
22+
1. Support Hyperloglog.
2923
</EasyCachingRedisPackageNotes>
3024
<EasyCachingSQLitePackageNotes>
3125
1. Make Interceptors and response caching Support .netcore3.0.
@@ -91,7 +85,7 @@
9185
7. Modify some extension methods' namespace.
9286
</EasyCachingProtobufPackageNotes>
9387
<EasyCachingCSRedisPackageNotes>
94-
1. Support sentinel mode.
88+
1. Support Hyperloglog.
9589
</EasyCachingCSRedisPackageNotes>
9690
<EasyCachingCSRedisBusPackageNotes>
9791
1. Support sentinel mode.

build/version.props

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<PropertyGroup>
33
<EasyCachingCorePackageVersion>0.8.0</EasyCachingCorePackageVersion>
44
<EasyCachingMemcachedPackageVersion>0.8.0</EasyCachingMemcachedPackageVersion>
5-
<EasyCachingRedisPackageVersion>0.8.0</EasyCachingRedisPackageVersion>
5+
<EasyCachingRedisPackageVersion>0.8.2</EasyCachingRedisPackageVersion>
66
<EasyCachingSQLitePackageVersion>0.8.0</EasyCachingSQLitePackageVersion>
77
<EasyCachingInMemoryPackageVersion>0.8.0</EasyCachingInMemoryPackageVersion>
88
<EasyCachingHybridPackageVersion>0.8.1</EasyCachingHybridPackageVersion>
@@ -12,7 +12,7 @@
1212
<EasyCachingJsonPackageVersion>0.8.1</EasyCachingJsonPackageVersion>
1313
<EasyCachingMessagePackPackageVersion>0.8.1</EasyCachingMessagePackPackageVersion>
1414
<EasyCachingProtobufPackageVersion>0.8.0</EasyCachingProtobufPackageVersion>
15-
<EasyCachingCSRedisPackageVersion>0.8.1</EasyCachingCSRedisPackageVersion>
15+
<EasyCachingCSRedisPackageVersion>0.8.2</EasyCachingCSRedisPackageVersion>
1616
<EasyCachingRedisBusPackageVersion>0.8.0</EasyCachingRedisBusPackageVersion>
1717
<EasyCachingCSRedisBusPackageVersion>0.8.1</EasyCachingCSRedisBusPackageVersion>
1818
<EasyCachingRabbitBusPackageVersion>0.8.0</EasyCachingRabbitBusPackageVersion>
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
namespace EasyCaching.CSRedis
2+
{
3+
using EasyCaching.Core;
4+
using System.Collections.Generic;
5+
using System.Threading.Tasks;
6+
7+
public partial class DefaultCSRedisCachingProvider : IRedisCachingProvider
8+
{
9+
public bool PfAdd<T>(string cacheKey, List<T> values)
10+
{
11+
ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey));
12+
ArgumentCheck.NotNullAndCountGTZero(values, nameof(values));
13+
14+
var list = new List<byte[]>();
15+
16+
foreach (var item in values)
17+
{
18+
list.Add(_serializer.Serialize(item));
19+
}
20+
21+
var res = _cache.PfAdd(cacheKey, list.ToArray());
22+
return res;
23+
}
24+
25+
public async Task<bool> PfAddAsync<T>(string cacheKey, List<T> values)
26+
{
27+
ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey));
28+
ArgumentCheck.NotNullAndCountGTZero(values, nameof(values));
29+
30+
var list = new List<byte[]>();
31+
32+
foreach (var item in values)
33+
{
34+
list.Add(_serializer.Serialize(item));
35+
}
36+
37+
var res = await _cache.PfAddAsync(cacheKey, list.ToArray());
38+
return res;
39+
}
40+
41+
[System.Obsolete()]
42+
public long PfCount(List<string> cacheKeys)
43+
{
44+
ArgumentCheck.NotNullAndCountGTZero(cacheKeys, nameof(cacheKeys));
45+
46+
var res = _cache.PfCount(cacheKeys.ToArray());
47+
return res;
48+
}
49+
50+
[System.Obsolete()]
51+
public async Task<long> PfCountAsync(List<string> cacheKeys)
52+
{
53+
ArgumentCheck.NotNullAndCountGTZero(cacheKeys, nameof(cacheKeys));
54+
55+
var res = await _cache.PfCountAsync(cacheKeys.ToArray());
56+
return res;
57+
}
58+
59+
[System.Obsolete()]
60+
public bool PfMerge(string destKey, List<string> sourceKeys)
61+
{
62+
ArgumentCheck.NotNullOrWhiteSpace(destKey, nameof(destKey));
63+
ArgumentCheck.NotNullAndCountGTZero(sourceKeys, nameof(sourceKeys));
64+
65+
var res = _cache.PfMerge(destKey, sourceKeys.ToArray());
66+
return res;
67+
}
68+
69+
[System.Obsolete()]
70+
public async Task<bool> PfMergeAsync(string destKey, List<string> sourceKeys)
71+
{
72+
ArgumentCheck.NotNullOrWhiteSpace(destKey, nameof(destKey));
73+
ArgumentCheck.NotNullAndCountGTZero(sourceKeys, nameof(sourceKeys));
74+
75+
var res = await _cache.PfMergeAsync(destKey, sourceKeys.ToArray());
76+
return res;
77+
}
78+
}
79+
}

src/EasyCaching.Core/IRedisCachingProvider.cs

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -789,7 +789,53 @@ public interface IRedisCachingProvider
789789
/// <param name="cacheKey"></param>
790790
/// <param name="cacheValue"></param>
791791
/// <returns></returns>
792-
Task<double?> ZScoreAsync<T>(string cacheKey, T cacheValue);
792+
Task<double?> ZScoreAsync<T>(string cacheKey, T cacheValue);
793+
#endregion
794+
795+
796+
#region Hyperloglog
797+
/// <summary>
798+
/// https://redis.io/commands/pfadd
799+
/// </summary>
800+
/// <typeparam name="T"></typeparam>
801+
/// <param name="cacheKey"></param>
802+
/// <param name="values"></param>
803+
/// <returns></returns>
804+
bool PfAdd<T>(string cacheKey, List<T> values);
805+
/// <summary>
806+
/// https://redis.io/commands/pfadd
807+
/// </summary>
808+
/// <typeparam name="T"></typeparam>
809+
/// <param name="cacheKey"></param>
810+
/// <param name="values"></param>
811+
/// <returns></returns>
812+
Task<bool> PfAddAsync<T>(string cacheKey, List<T> values);
813+
/// <summary>
814+
/// https://redis.io/commands/pfcount
815+
/// </summary>
816+
/// <param name="cacheKeys"></param>
817+
/// <returns></returns>
818+
long PfCount(List<string> cacheKeys);
819+
/// <summary>
820+
/// https://redis.io/commands/pfcount
821+
/// </summary>
822+
/// <param name="cacheKeys"></param>
823+
/// <returns></returns>
824+
Task<long> PfCountAsync(List<string> cacheKeys);
825+
/// <summary>
826+
/// https://redis.io/commands/pfmerge
827+
/// </summary>
828+
/// <param name="destKey"></param>
829+
/// <param name="sourceKeys"></param>
830+
/// <returns></returns>
831+
bool PfMerge(string destKey, List<string> sourceKeys);
832+
/// <summary>
833+
/// https://redis.io/commands/pfmerge
834+
/// </summary>
835+
/// <param name="destKey"></param>
836+
/// <param name="sourceKeys"></param>
837+
/// <returns></returns>
838+
Task<bool> PfMergeAsync(string destKey, List<string> sourceKeys);
793839
#endregion
794840
}
795841
}
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
namespace EasyCaching.Redis
2+
{
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using System.Threading.Tasks;
7+
using EasyCaching.Core;
8+
using EasyCaching.Core.Internal;
9+
using StackExchange.Redis;
10+
11+
/// <summary>
12+
/// Default redis caching provider.
13+
/// </summary>
14+
public partial class DefaultRedisCachingProvider : IRedisCachingProvider
15+
{
16+
public bool PfAdd<T>(string cacheKey, List<T> values)
17+
{
18+
ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey));
19+
ArgumentCheck.NotNullAndCountGTZero(values, nameof(values));
20+
21+
var list = new List<RedisValue>();
22+
23+
foreach (var item in values)
24+
{
25+
list.Add(_serializer.Serialize(item));
26+
}
27+
28+
var res = _cache.HyperLogLogAdd(cacheKey, list.ToArray());
29+
return res;
30+
}
31+
32+
public async Task<bool> PfAddAsync<T>(string cacheKey, List<T> values)
33+
{
34+
ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey));
35+
ArgumentCheck.NotNullAndCountGTZero(values, nameof(values));
36+
37+
var list = new List<RedisValue>();
38+
39+
foreach (var item in values)
40+
{
41+
list.Add(_serializer.Serialize(item));
42+
}
43+
44+
var res = await _cache.HyperLogLogAddAsync(cacheKey, list.ToArray());
45+
return res;
46+
}
47+
48+
public long PfCount(List<string> cacheKeys)
49+
{
50+
ArgumentCheck.NotNullAndCountGTZero(cacheKeys, nameof(cacheKeys));
51+
52+
var list = new List<RedisKey>();
53+
54+
foreach (var item in cacheKeys)
55+
{
56+
list.Add(item);
57+
}
58+
59+
var res = _cache.HyperLogLogLength(list.ToArray());
60+
return res;
61+
}
62+
63+
public async Task<long> PfCountAsync(List<string> cacheKeys)
64+
{
65+
ArgumentCheck.NotNullAndCountGTZero(cacheKeys, nameof(cacheKeys));
66+
67+
var list = new List<RedisKey>();
68+
69+
foreach (var item in cacheKeys)
70+
{
71+
list.Add(item);
72+
}
73+
74+
var res = await _cache.HyperLogLogLengthAsync(list.ToArray());
75+
return res;
76+
}
77+
78+
public bool PfMerge(string destKey, List<string> sourceKeys)
79+
{
80+
ArgumentCheck.NotNullOrWhiteSpace(destKey, nameof(destKey));
81+
ArgumentCheck.NotNullAndCountGTZero(sourceKeys, nameof(sourceKeys));
82+
83+
var list = new List<RedisKey>();
84+
85+
foreach (var item in sourceKeys)
86+
{
87+
list.Add(item);
88+
}
89+
90+
_cache.HyperLogLogMerge(destKey, list.ToArray());
91+
return true;
92+
}
93+
94+
public async Task<bool> PfMergeAsync(string destKey, List<string> sourceKeys)
95+
{
96+
ArgumentCheck.NotNullOrWhiteSpace(destKey, nameof(destKey));
97+
ArgumentCheck.NotNullAndCountGTZero(sourceKeys, nameof(sourceKeys));
98+
99+
var list = new List<RedisKey>();
100+
101+
foreach (var item in sourceKeys)
102+
{
103+
list.Add(item);
104+
}
105+
106+
await _cache.HyperLogLogMergeAsync(destKey, list.ToArray());
107+
return true;
108+
}
109+
}
110+
}

test/EasyCaching.UnitTests/CachingTests/BaseRedisFeatureCachingProviderTest.cs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1550,5 +1550,90 @@ protected virtual async Task SRandMemberAsync_With_Exist_Should_Succeed()
15501550
await _baseProvider.RemoveAsync(cacheKey);
15511551
}
15521552
#endregion
1553+
1554+
#region Hyperloglog
1555+
[Fact]
1556+
protected virtual void PfAdd_Should_Succeed()
1557+
{
1558+
var cacheKey = $"{_nameSpace}-{Guid.NewGuid().ToString()}";
1559+
1560+
var res1 = _provider.PfAdd<string>(cacheKey, new List<string> { "foo", "bar", "zap" });
1561+
var res2 = _provider.PfAdd<string>(cacheKey, new List<string> { "zap", "zap", "zap" });
1562+
Assert.True(res1);
1563+
Assert.True(res2);
1564+
1565+
var count = _provider.PfCount(new List<string> { cacheKey });
1566+
1567+
Assert.Equal(3, count);
1568+
_provider.KeyDel(cacheKey);
1569+
}
1570+
1571+
[Fact]
1572+
protected virtual async Task PfAddAsync_Should_Succeed()
1573+
{
1574+
var cacheKey = $"{_nameSpace}-{Guid.NewGuid().ToString()}";
1575+
1576+
var res1 = await _provider.PfAddAsync<string>(cacheKey, new List<string> { "foo", "bar", "zap" });
1577+
var res2 = await _provider.PfAddAsync<string>(cacheKey, new List<string> { "zap", "zap", "zap" });
1578+
Assert.True(res1);
1579+
Assert.True(res2);
1580+
1581+
var count = await _provider.PfCountAsync(new List<string> { cacheKey });
1582+
1583+
Assert.Equal(3, count);
1584+
1585+
await _provider.KeyDelAsync(cacheKey);
1586+
}
1587+
1588+
[Fact]
1589+
protected virtual void PfMerge_Should_Succeed()
1590+
{
1591+
var cacheKey0 = $"{_nameSpace}-{Guid.NewGuid().ToString()}";
1592+
var cacheKey1 = $"{_nameSpace}-{Guid.NewGuid().ToString()}";
1593+
var cacheKey2 = $"{_nameSpace}-{Guid.NewGuid().ToString()}";
1594+
1595+
var res1 = _provider.PfAdd<string>(cacheKey1, new List<string> { "foo", "bar", "zap", "a" });
1596+
var res2 = _provider.PfAdd<string>(cacheKey2, new List<string> { "a", "b", "c", "foo" });
1597+
Assert.True(res1);
1598+
Assert.True(res2);
1599+
1600+
1601+
var flag = _provider.PfMerge(cacheKey0, new List<string> { cacheKey1, cacheKey2 });
1602+
Assert.True(flag);
1603+
1604+
var count = _provider.PfCount(new List<string> { cacheKey0 });
1605+
1606+
Assert.Equal(6, count);
1607+
1608+
_provider.KeyDel(cacheKey0);
1609+
_provider.KeyDel(cacheKey1);
1610+
_provider.KeyDel(cacheKey2);
1611+
}
1612+
1613+
[Fact]
1614+
protected virtual async Task PfMergeAsync_Should_Succeed()
1615+
{
1616+
var cacheKey0 = $"{_nameSpace}-{Guid.NewGuid().ToString()}";
1617+
var cacheKey1 = $"{_nameSpace}-{Guid.NewGuid().ToString()}";
1618+
var cacheKey2 = $"{_nameSpace}-{Guid.NewGuid().ToString()}";
1619+
1620+
var res1 = await _provider.PfAddAsync<string>(cacheKey1, new List<string> { "foo", "bar", "zap", "a" });
1621+
var res2 = await _provider.PfAddAsync<string>(cacheKey2, new List<string> { "a", "b", "c", "foo" });
1622+
Assert.True(res1);
1623+
Assert.True(res2);
1624+
1625+
1626+
var flag = await _provider.PfMergeAsync(cacheKey0, new List<string> { cacheKey1, cacheKey2 });
1627+
Assert.True(flag);
1628+
1629+
var count = await _provider.PfCountAsync(new List<string> { cacheKey0 });
1630+
1631+
Assert.Equal(6, count);
1632+
1633+
await _provider.KeyDelAsync(cacheKey0);
1634+
await _provider.KeyDelAsync(cacheKey1);
1635+
await _provider.KeyDelAsync(cacheKey2);
1636+
}
1637+
#endregion
15531638
}
15541639
}

0 commit comments

Comments
 (0)