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

Commit ea6235e

Browse files
committed
Add support for running RedisData/RedisText operations in a Transaction
1 parent a6a4483 commit ea6235e

File tree

7 files changed

+139
-37
lines changed

7 files changed

+139
-37
lines changed

src/ServiceStack.Redis/Pipeline/QueuedRedisOperation.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ internal class QueuedRedisOperation
1919
public Func<List<string>> MultiStringReadCommand { get; set; }
2020
public Func<Dictionary<string, string>> DictionaryStringReadCommand { get; set; }
2121
public Func<double> DoubleReadCommand { get; set; }
22+
public Func<RedisData> RedisDataReadCommand { get; set; }
2223

2324
public Action OnSuccessVoidCallback { get; set; }
2425
public Action<int> OnSuccessIntCallback { get; set; }
@@ -29,6 +30,8 @@ internal class QueuedRedisOperation
2930
public Action<string> OnSuccessStringCallback { get; set; }
3031
public Action<List<string>> OnSuccessMultiStringCallback { get; set; }
3132
public Action<Dictionary<string, string>> OnSuccessDictionaryStringCallback { get; set; }
33+
public Action<RedisData> OnSuccessRedisDataCallback { get; set; }
34+
public Action<RedisText> OnSuccessRedisTextCallback { get; set; }
3235
public Action<double> OnSuccessDoubleCallback { get; set; }
3336

3437
public Action<string> OnSuccessTypeCallback { get; set; }
@@ -166,6 +169,18 @@ public void ProcessResult()
166169
OnSuccessMultiStringCallback(result);
167170
}
168171
}
172+
else if (RedisDataReadCommand != null)
173+
{
174+
var data = RedisDataReadCommand();
175+
if (OnSuccessRedisTextCallback != null)
176+
{
177+
OnSuccessRedisTextCallback(data.ToRedisText());
178+
}
179+
if (OnSuccessRedisDataCallback != null)
180+
{
181+
OnSuccessRedisDataCallback(data);
182+
}
183+
}
169184
}
170185
catch (Exception ex)
171186
{

src/ServiceStack.Redis/Pipeline/RedisCommand.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ internal class RedisCommand : QueuedRedisOperation
2020
public Func<IRedisClient, string> StringReturnCommand { get; set; }
2121
public Func<IRedisClient, List<string>> MultiStringReturnCommand { get; set; }
2222
public Func<IRedisClient, Dictionary<string, string>> DictionaryStringReturnCommand { get; set; }
23+
public Func<IRedisClient, RedisData> RedisDataReturnCommand { get; set; }
24+
public Func<IRedisClient, RedisText> RedisTextReturnCommand { get; set; }
2325
public Func<IRedisClient, double> DoubleReturnCommand { get; set; }
2426

2527
public override void Execute(IRedisClient client)
@@ -69,6 +71,14 @@ public override void Execute(IRedisClient client)
6971
{
7072
DictionaryStringReturnCommand(client);
7173
}
74+
else if (RedisDataReturnCommand != null)
75+
{
76+
RedisDataReturnCommand(client);
77+
}
78+
else if (RedisTextReturnCommand != null)
79+
{
80+
RedisTextReturnCommand(client);
81+
}
7282
}
7383
catch (Exception ex)
7484
{

src/ServiceStack.Redis/Pipeline/RedisCommandQueue.cs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,5 +269,49 @@ public void QueueCommand(Func<IRedisClient, Dictionary<string, string>> command,
269269
});
270270
command(RedisClient);
271271
}
272+
273+
274+
public void QueueCommand(Func<IRedisClient, RedisData> command)
275+
{
276+
QueueCommand(command, null, null);
277+
}
278+
279+
public void QueueCommand(Func<IRedisClient, RedisData> command, Action<RedisData> onSuccessCallback)
280+
{
281+
QueueCommand(command, onSuccessCallback, null);
282+
}
283+
284+
public void QueueCommand(Func<IRedisClient, RedisData> command, Action<RedisData> onSuccessCallback, Action<Exception> onErrorCallback)
285+
{
286+
BeginQueuedCommand(new QueuedRedisCommand
287+
{
288+
RedisDataReturnCommand = command,
289+
OnSuccessRedisDataCallback = onSuccessCallback,
290+
OnErrorCallback = onErrorCallback
291+
});
292+
command(RedisClient);
293+
}
294+
295+
296+
public void QueueCommand(Func<IRedisClient, RedisText> command)
297+
{
298+
QueueCommand(command, null, null);
299+
}
300+
301+
public void QueueCommand(Func<IRedisClient, RedisText> command, Action<RedisText> onSuccessCallback)
302+
{
303+
QueueCommand(command, onSuccessCallback, null);
304+
}
305+
306+
public void QueueCommand(Func<IRedisClient, RedisText> command, Action<RedisText> onSuccessCallback, Action<Exception> onErrorCallback)
307+
{
308+
BeginQueuedCommand(new QueuedRedisCommand
309+
{
310+
RedisTextReturnCommand = command,
311+
OnSuccessRedisTextCallback = onSuccessCallback,
312+
OnErrorCallback = onErrorCallback
313+
});
314+
command(RedisClient);
315+
}
272316
}
273317
}

src/ServiceStack.Redis/Pipeline/RedisQueueCompletableOperation.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,15 @@ public virtual void CompleteDoubleQueuedCommand(Func<double> doubleReadCommand)
113113
AddCurrentQueuedOperation();
114114
}
115115

116+
public virtual void CompleteRedisDataQueuedCommand(Func<RedisData> redisDataReadCommand)
117+
{
118+
//AssertCurrentOperation();
119+
// this can happen when replaying pipeline/transaction
120+
if (CurrentQueuedOperation == null) return;
121+
122+
CurrentQueuedOperation.RedisDataReadCommand = redisDataReadCommand;
123+
AddCurrentQueuedOperation();
124+
}
116125

117126
}
118127
}

src/ServiceStack.Redis/RedisDataExtensions.cs

Lines changed: 38 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -4,41 +4,43 @@ namespace ServiceStack.Redis
44
{
55
public static class RedisDataExtensions
66
{
7-
public static RedisText ToRedisText(this RedisData data)
8-
{
9-
var to = new RedisText();
10-
11-
if (data.Data != null)
12-
to.Text = data.Data.FromUtf8Bytes();
13-
14-
if (data.Children != null)
15-
to.Children = data.Children.ConvertAll(x => x.ToRedisText());
16-
17-
return to;
18-
}
19-
20-
public static string GetResult(this RedisText from)
21-
{
22-
return from.Text;
23-
}
24-
25-
public static T GetResult<T>(this RedisText from)
26-
{
27-
return from.Text.FromJson<T>();
28-
}
29-
30-
public static List<string> GetResults(this RedisText from)
31-
{
32-
return from.Children == null
33-
? new List<string>()
34-
: from.Children.ConvertAll(x => x.Text);
35-
}
36-
37-
public static List<T> GetResults<T>(this RedisText from)
38-
{
39-
return from.Children == null
40-
? new List<T>()
41-
: from.Children.ConvertAll(x => x.Text.FromJson<T>());
42-
}
7+
public static RedisText ToRedisText(this RedisData data)
8+
{
9+
if (data == null) return null; //In Transaction
10+
11+
var to = new RedisText();
12+
13+
if (data.Data != null)
14+
to.Text = data.Data.FromUtf8Bytes();
15+
16+
if (data.Children != null)
17+
to.Children = data.Children.ConvertAll(x => x.ToRedisText());
18+
19+
return to;
20+
}
21+
22+
public static string GetResult(this RedisText from)
23+
{
24+
return from.Text;
25+
}
26+
27+
public static T GetResult<T>(this RedisText from)
28+
{
29+
return from.Text.FromJson<T>();
30+
}
31+
32+
public static List<string> GetResults(this RedisText from)
33+
{
34+
return from.Children == null
35+
? new List<string>()
36+
: from.Children.ConvertAll(x => x.Text);
37+
}
38+
39+
public static List<T> GetResults<T>(this RedisText from)
40+
{
41+
return from.Children == null
42+
? new List<T>()
43+
: from.Children.ConvertAll(x => x.Text.FromJson<T>());
44+
}
4345
}
4446
}

src/ServiceStack.Redis/RedisNativeClient_Utils.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -661,7 +661,7 @@ protected object[] SendExpectDeeplyNestedMultiData(params byte[][] cmdWithBinary
661661

662662
protected RedisData SendExpectComplexResponse(params byte[][] cmdWithBinaryArgs)
663663
{
664-
return SendReceive(cmdWithBinaryArgs, ReadComplexResponse);
664+
return SendReceive(cmdWithBinaryArgs, ReadComplexResponse, Pipeline != null ? Pipeline.CompleteRedisDataQueuedCommand : (Action<Func<RedisData>>)null);
665665
}
666666

667667
protected string SendExpectString(params byte[][] cmdWithBinaryArgs)

tests/ServiceStack.Redis.Tests/RedisTransactionTests.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,5 +381,27 @@ public void Can_call_HashSet_commands_in_transaction()
381381

382382
Assert.That(result, Is.EquivalentTo(new[] { "ITEM 1", "ITEM 2" }));
383383
}
384+
385+
[Test]
386+
public void Can_call_LUA_Script_in_transaction()
387+
{
388+
using (var trans = Redis.CreateTransaction())
389+
{
390+
trans.QueueCommand(r => r.ExecLua("return {'myval', 'myotherval'}"));
391+
392+
trans.Commit();
393+
}
394+
395+
RedisText result = null;
396+
using (var trans = Redis.CreateTransaction())
397+
{
398+
trans.QueueCommand(r => r.ExecLua("return {'myval', 'myotherval'}"), s => result = s);
399+
400+
trans.Commit();
401+
}
402+
403+
Assert.That(result.Children[0].Text, Is.EqualTo("myval"));
404+
Assert.That(result.Children[1].Text, Is.EqualTo("myotherval"));
405+
}
384406
}
385407
}

0 commit comments

Comments
 (0)