生产消息测试通过

This commit is contained in:
大石头 2020-07-03 10:28:06 +08:00
parent 0d101f7a1c
commit 7ff2e9bc59
5 changed files with 133 additions and 15 deletions

1
.gitignore vendored
View File

@ -22,3 +22,4 @@ bld/
*.nuspec *.nuspec
*.nupkg *.nupkg
/BinTest /BinTest
/BinUnitTest

View File

@ -2,15 +2,12 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NewLife.Caching;
using NewLife.Collections; using NewLife.Collections;
namespace NewLife.Caching namespace NewLife.Caching
{ {
/// <summary>Redis5.0的Stream数据结果完整态消息队列支持多消费组</summary> /// <summary>Redis5.0的Stream数据结果完整态消息队列支持多消费组</summary>
public class RedisStream : RedisBase, IProducerConsumer<String> public class RedisStream : RedisBase, IProducerConsumer<Object>
{ {
#region #region
/// <summary>个数</summary> /// <summary>个数</summary>
@ -18,9 +15,6 @@ namespace NewLife.Caching
/// <summary>是否为空</summary> /// <summary>是否为空</summary>
public Boolean IsEmpty => Count == 0; public Boolean IsEmpty => Count == 0;
/// <summary>最小管道阈值达到该值时使用管道默认3</summary>
public Int32 MinPipeline { get; set; } = 3;
#endregion #endregion
#region #region
@ -34,20 +28,51 @@ namespace NewLife.Caching
/// <param name="value"></param> /// <param name="value"></param>
/// <param name="maxlen"></param> /// <param name="maxlen"></param>
/// <returns></returns> /// <returns></returns>
public String Add(String value, Int32 maxlen = -1) public String Add(Object value, Int32 maxlen = -1)
{ {
var cmd = maxlen > 0 ? if (value == null) throw new ArgumentNullException(nameof(value));
$"{Key} maxlen {maxlen} * {value}" :
$"{Key} * {value}";
return Execute(rc => rc.Execute<String>("XADD", $"{Key} * {value}"), true); var args = new List<Object> { Key };
if (maxlen > 0)
{
args.Add("maxlen");
args.Add(maxlen);
}
args.Add("*");
// 数组和复杂对象字典,分开处理
if (Type.GetTypeCode(value.GetType()) != TypeCode.Object)
{
//throw new ArgumentOutOfRangeException(nameof(value), "消息体必须是复杂对象!");
args.Add("__data");
args.Add(value);
}
else if (value.GetType().IsArray)
{
foreach (var item in (value as Array))
{
args.Add(item);
}
}
else
{
foreach (var item in value.ToDictionary())
{
args.Add(item.Key);
args.Add(item.Value);
}
}
return Execute(rc => rc.Execute<String>("XADD", args.ToArray()), true);
} }
/// <summary>批量生产添加</summary> /// <summary>批量生产添加</summary>
/// <param name="values"></param> /// <param name="values"></param>
/// <returns></returns> /// <returns></returns>
public Int32 Add(IEnumerable<String> values) Int32 IProducerConsumer<Object>.Add(IEnumerable<Object> values)
{ {
if (values == null) throw new ArgumentNullException(nameof(values));
var count = 0; var count = 0;
foreach (var item in values) foreach (var item in values)
{ {
@ -111,7 +136,7 @@ namespace NewLife.Caching
/// <summary>批量消费获取</summary> /// <summary>批量消费获取</summary>
/// <param name="count"></param> /// <param name="count"></param>
/// <returns></returns> /// <returns></returns>
public IEnumerable<String> Take(Int32 count = 1) => Read(null, count); public IEnumerable<Object> Take(Int32 count = 1) => Read(null, count);
/// <summary>创建消费组</summary> /// <summary>创建消费组</summary>
/// <param name="group"></param> /// <param name="group"></param>

View File

@ -5,7 +5,6 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using NewLife.Caching; using NewLife.Caching;
using NewLife.Security; using NewLife.Security;
using NewLife.Threading;
using Xunit; using Xunit;
namespace XUnitTest namespace XUnitTest

92
XUnitTest/StreamTests.cs Normal file
View File

@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using NewLife.Caching;
using NewLife.Log;
using NewLife.Serialization;
using Xunit;
namespace XUnitTest
{
public class StreamTests
{
private FullRedis _redis;
public StreamTests()
{
//_redis = new FullRedis("127.0.0.1:6379", null, 2);
var config = "";
var file = @"config\redis.config";
if (File.Exists(file)) config = File.ReadAllText(file.GetFullPath())?.Trim();
if (config.IsNullOrEmpty()) config = "server=127.0.0.1;port=6379;db=3";
_redis = new FullRedis();
_redis.Init(config);
#if DEBUG
_redis.Log = XTrace.Log;
#endif
}
[Fact]
public void Stream_Normal()
{
var key = "stream_key";
// 删除已有
_redis.Remove(key);
var s = _redis.GetStream(key);
_redis.SetExpire(key, TimeSpan.FromMinutes(60));
// 取出个数
var count = s.Count;
Assert.True(s.IsEmpty);
Assert.Equal(0, count);
// 添加
Assert.Throws<ArgumentNullException>(() => s.Add(null));
//Assert.Throws<ArgumentOutOfRangeException>(() => s.Add("name stone age 24"));
//Assert.Throws<ArgumentOutOfRangeException>(() => s.Add(1234));
// 基础类型、数组、复杂对象
s.Add(1234);
s.Add(new Object[] { "name", "bigStone", "age", 24 });
s.Add(new { name = "smartStone", age = 36 });
var queue = s as IProducerConsumer<Object>;
var vs = new Object[] {
new { aaa = "1234" },
new { bbb = "abcd" },
new { ccc = "新生命团队" },
new { ddd = "ABEF" }
};
queue.Add(vs);
// 对比个数
var count2 = s.Count;
Assert.False(s.IsEmpty);
Assert.Equal(count + 1 + 1 + 1 + vs.Length, count2);
// 独立消费
var vs1 = s.Read(null, 3);
Assert.Equal(3, vs1.Length);
// 取出来
var vs2 = s.Take(2).ToArray();
Assert.Equal(2, vs2.Length);
Assert.Equal(vs[3], vs2[0]);
Assert.Equal(vs[2], vs2[1]);
var vs3 = s.Take(2).ToArray();
Assert.Equal(2, vs3.Length);
Assert.Equal(vs[1], vs3[0]);
Assert.Equal(vs[0], vs3[1]);
// 对比个数
var count3 = s.Count;
Assert.True(s.IsEmpty);
Assert.Equal(count, count3);
}
}
}

View File

@ -2,6 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework> <TargetFramework>netcoreapp3.1</TargetFramework>
<OutputPath>..\BinUnitTest</OutputPath>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
</PropertyGroup> </PropertyGroup>