Skip to content

Commit 7bcc815

Browse files
author
Thomas Grassauer
committed
added wrapper for values stored in memcached
1 parent 0c9074e commit 7bcc815

6 files changed

Lines changed: 140 additions & 46 deletions

File tree

lib/Enyim.Caching.dll

-65.5 KB
Binary file not shown.

src/ServiceStack.CacheAccess.Memcached/AdapterBase.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,17 @@ public abstract class AdapterBase
2020
protected T Execute<T>(Func<T> action)
2121
{
2222
DateTime before = DateTime.Now;
23-
this.Log.DebugFormat("Executing action '{0}'", action.Method.Name);
23+
Log.DebugFormat("Executing action '{0}'", action.Method.Name);
2424
try
2525
{
2626
T result = action();
2727
TimeSpan timeTaken = DateTime.Now - before;
28-
this.Log.DebugFormat("Action '{0}' executed. Took {1} ms.", action.Method.Name, timeTaken.TotalMilliseconds);
28+
Log.DebugFormat("Action '{0}' executed. Took {1} ms.", action.Method.Name, timeTaken.TotalMilliseconds);
2929
return result;
3030
}
3131
catch (Exception ex)
3232
{
33-
this.Log.ErrorFormat("There was an error executing Action '{0}'. Message: {1}", action.Method.Name, ex.Message);
33+
Log.ErrorFormat("There was an error executing Action '{0}'. Message: {1}", action.Method.Name, ex.Message);
3434
throw;
3535
}
3636
}
@@ -42,16 +42,16 @@ protected T Execute<T>(Func<T> action)
4242
protected void Execute(Action action)
4343
{
4444
DateTime before = DateTime.Now;
45-
this.Log.DebugFormat("Executing action '{0}'", action.Method.Name);
45+
Log.DebugFormat("Executing action '{0}'", action.Method.Name);
4646
try
4747
{
4848
action();
4949
TimeSpan timeTaken = DateTime.Now - before;
50-
this.Log.DebugFormat("Action '{0}' executed. Took {1} ms.", action.Method.Name, timeTaken.TotalMilliseconds);
50+
Log.DebugFormat("Action '{0}' executed. Took {1} ms.", action.Method.Name, timeTaken.TotalMilliseconds);
5151
}
5252
catch (Exception ex)
5353
{
54-
this.Log.ErrorFormat("There was an error executing Action '{0}'. Message: {1}", action.Method.Name, ex.Message);
54+
Log.ErrorFormat("There was an error executing Action '{0}'. Message: {1}", action.Method.Name, ex.Message);
5555
throw;
5656
}
5757
}

src/ServiceStack.CacheAccess.Memcached/MemcachedClientCache.cs

Lines changed: 57 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using Enyim.Caching;
66
using Enyim.Caching.Configuration;
77
using Enyim.Caching.Memcached;
8+
using ServiceStack.Common.Extensions;
89
using ILog = ServiceStack.Logging.ILog;
910
using LogManager = ServiceStack.Logging.LogManager;
1011

@@ -21,15 +22,16 @@ public class MemcachedClientCache
2122
{
2223
protected override ILog Log { get { return LogManager.GetLogger(GetType()); } }
2324

24-
private MemcachedClient client;
25+
private MemcachedClient _client;
2526

2627
public MemcachedClientCache(IEnumerable<string> hosts)
2728
{
2829
const int defaultPort = 11211;
2930
const int ipAddressIndex = 0;
3031
const int portIndex = 1;
3132

32-
this.client = new MemcachedClient();
33+
_client = new MemcachedClient();
34+
3335
var ipEndpoints = new List<IPEndPoint>();
3436
foreach (var host in hosts)
3537
{
@@ -67,7 +69,7 @@ private void LoadClient(IEnumerable<IPEndPoint> ipEndpoints)
6769
config.SocketPool.ConnectionTimeout = new TimeSpan(0, 0, 10);
6870
config.SocketPool.DeadTimeout = new TimeSpan(0, 2, 0);
6971

70-
this.client = new MemcachedClient(config);
72+
_client = new MemcachedClient(config);
7173
}
7274

7375
public MemcachedClientCache(MemcachedClient client)
@@ -76,22 +78,29 @@ public MemcachedClientCache(MemcachedClient client)
7678
{
7779
throw new ArgumentNullException("client");
7880
}
79-
this.client = client;
81+
_client = client;
8082
}
8183

8284
public void Dispose()
8385
{
84-
Execute(() => client.Dispose());
85-
}
86+
/*
87+
* DO NOTHING!!
88+
*
89+
* Calling _client.Dispose() breaks any call to a service that uses ICachClient
90+
* after a call to ServiceStack.ServiceInterface.ServiceExtension.GetSession.
91+
*
92+
* Enyim.Caching.MemcachedClient defines a destructor that handles all necessary cleanup (disposing is done there, we don't need to worry).
93+
*/
94+
}
8695

8796
public bool Remove(string key)
8897
{
89-
return Execute(() => client.Remove(key));
98+
return Execute(() => _client.Remove(key));
9099
}
91100

92101
public object Get(string key)
93102
{
94-
return Execute(() => client.Get(key));
103+
return Execute(() => ((MemcachedValueWrapper)_client.Get(key)).Value);
95104
}
96105

97106
public object Get(string key, out ulong ucas)
@@ -112,7 +121,13 @@ public object Get(string key, out ulong ucas)
112121

113122
public T Get<T>(string key)
114123
{
115-
return Execute(() => client.Get<T>(key));
124+
return Execute(() =>
125+
{
126+
var result = _client.Get<MemcachedValueWrapper>(key);
127+
if (result != null)
128+
return (T)result.Value;
129+
return default(T);
130+
});
116131
}
117132

118133
public T Get<T>(string key, out ulong ucas)
@@ -133,110 +148,110 @@ public T Get<T>(string key, out ulong ucas)
133148

134149
public long Increment(string key, uint amount)
135150
{
136-
return Execute(() => (long)client.Increment(key, 0, amount));
151+
return Execute(() => (long)_client.Increment(key, 0, amount));
137152
}
138153

139154
public long Decrement(string key, uint amount)
140155
{
141-
return Execute(() => (long)client.Decrement(key, 0, amount));
156+
return Execute(() => (long)_client.Decrement(key, 0, amount));
142157
}
143158

144159
public bool Add<T>(string key, T value)
145160
{
146-
return Execute(() => client.Store(StoreMode.Add, key, value));
161+
return Execute(() => _client.Store(StoreMode.Add, key, new MemcachedValueWrapper(value)));
147162
}
148163

149164
public bool Set<T>(string key, T value)
150165
{
151-
return Execute(() => client.Store(StoreMode.Set, key, value));
166+
return Execute(() => _client.Store(StoreMode.Set, key, new MemcachedValueWrapper(value)));
152167
}
153168

154169
public bool Replace<T>(string key, T value)
155170
{
156-
return Execute(() => client.Store(StoreMode.Replace, key, value));
171+
return Execute(() => _client.Store(StoreMode.Replace, key, new MemcachedValueWrapper(value)));
157172
}
158173

159174
public bool Add<T>(string key, T value, DateTime expiresAt)
160175
{
161-
return Execute(() => client.Store(StoreMode.Add, key, value, expiresAt));
176+
return Execute(() => _client.Store(StoreMode.Add, key, new MemcachedValueWrapper(value), expiresAt));
162177
}
163178

164179
public bool Set<T>(string key, T value, DateTime expiresAt)
165180
{
166-
return Execute(() => client.Store(StoreMode.Set, key, value, expiresAt));
181+
return Execute(() => _client.Store(StoreMode.Set, key, new MemcachedValueWrapper(value), expiresAt));
167182
}
168183

169184
public bool Replace<T>(string key, T value, DateTime expiresAt)
170185
{
171-
return Execute(() => client.Store(StoreMode.Replace, key, value, expiresAt));
186+
return Execute(() => _client.Store(StoreMode.Replace, key, new MemcachedValueWrapper(value), expiresAt));
172187
}
173188

174189
public bool Add<T>(string key, T value, TimeSpan expiresIn)
175190
{
176-
return Execute(() => client.Store(StoreMode.Add, key, value, expiresIn));
191+
return Execute(() => _client.Store(StoreMode.Add, key, new MemcachedValueWrapper(value), expiresIn));
177192
}
178193

179194
public bool Set<T>(string key, T value, TimeSpan expiresIn)
180195
{
181-
return Execute(() => client.Store(StoreMode.Set, key, value, expiresIn));
196+
return Execute(() => _client.Store(StoreMode.Set, key, new MemcachedValueWrapper(value), expiresIn));
182197
}
183198

184199
public bool Replace<T>(string key, T value, TimeSpan expiresIn)
185200
{
186-
return Execute(() => client.Store(StoreMode.Replace, key, value, expiresIn));
201+
return Execute(() => _client.Store(StoreMode.Replace, key, new MemcachedValueWrapper(value), expiresIn));
187202
}
188203

189204
public bool Add(string key, object value)
190205
{
191-
return Execute(() => client.Store(StoreMode.Add, key, value));
206+
return Execute(() => _client.Store(StoreMode.Add, key, new MemcachedValueWrapper(value)));
192207
}
193208

194209
public bool Set(string key, object value)
195210
{
196-
return Execute(() => client.Store(StoreMode.Set, key, value));
211+
return Execute(() => _client.Store(StoreMode.Set, key, new MemcachedValueWrapper(value)));
197212
}
198213

199214
public bool Replace(string key, object value)
200215
{
201-
return Execute(() => client.Store(StoreMode.Replace, key, value));
216+
return Execute(() => _client.Store(StoreMode.Replace, key, new MemcachedValueWrapper(value)));
202217
}
203218

204219
public bool Add(string key, object value, DateTime expiresAt)
205220
{
206-
return Execute(() => client.Store(StoreMode.Add, key, value, expiresAt));
221+
return Execute(() => _client.Store(StoreMode.Add, key, new MemcachedValueWrapper(value), expiresAt));
207222
}
208223

209224
public bool Set(string key, object value, DateTime expiresAt)
210225
{
211-
return Execute(() => client.Store(StoreMode.Set, key, value, expiresAt));
226+
return Execute(() => _client.Store(StoreMode.Set, key, new MemcachedValueWrapper(value), expiresAt));
212227
}
213228

214229
public bool Replace(string key, object value, DateTime expiresAt)
215230
{
216-
return Execute(() => client.Store(StoreMode.Replace, key, value, expiresAt));
231+
return Execute(() => _client.Store(StoreMode.Replace, key, new MemcachedValueWrapper(value), expiresAt));
217232
}
218233

219234
public bool CheckAndSet(string key, object value, ulong cas)
220235
{
221-
return Execute(() => client.Cas(StoreMode.Replace, key, value, cas).Result);
236+
return Execute(() => _client.Cas(StoreMode.Replace, key, new MemcachedValueWrapper(value), cas).Result);
222237
}
223238

224239
public bool CheckAndSet(string key, object value, ulong cas, DateTime expiresAt)
225240
{
226-
return Execute(() => client.Cas(StoreMode.Replace, key, value, expiresAt, cas).Result);
241+
return Execute(() => _client.Cas(StoreMode.Replace, key, new MemcachedValueWrapper(value), expiresAt, cas).Result);
227242
}
228243

229244
public void FlushAll()
230245
{
231-
Execute(() => client.FlushAll());
246+
Execute(() => _client.FlushAll());
232247
}
233248

234249
public IDictionary<string, T> GetAll<T>(IEnumerable<string> keys)
235250
{
236251
var results = new Dictionary<string, T>();
237252
foreach (var key in keys)
238253
{
239-
var result = this.Get<T>(key);
254+
var result = Get<T>(key);
240255
results[key] = result;
241256
}
242257

@@ -247,25 +262,29 @@ public void SetAll<T>(IDictionary<string, T> values)
247262
{
248263
foreach (var entry in values)
249264
{
250-
Set(entry.Key, entry.Value);
265+
Set(entry.Key, new MemcachedValueWrapper(entry.Value));
251266
}
252267
}
253268

254269
public IDictionary<string, object> GetAll(IEnumerable<string> keys)
255270
{
256-
return Execute(() => client.Get(keys));
271+
var results = new Dictionary<string, object>();
272+
foreach (var key in keys)
273+
{
274+
var result = Get(key);
275+
results[key] = result;
276+
}
277+
278+
return results;
257279
}
258280

259281
public IDictionary<string, object> GetAll(IEnumerable<string> keys, out IDictionary<string, ulong> casValues)
260282
{
261-
//Can't call methods with 'out' params in anonymous method blocks
262-
//Calling client directly instead - Add try{} if warranted.
263-
264283
var retVal = new Dictionary<string, object>();
265284
casValues = new Dictionary<string, ulong>();
266-
foreach (var casResult in client.GetWithCas(keys))
285+
foreach (var casResult in _client.GetWithCas(keys))
267286
{
268-
retVal.Add(casResult.Key, casResult.Value.Result);
287+
retVal.Add(casResult.Key, ((MemcachedValueWrapper)casResult.Value.Result).Value);
269288
casValues.Add(casResult.Key, casResult.Value.Cas);
270289
}
271290
return retVal;
@@ -277,14 +296,13 @@ public void RemoveAll(IEnumerable<string> keys)
277296
{
278297
try
279298
{
280-
this.Remove(key);
299+
Remove(key);
281300
}
282301
catch (Exception ex)
283302
{
284303
Log.Error(string.Format("Error trying to remove {0} from memcached", key), ex);
285304
}
286305
}
287306
}
288-
289307
}
290308
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using System;
2+
using ServiceStack.Text;
3+
4+
namespace ServiceStack.CacheAccess.Memcached
5+
{
6+
[Serializable]
7+
public class MemcachedValueWrapper
8+
{
9+
public Type ValueType { get; set; }
10+
public string JsonString { get; set; }
11+
12+
[NonSerialized] private object _value;
13+
14+
public object Value
15+
{
16+
get
17+
{
18+
if (_value == null && !string.IsNullOrEmpty(JsonString))
19+
_value = JsonSerializer.DeserializeFromString(JsonString, ValueType);
20+
return _value;
21+
}
22+
}
23+
24+
public MemcachedValueWrapper() {}
25+
26+
public MemcachedValueWrapper(object value)
27+
{
28+
ValueType = value.GetType();
29+
_value = value;
30+
JsonString = value.ToJson();
31+
}
32+
}
33+
}

src/ServiceStack.CacheAccess.Memcached/ServiceStack.CacheAccess.Memcached.csproj

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,12 @@
7878
<SpecificVersion>False</SpecificVersion>
7979
<HintPath>..\packages\EnyimMemcached.2.11\lib\net35\Enyim.Caching.dll</HintPath>
8080
</Reference>
81+
<Reference Include="ServiceStack.Common">
82+
<HintPath>..\..\lib\ServiceStack.Common.dll</HintPath>
83+
</Reference>
84+
<Reference Include="ServiceStack.Text">
85+
<HintPath>..\..\lib\ServiceStack.Text.dll</HintPath>
86+
</Reference>
8187
<Reference Include="System" />
8288
<Reference Include="System.Core">
8389
<RequiredTargetFramework>3.5</RequiredTargetFramework>
@@ -97,6 +103,7 @@
97103
</ItemGroup>
98104
<ItemGroup>
99105
<Compile Include="MemcachedClientCache.cs" />
106+
<Compile Include="MemcachedValueWrapper.cs" />
100107
<Compile Include="Properties\AssemblyInfo.cs" />
101108
<Compile Include="AdapterBase.cs" />
102109
</ItemGroup>

0 commit comments

Comments
 (0)