From f4a1cb811dd0d5ac46c762b8a18035afb49fb7d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=99=BA=E8=83=BD=E5=A4=A7=E7=9F=B3=E5=A4=B4?= Date: Sat, 3 May 2025 22:55:07 +0800 Subject: [PATCH] =?UTF-8?q?[feat]=20=E6=94=AF=E6=8C=81=E6=89=A7=E8=A1=8CLu?= =?UTF-8?q?a=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NewLife.Redis/FullRedis.cs | 33 +++++++++++++++++++++++++++++-- XUnitTest/RedisTest.cs | 40 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 2 deletions(-) diff --git a/NewLife.Redis/FullRedis.cs b/NewLife.Redis/FullRedis.cs index fb53e68..8b00465 100644 --- a/NewLife.Redis/FullRedis.cs +++ b/NewLife.Redis/FullRedis.cs @@ -831,10 +831,11 @@ public class FullRedis : Redis /// public virtual T? RPOPLPUSH(String source, String destination) => Execute(source, (rc, k) => rc.Execute("RPOPLPUSH", k, GetKey(destination)), true); - /// + /// 弹出并插入另一个列表 + /// /// 从列表中弹出一个值,将弹出的元素插入到另外一个列表中并返回它; 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。 /// 适用于做安全队列(通过secTimeout决定阻塞时长) - /// + /// /// /// 源列表名称 /// 元素后写入的新列表名称 @@ -998,5 +999,33 @@ public class FullRedis : Redis /// /// public virtual T[]? SPOP(String key, Int32 count) => Execute(key, (r, k) => r.Execute("SPOP", k, count), true); + + /// 执行lua脚本 + /// + /// + /// + /// + /// + public virtual T? Eval(String script, String[] keys, Object[] args) + { + // EVAL script numkeys [key [key ...]] [arg [arg ...]] + keys ??= []; + args ??= []; + var ps = new List + { + script, + keys.Length + "" + }; + for (var i = 0; i < keys.Length && i < args.Length; i++) + { + ps.Add(keys[i]); + } + for (var i = 0; i < keys.Length && i < args.Length; i++) + { + ps.Add(args[i]); + } + + return Execute("", (rc, k) => rc.Execute("EVAL", ps), true); + } #endregion } diff --git a/XUnitTest/RedisTest.cs b/XUnitTest/RedisTest.cs index b8c8e6c..0519cc7 100644 --- a/XUnitTest/RedisTest.cs +++ b/XUnitTest/RedisTest.cs @@ -541,4 +541,44 @@ public class RedisTest Assert.NotNull(ex); Assert.Equal("命令[SET]的数据包大小[1060]超过最大限制[1028],大key会拖累整个Redis实例,可通过Redis.MaxMessageSize调节。", ex.Message); } + + [Fact] + public void EvalLua() + { + var ic = _redis; + var key = "LuaTest"; + ic.Remove(key); + var script = @" + local key = KEYS[1] + local value = ARGV[1] + redis.call('SET', key, value) + return redis.call('GET', key) + "; + var rs = ic.Execute(null, (r, k) => r.Execute("EVAL", script, 1, key, "大石头")); + Assert.Equal("大石头", rs); + + // 删除 + ic.Remove(key); + rs = ic.Execute(null, (r, k) => r.Execute("EVAL", script, 1, key, "新生命")); + Assert.Equal("新生命", rs); + } + + [Fact] + public void EvalLua2() + { + var ic = _redis; + var key = "LuaTest2"; + ic.Set(key, 666); + var script = @" + local key = KEYS[1] + local value = ARGV[1] + return redis.call('INCRBY', key, value) + "; + var rs = ic.Execute(null, (r, k) => r.Execute("EVAL", script, 1, key, 123)); + Assert.Equal(666 + 123, rs); + + // 删除 + ic.Remove(key); + + } } \ No newline at end of file