1
+ using System ;
2
+ using System . Collections . Generic ;
3
+ using System . Linq ;
4
+ using System . Threading ;
5
+ using ServiceStack . Redis ;
6
+ using ServiceStack . Redis . Generic ;
7
+ using ServiceStack . Text ;
8
+
9
+ namespace TestRedisConnection
10
+ {
11
+ public class HashCollectionStressTests
12
+ {
13
+ private IRedisClientsManager clientsManager ;
14
+ private int running = 0 ;
15
+ private long writeCount = 0 ;
16
+ private long readCount = 0 ;
17
+
18
+ public void Execute ( string ipAddress , int noOfThreads = 64 )
19
+ {
20
+ clientsManager = new PooledRedisClientManager ( ipAddress ) ;
21
+
22
+ var StartedAt = DateTime . UtcNow ;
23
+ Interlocked . Increment ( ref running ) ;
24
+
25
+ "Starting HashCollectionStressTests with {0} threads" . Print ( noOfThreads ) ;
26
+ var threads = new List < Thread > ( ) ;
27
+ for ( int i = 0 ; i < noOfThreads ; i ++ )
28
+ {
29
+ threads . Add ( new Thread ( WorkerLoop ) ) ;
30
+ }
31
+ threads . ForEach ( t => t . Start ( ) ) ;
32
+
33
+ "Press Enter to Stop..." . Print ( ) ;
34
+ Console . ReadLine ( ) ;
35
+
36
+ Interlocked . Decrement ( ref running ) ;
37
+
38
+ "Writes: {0}, Reads: {1}" . Print ( writeCount , readCount ) ;
39
+ "{0} EndedAt: {1}" . Print ( GetType ( ) . Name , DateTime . UtcNow . ToLongTimeString ( ) ) ;
40
+ "{0} TimeTaken: {1}s" . Print ( GetType ( ) . Name , ( DateTime . UtcNow - StartedAt ) . TotalSeconds ) ;
41
+
42
+ "\n Press Enter to Quit..." . Print ( ) ;
43
+ Console . ReadLine ( ) ;
44
+ }
45
+
46
+ public void WorkerLoop ( )
47
+ {
48
+ while ( Interlocked . CompareExchange ( ref running , 0 , 0 ) > 0 )
49
+ {
50
+ var redisCollection = new RedisCachedCollection < string , string > (
51
+ clientsManager , "Thread: " + Thread . CurrentThread . ManagedThreadId ) ;
52
+
53
+ redisCollection . ContainsKey ( "key" ) ;
54
+ Interlocked . Increment ( ref readCount ) ;
55
+
56
+ redisCollection [ "key" ] = "value " + readCount ;
57
+ Interlocked . Increment ( ref writeCount ) ;
58
+
59
+ var value = redisCollection [ "key" ] ;
60
+ Interlocked . Increment ( ref readCount ) ;
61
+
62
+ if ( value == null )
63
+ Console . WriteLine ( "value == null" ) ;
64
+ }
65
+ }
66
+ }
67
+
68
+ public class RedisCachedCollection < TKey , TValue > : IEnumerable < TValue >
69
+ {
70
+ private readonly string collectionKey ;
71
+ private Func < TValue , TKey > idAction ;
72
+ private readonly IRedisClientsManager clientsManager ;
73
+
74
+ public RedisCachedCollection ( IRedisClientsManager clientsManager , string collectionKey )
75
+ {
76
+ this . clientsManager = clientsManager ;
77
+ this . collectionKey = string . Format ( "urn:{0}:{1}" , "XXXXX" , collectionKey ) ;
78
+ }
79
+
80
+ public IRedisClient RedisConnection
81
+ {
82
+ get
83
+ {
84
+ return clientsManager . GetClient ( ) ;
85
+ }
86
+ }
87
+
88
+ private IRedisHash < TKey , TValue > GetCollection ( IRedisClient redis )
89
+ {
90
+ var _redisTypedClient = redis . As < TValue > ( ) ;
91
+ return _redisTypedClient . GetHash < TKey > ( collectionKey ) ;
92
+ }
93
+
94
+ public void Add ( TValue obj )
95
+ {
96
+ TKey Id = GetUniqueIdAction ( obj ) ;
97
+
98
+ RetryAction ( ( redis ) =>
99
+ {
100
+ GetCollection ( redis ) . Add ( Id , obj ) ;
101
+ } ) ;
102
+ }
103
+
104
+ public bool Remove ( TValue obj )
105
+ {
106
+ TKey Id = GetUniqueIdAction ( obj ) ;
107
+ TKey defaultv = default ( TKey ) ;
108
+
109
+ return RetryAction < bool > ( ( redis ) =>
110
+ {
111
+ if ( ! Id . Equals ( defaultv ) )
112
+ {
113
+ {
114
+ return GetCollection ( redis ) . Remove ( Id ) ;
115
+ }
116
+ }
117
+ return false ;
118
+ } ) ;
119
+
120
+ }
121
+
122
+ public TValue this [ TKey id ]
123
+ {
124
+ get
125
+ {
126
+ return RetryAction < TValue > ( ( redis ) =>
127
+ {
128
+ if ( GetCollection ( redis ) . ContainsKey ( id ) )
129
+ return GetCollection ( redis ) [ id ] ;
130
+ return default ( TValue ) ;
131
+ } ) ;
132
+ }
133
+ set
134
+ {
135
+ RetryAction ( ( redis ) =>
136
+ {
137
+ GetCollection ( redis ) [ id ] = value ;
138
+ } ) ;
139
+ }
140
+ }
141
+ public int Count
142
+ {
143
+ get
144
+ {
145
+ return RetryAction < int > ( ( redis ) =>
146
+ {
147
+ return GetCollection ( redis ) . Count ;
148
+ } ) ;
149
+ }
150
+ }
151
+
152
+ public IEnumerable < TValue > Where ( Func < TValue , bool > predicate )
153
+ {
154
+ return RetryAction ( ( redis ) =>
155
+ {
156
+ return GetCollection ( redis ) . Values . Where ( predicate ) ;
157
+ } ) ;
158
+ }
159
+
160
+ public bool Any ( Func < TValue , bool > predicate )
161
+ {
162
+ return RetryAction < bool > ( ( redis ) =>
163
+ {
164
+ return GetCollection ( redis ) . Values . Any ( predicate ) ;
165
+ } ) ;
166
+ }
167
+
168
+
169
+ public IEnumerator < TValue > GetEnumerator ( )
170
+ {
171
+ return RetryAction < IEnumerator < TValue > > ( ( redis ) =>
172
+ {
173
+ return GetCollection ( redis ) . Values . GetEnumerator ( ) ;
174
+ } ) ;
175
+ }
176
+
177
+ System . Collections . IEnumerator System . Collections . IEnumerable . GetEnumerator ( )
178
+ {
179
+ return RetryAction ( redis =>
180
+ {
181
+ return ( ( System . Collections . IEnumerable ) GetCollection ( redis ) . Values ) . GetEnumerator ( ) ;
182
+ } ) ;
183
+
184
+ }
185
+
186
+ public void Clear ( )
187
+ {
188
+ RetryAction ( ( redis ) =>
189
+ {
190
+ GetCollection ( redis ) . Clear ( ) ;
191
+ } ) ;
192
+ }
193
+
194
+ public bool Contains ( TValue obj )
195
+ {
196
+ TKey Id = GetUniqueIdAction ( obj ) ;
197
+ return RetryAction < bool > ( ( redis ) =>
198
+ {
199
+ return GetCollection ( redis ) . ContainsKey ( Id ) ;
200
+ } ) ;
201
+ }
202
+
203
+ public bool ContainsKey ( TKey obj )
204
+ {
205
+ return RetryAction < bool > ( ( redis ) =>
206
+ {
207
+ return GetCollection ( redis ) . ContainsKey ( obj ) ;
208
+ } ) ;
209
+ }
210
+
211
+ public void CopyTo ( TValue [ ] array , int arrayIndex )
212
+ {
213
+ RetryAction ( ( redis ) =>
214
+ {
215
+ GetCollection ( redis ) . Values . CopyTo ( array , arrayIndex ) ;
216
+ } ) ;
217
+ }
218
+
219
+ public bool IsReadOnly
220
+ {
221
+ get
222
+ {
223
+ return RetryAction < bool > ( ( redis ) =>
224
+ {
225
+ return GetCollection ( redis ) . IsReadOnly ;
226
+ } ) ;
227
+ }
228
+ }
229
+
230
+ public Func < TValue , TKey > GetUniqueIdAction
231
+ {
232
+ get
233
+ {
234
+ return idAction ;
235
+ }
236
+ set
237
+ {
238
+ idAction = value ;
239
+ }
240
+ }
241
+
242
+ private void RetryAction ( Action < IRedisClient > action )
243
+ {
244
+ int i = 0 ;
245
+ while ( true )
246
+ {
247
+ try
248
+ {
249
+ using ( var redis = RedisConnection )
250
+ {
251
+ action ( redis ) ;
252
+ return ;
253
+ }
254
+ }
255
+ catch ( Exception ex )
256
+ {
257
+ Console . WriteLine ( ex ) ;
258
+ throw ;
259
+
260
+ //if (i++ < 3)
261
+ //{
262
+ // continue;
263
+ //}
264
+ //throw;
265
+ }
266
+ }
267
+ }
268
+
269
+ private TOut RetryAction < TOut > ( Func < IRedisClient , TOut > action )
270
+ {
271
+ int i = 0 ;
272
+
273
+ while ( true )
274
+ {
275
+ try
276
+ {
277
+ using ( var redis = RedisConnection )
278
+ {
279
+ TOut result = action ( redis ) ;
280
+ return result ;
281
+ }
282
+ }
283
+ catch ( Exception ex )
284
+ {
285
+
286
+ if ( i ++ < 3 )
287
+ {
288
+
289
+ continue ;
290
+ }
291
+
292
+ throw ;
293
+ }
294
+ }
295
+ }
296
+ }
297
+ }
0 commit comments