Skip to content
This repository was archived by the owner on Dec 24, 2022. It is now read-only.

Commit 2d0e210

Browse files
committed
Add lua script and equivalent c# code using pipelines
1 parent 0e4a641 commit 2d0e210

File tree

1 file changed

+147
-1
lines changed

1 file changed

+147
-1
lines changed

tests/ServiceStack.Redis.Tests/LuaCachedScripts.cs

Lines changed: 147 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
using NUnit.Framework;
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using NUnit.Framework;
24
using ServiceStack.Text;
35

46
namespace ServiceStack.Redis.Tests
@@ -80,5 +82,149 @@ public void Can_call_Cached_Lua_even_after_script_is_flushed()
8082
Assert.That(r.Children.Count, Is.EqualTo(10));
8183
}
8284
}
85+
86+
private const string KeyAttributesScript = @"
87+
local limit = tonumber(ARGV[2])
88+
local pattern = ARGV[1]
89+
local cursor = 0
90+
local len = 0
91+
local keys = {}
92+
93+
repeat
94+
local r = redis.call('scan', cursor, 'MATCH', pattern, 'COUNT', limit)
95+
cursor = tonumber(r[1])
96+
for k,v in ipairs(r[2]) do
97+
table.insert(keys, v)
98+
len = len + 1
99+
if len == limit then break end
100+
end
101+
until cursor == 0 or len == limit
102+
103+
local keyAttrs = {}
104+
for i,key in ipairs(keys) do
105+
local type = redis.call('type', key)['ok']
106+
local pttl = redis.call('pttl', key)
107+
local size = 0
108+
if type == 'string' then
109+
size = redis.call('strlen', key)
110+
elseif type == 'list' then
111+
size = redis.call('llen', key)
112+
elseif type == 'set' then
113+
size = redis.call('scard', key)
114+
elseif type == 'zset' then
115+
size = redis.call('zcard', key)
116+
elseif type == 'hash' then
117+
size = redis.call('hlen', key)
118+
end
119+
120+
local attrs = {['id'] = key, ['type'] = type, ['ttl'] = pttl, ['size'] = size}
121+
122+
table.insert(keyAttrs, attrs)
123+
end
124+
125+
return cjson.encode(keyAttrs)";
126+
127+
[Test]
128+
public void Can_call_script_with_complex_response()
129+
{
130+
using (var redis = new RedisClient())
131+
{
132+
var r = redis.ExecCachedLua(KeyAttributesScript, sha1 =>
133+
redis.ExecLuaShaAsString(sha1, "key:*", "10"));
134+
135+
r.Print();
136+
137+
var results = r.FromJson<List<SearchResult>>();
138+
139+
Assert.That(results.Count, Is.EqualTo(10));
140+
141+
var result = results[0];
142+
Assert.That(result.Id.StartsWith("key:"));
143+
Assert.That(result.Type, Is.EqualTo("string"));
144+
Assert.That(result.Size, Is.GreaterThan("value:".Length));
145+
Assert.That(result.Ttl, Is.EqualTo(-1));
146+
}
147+
}
148+
149+
public class SearchResult
150+
{
151+
public string Id { get; set; }
152+
public string Type { get; set; }
153+
public long Ttl { get; set; }
154+
public long Size { get; set; }
155+
}
156+
157+
[Test]
158+
public void Can_merge_multiple_SearchResults()
159+
{
160+
var Redis = new RedisClient();
161+
var limit = 10;
162+
var query = "key:*";
163+
164+
var keys = Redis.ScanAllKeys(pattern: query, pageSize: limit)
165+
.Take(limit).ToList();
166+
167+
var keyTypes = new Dictionary<string, string>();
168+
var keyTtls = new Dictionary<string, long>();
169+
var keySizes = new Dictionary<string, long>();
170+
171+
if (keys.Count > 0)
172+
{
173+
using (var pipeline = Redis.CreatePipeline())
174+
{
175+
keys.Each(key =>
176+
pipeline.QueueCommand(r => r.Type(key), x => keyTypes[key] = x));
177+
178+
keys.Each(key =>
179+
pipeline.QueueCommand(r => ((RedisNativeClient)r).PTtl(key), x => keyTtls[key] = x));
180+
181+
pipeline.Flush();
182+
}
183+
184+
using (var pipeline = Redis.CreatePipeline())
185+
{
186+
foreach (var entry in keyTypes)
187+
{
188+
var key = entry.Key;
189+
switch (entry.Value)
190+
{
191+
case "string":
192+
pipeline.QueueCommand(r => r.GetStringCount(key), x => keySizes[key] = x);
193+
break;
194+
case "list":
195+
pipeline.QueueCommand(r => r.GetListCount(key), x => keySizes[key] = x);
196+
break;
197+
case "set":
198+
pipeline.QueueCommand(r => r.GetSetCount(key), x => keySizes[key] = x);
199+
break;
200+
case "zset":
201+
pipeline.QueueCommand(r => r.GetSortedSetCount(key), x => keySizes[key] = x);
202+
break;
203+
case "hash":
204+
pipeline.QueueCommand(r => r.GetHashCount(key), x => keySizes[key] = x);
205+
break;
206+
}
207+
}
208+
209+
pipeline.Flush();
210+
}
211+
}
212+
213+
var results = keys.Map(x => new SearchResult
214+
{
215+
Id = x,
216+
Type = keyTypes.GetValueOrDefault(x),
217+
Ttl = keyTtls.GetValueOrDefault(x),
218+
Size = keySizes.GetValueOrDefault(x),
219+
});
220+
221+
Assert.That(results.Count, Is.EqualTo(limit));
222+
223+
var result = results[0];
224+
Assert.That(result.Id.StartsWith("key:"));
225+
Assert.That(result.Type, Is.EqualTo("string"));
226+
Assert.That(result.Size, Is.GreaterThan("value:".Length));
227+
Assert.That(result.Ttl, Is.EqualTo(-1));
228+
}
83229
}
84230
}

0 commit comments

Comments
 (0)