Skip to content

Commit bb93907

Browse files
Aaron BoxerAaron Boxer
authored andcommitted
1. when completing queued operations, simply return if there is no current queued op,
rather than throwing exception: this situation can occur when replaying pipeline/transaction 2. now re-throwing exception when completing queued op 3. added some tests for above fixes
1 parent 6aac9f2 commit bb93907

3 files changed

Lines changed: 94 additions & 8 deletions

File tree

src/ServiceStack.Redis/Pipeline/RedisQueueCompletableOperation.cs

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,63 +35,79 @@ protected virtual void AddCurrentQueuedOperation()
3535

3636
public virtual void CompleteVoidQueuedCommand(Action voidReadCommand)
3737
{
38-
AssertCurrentOperation();
38+
//AssertCurrentOperation();
39+
// this can happen when replaying pipeline/transaction
40+
if (CurrentQueuedOperation == null) return;
3941

4042
CurrentQueuedOperation.VoidReadCommand = voidReadCommand;
4143
AddCurrentQueuedOperation();
4244
}
4345

4446
public virtual void CompleteIntQueuedCommand(Func<int> intReadCommand)
4547
{
46-
AssertCurrentOperation();
48+
//AssertCurrentOperation();
49+
// this can happen when replaying pipeline/transaction
50+
if (CurrentQueuedOperation == null) return;
4751

4852
CurrentQueuedOperation.IntReadCommand = intReadCommand;
4953
AddCurrentQueuedOperation();
5054
}
5155

5256
public virtual void CompleteLongQueuedCommand(Func<long> longReadCommand)
5357
{
54-
AssertCurrentOperation();
58+
//AssertCurrentOperation();
59+
// this can happen when replaying pipeline/transaction
60+
if (CurrentQueuedOperation == null) return;
5561

5662
CurrentQueuedOperation.LongReadCommand = longReadCommand;
5763
AddCurrentQueuedOperation();
5864
}
5965

6066
public virtual void CompleteBytesQueuedCommand(Func<byte[]> bytesReadCommand)
6167
{
62-
AssertCurrentOperation();
68+
//AssertCurrentOperation();
69+
// this can happen when replaying pipeline/transaction
70+
if (CurrentQueuedOperation == null) return;
6371

6472
CurrentQueuedOperation.BytesReadCommand = bytesReadCommand;
6573
AddCurrentQueuedOperation();
6674
}
6775

6876
public virtual void CompleteMultiBytesQueuedCommand(Func<byte[][]> multiBytesReadCommand)
6977
{
70-
AssertCurrentOperation();
78+
//AssertCurrentOperation();
79+
// this can happen when replaying pipeline/transaction
80+
if (CurrentQueuedOperation == null) return;
7181

7282
CurrentQueuedOperation.MultiBytesReadCommand = multiBytesReadCommand;
7383
AddCurrentQueuedOperation();
7484
}
7585

7686
public virtual void CompleteStringQueuedCommand(Func<string> stringReadCommand)
7787
{
78-
AssertCurrentOperation();
88+
//AssertCurrentOperation();
89+
// this can happen when replaying pipeline/transaction
90+
if (CurrentQueuedOperation == null) return;
7991

8092
CurrentQueuedOperation.StringReadCommand = stringReadCommand;
8193
AddCurrentQueuedOperation();
8294
}
8395

8496
public virtual void CompleteMultiStringQueuedCommand(Func<List<string>> multiStringReadCommand)
8597
{
86-
AssertCurrentOperation();
98+
//AssertCurrentOperation();
99+
// this can happen when replaying pipeline/transaction
100+
if (CurrentQueuedOperation == null) return;
87101

88102
CurrentQueuedOperation.MultiStringReadCommand = multiStringReadCommand;
89103
AddCurrentQueuedOperation();
90104
}
91105

92106
public virtual void CompleteDoubleQueuedCommand(Func<double> doubleReadCommand)
93107
{
94-
AssertCurrentOperation();
108+
//AssertCurrentOperation();
109+
// this can happen when replaying pipeline/transaction
110+
if (CurrentQueuedOperation == null) return;
95111

96112
CurrentQueuedOperation.DoubleReadCommand = doubleReadCommand;
97113
AddCurrentQueuedOperation();

tests/ServiceStack.Redis.Tests/RedisPipelineTests.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,29 @@ public void Can_call_single_operation_3_Times_in_pipeline()
7373

7474
Assert.That(Redis.GetValue(Key), Is.EqualTo("3"));
7575
}
76+
[Test]
77+
public void Can_call_multiple_setexs_in_pipeline()
78+
{
79+
Assert.That(Redis.GetValue(Key), Is.Null);
80+
var keys = new[] {"key1", "key2", "key3"};
81+
var values = new[] { "1","2","3" };
82+
var pipeline = Redis.CreatePipeline();
83+
84+
for (int i = 0; i < 3; ++i )
85+
{
86+
int index0 = i;
87+
pipeline.QueueCommand(r => ((RedisNativeClient)r).SetEx(keys[index0], 100, GetBytes(values[index0])));
88+
}
89+
90+
pipeline.Flush();
91+
pipeline.Replay();
92+
93+
94+
for (int i = 0; i < 3; ++i )
95+
Assert.AreEqual(Redis.GetValue(keys[i]), values[i]);
96+
97+
pipeline.Dispose();
98+
}
7699

77100
[Test]
78101
public void Can_call_single_operation_with_callback_3_Times_in_pipeline()

tests/ServiceStack.Redis.Tests/RedisTransactionTests.cs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,30 @@ public void No_commit_of_atomic_transactions_discards_all_commands()
4040
Assert.That(Redis.GetValue(Key), Is.Null);
4141
}
4242

43+
[Test]
44+
public void Watch_aborts_transaction()
45+
{
46+
Assert.That(Redis.GetValue(Key), Is.Null);
47+
const string value1 = "value1";
48+
const string value2 = "value2";
49+
try
50+
{
51+
Redis.Watch(Key);
52+
Redis.Set(Key, value1);
53+
using (var trans = Redis.CreateTransaction())
54+
{
55+
trans.QueueCommand(r => r.Set(Key,value1));
56+
var success = trans.Commit();
57+
Assert.False(success);
58+
Assert.AreEqual(Redis.GetValue(Key), value1);
59+
}
60+
}
61+
catch (NotSupportedException ignore)
62+
{
63+
Assert.That(Redis.GetValue(Key), Is.Null);
64+
}
65+
}
66+
4367
[Test]
4468
public void Exception_in_atomic_transactions_discards_all_commands()
4569
{
@@ -153,6 +177,29 @@ public void Can_call_multi_string_operations_in_transaction()
153177
Assert.That(item4, Is.Null);
154178
}
155179
[Test]
180+
public void Can_call_multiple_setexs_in_transaction()
181+
{
182+
Assert.That(Redis.GetValue(Key), Is.Null);
183+
var keys = new[] { "key1", "key2", "key3" };
184+
var values = new[] { "1", "2", "3" };
185+
var trans = Redis.CreateTransaction();
186+
187+
for (int i = 0; i < 3; ++i)
188+
{
189+
int index0 = i;
190+
trans.QueueCommand(r => ((RedisNativeClient)r).SetEx(keys[index0], 100, GetBytes(values[index0])));
191+
}
192+
193+
trans.Commit();
194+
trans.Replay();
195+
196+
197+
for (int i = 0; i < 3; ++i)
198+
Assert.AreEqual(Redis.GetValue(keys[i]), values[i]);
199+
200+
trans.Dispose();
201+
}
202+
[Test]
156203
// Operations that are not supported in older versions will look at server info to determine what to do.
157204
// If server info is fetched each time, then it will interfer with transaction
158205
public void Can_call_operation_not_supported_on_older_servers_in_transaction()

0 commit comments

Comments
 (0)