This repository has been archived by the owner on Dec 24, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 873
/
SimpleLocks.cs
152 lines (128 loc) · 5.4 KB
/
SimpleLocks.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using NUnit.Framework;
namespace ServiceStack.Redis.Tests.Examples
{
[TestFixture, Ignore("Integration"), Category("Integration")]
public class SimpleLocks
{
[SetUp]
public void OnTestFixtureSetUp()
{
using (var redisClient = new RedisClient(TestConfig.SingleHost))
{
redisClient.FlushAll();
}
}
[Test]
public void Use_multiple_redis_clients_to_safely_execute()
{
//The number of concurrent clients to run
const int noOfClients = 5;
var asyncResults = new List<IAsyncResult>(noOfClients);
for (var i = 1; i <= noOfClients; i++)
{
var clientNo = i;
var actionFn = (Action)delegate
{
var redisClient = new RedisClient(TestConfig.SingleHost);
using (redisClient.AcquireLock("testlock"))
{
Debug.WriteLine(String.Format("client {0} acquired lock", clientNo));
var counter = redisClient.Get<int>("atomic-counter");
//Add an artificial delay to demonstrate locking behaviour
Thread.Sleep(100);
redisClient.Set("atomic-counter", counter + 1);
Debug.WriteLine(String.Format("client {0} released lock", clientNo));
}
};
//Asynchronously invoke the above delegate in a background thread
asyncResults.Add(actionFn.BeginInvoke(null, null));
}
//Wait at most 1 second for all the threads to complete
asyncResults.WaitAll(TimeSpan.FromSeconds(1));
//Print out the 'atomic-counter' result
using (var redisClient = new RedisClient(TestConfig.SingleHost))
{
var counter = redisClient.Get<int>("atomic-counter");
Debug.WriteLine(String.Format("atomic-counter after 1sec: {0}", counter));
}
}
[Test]
public void Acquiring_lock_with_timeout()
{
var redisClient = new RedisClient(TestConfig.SingleHost);
//Initialize and set counter to '1'
redisClient.IncrementValue("atomic-counter");
//Acquire lock and never release it
redisClient.AcquireLock("testlock");
var waitFor = TimeSpan.FromSeconds(2);
var now = DateTime.Now;
try
{
using (var newClient = new RedisClient(TestConfig.SingleHost))
{
//Attempt to acquire a lock with a 2 second timeout
using (newClient.AcquireLock("testlock", waitFor))
{
//If lock was acquired this would be incremented to '2'
redisClient.IncrementValue("atomic-counter");
}
}
}
catch (TimeoutException tex)
{
var timeTaken = DateTime.Now - now;
Debug.WriteLine(String.Format("After '{0}', Received TimeoutException: '{1}'", timeTaken, tex.Message));
var counter = redisClient.Get<int>("atomic-counter");
Debug.WriteLine(String.Format("atomic-counter remains at '{0}'", counter));
}
}
[Test]
public void SimulateLockTimeout()
{
var redisClient = new RedisClient(TestConfig.SingleHost);
var waitFor = TimeSpan.FromMilliseconds(20);
var loc = redisClient.AcquireLock("testlock", waitFor);
Thread.Sleep(100); //should have lock expire
using (var newloc = redisClient.AcquireLock("testlock", waitFor))
{
}
}
[Test]
public void AcquireLock_using_Tasks()
{
const int noOfClients = 4;
var tasks = new Task[noOfClients];
for (var i = 0; i < noOfClients; i++)
{
Thread.Sleep(2000);
tasks[i] = Task.Factory.StartNew((object clientNo) =>
{
try
{
Console.WriteLine("About to process " + clientNo);
//var redisClient = new RedisClient("xxxx.redis.cache.windows.net", 6379, "xxxx");
var redisClient = new RedisClient(TestConfig.SingleHost, 6379);
using (redisClient.AcquireLock("testlock1", TimeSpan.FromMinutes(3)))
{
Console.WriteLine("client {0} acquired lock", (int)clientNo);
var counter = redisClient.Get<int>("atomic-counter");
//Add an artificial delay to demonstrate locking behaviour
Thread.Sleep(100);
redisClient.Set("atomic-counter", counter + 1);
Console.WriteLine("client {0} released lock", (int)clientNo);
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}, i + 1);
}
}
}
}