public async Task <CachedObject <TResult> > GetAsync <TResult>(ProxiedMethodInvocation <T, TResult> proxiedMethodInvocation, CachePolicy cachePolicy) { return(await Task.Factory.StartNew(() => { var hash = proxiedMethodInvocation.GetHashString(); DictionaryCacheItem cachedObject; if (_cache.TryGetValue(hash, out cachedObject)) { if (cachedObject.ThrownException != null && cachedObject.Created.AddSeconds(cachePolicy.ExceptionCacheDuration) > DateTime.Now) { return new CachedObject <TResult>(CachedObjectState.Exception, cachedObject.ThrownException); } else if (cachedObject.ThrownException != null) { return new CachedObject <TResult>(CachedObjectState.None, null); } if (cachedObject.AbsoluteDuration.TotalSeconds > 0 && cachedObject.Created + cachedObject.AbsoluteDuration < DateTime.Now) { return new CachedObject <TResult>(CachedObjectState.None, null); } return new CachedObject <TResult>(cachedObject.IsExpired ? CachedObjectState.Stale : CachedObjectState.Fresh, (TResult)cachedObject.Object); } return CachedObject <TResult> .Empty(); })); }
public async Task StoreExceptionAsync <TResult>(ProxiedMethodInvocation <T, TResult> proxiedMethodInvocation, CachePolicy cachePolicy, Exception e) { await Task.Factory.StartNew(() => { var hash = proxiedMethodInvocation.GetHashString(); var duration = TimeSpan.FromSeconds(cachePolicy.CacheDuration); var absoluteDuration = TimeSpan.FromSeconds(cachePolicy.MaxAge); _cache[hash] = new DictionaryCacheItem(e, duration, absoluteDuration); }); }
public async Task <CachedObject <TResult> > GetAsync <TResult>(ProxiedMethodInvocation <T, TResult> proxiedMethodInvocation, CachePolicy cachePolicy) { var key = proxiedMethodInvocation.GetHashString(_hashScramble); var memcachedItem = await _memcachedCluster.Get(key); if (memcachedItem != null) { MemcachedObject <TResult> cacheItem; using (var zipStream = new GZipStream(memcachedItem.Data, CompressionMode.Decompress)) { using (var streamReader = new StreamReader(zipStream)) { var textReader = new JsonTextReader(streamReader); try { cacheItem = _serializer.Deserialize <MemcachedObject <TResult> >(textReader); } catch (JsonSerializationException) { //This exception occurs if whatever is in memcached is impossible to deserialize. It's a tricky case, but we'll have to report back that nothing is in there. return(new CachedObject <TResult>(CachedObjectState.None, default(TResult))); } } } if (cacheItem == null) { return(new CachedObject <TResult>(CachedObjectState.None, default(TResult))); } if (cacheItem.IsException && cacheItem.Created.AddSeconds(cachePolicy.ExceptionCacheDuration) > DateTime.Now) { return(new CachedObject <TResult>(CachedObjectState.Exception, cacheItem.Exception)); } else if (cacheItem.IsException) { return(new CachedObject <TResult>(CachedObjectState.None, default(TResult))); } var fresh = cacheItem.Created.AddSeconds(cachePolicy.CacheDuration) > DateTime.Now; var state = fresh ? CachedObjectState.Fresh : CachedObjectState.Stale; if (cachePolicy.DiscardStale && state == CachedObjectState.Stale) { return(new CachedObject <TResult>(CachedObjectState.None, default(TResult))); } return(new CachedObject <TResult>(state, cacheItem.Object)); } return(new CachedObject <TResult>(CachedObjectState.None, default(TResult))); }
public static byte[] GetHashBytes <T, TResult>(this ProxiedMethodInvocation <T, TResult> invocation, string scrambleString = null) where T : class { var sb = new StringBuilder(); sb.Append(typeof(T).FullName); sb.Append(" - "); sb.Append(invocation.Method); sb.Append(" - "); sb.AddParameterRepresentations(invocation.Parameters); if (!string.IsNullOrEmpty(scrambleString)) { sb.Append(" - "); sb.Append(scrambleString); } var bytes = Encoding.UTF8.GetBytes(sb.ToString()); var hashAlgorithm = new SHA256Managed(); var hash = hashAlgorithm.ComputeHash(bytes); return(hash); }
public async Task StoreAsync <TResult>(ProxiedMethodInvocation <T, TResult> proxiedMethodInvocation, CachePolicy cachePolicy, TResult data) { var key = proxiedMethodInvocation.GetHashString(_hashScramble); var cachedObject = new MemcachedObject <TResult>() { Created = DateTime.Now, Object = data }; var bytes = SerializeAndZip(cachedObject); if (cachePolicy.MaxAge > 0) { await _memcachedCluster.Set(key, bytes, new MemcachedStorageOptions() { ExpirationTime = TimeSpan.FromSeconds(cachePolicy.MaxAge) }); } else { await _memcachedCluster.Set(key, bytes); } }
public async Task <TResult> LookupAsync <TResult>(ProxiedMethodInvocation <T, TResult> methodInvocation) { var cachePolicy = _cachePolicyProvider.GetPolicy(methodInvocation.Method, methodInvocation.Parameters); if (cachePolicy == null || cachePolicy.CacheDuration <= 0) { return(await methodInvocation.InvokeAsync(_implementation)); } var cachedItem = await _cache.GetAsync(methodInvocation, cachePolicy) ?? new CachedObject <TResult>(CachedObjectState.None, null); if (cachedItem.State == CachedObjectState.Fresh) { return(cachedItem.Object); } if (cachedItem.State == CachedObjectState.Exception) { throw cachedItem.ThrownException; } var requestKey = new RequestKey(methodInvocation.Method, methodInvocation.Parameters); Task <TResult> awaitableTask; if (_taskSyncronizer.TryGetAwaitable(requestKey, () => methodInvocation.InvokeAsync(_implementation), out awaitableTask)) { if (cachedItem.State == CachedObjectState.Stale) { return(cachedItem.Object); } return(await awaitableTask); } if (cachedItem.State == CachedObjectState.Stale) { try { Exception thrownException = null; try { var data = await awaitableTask; await _cache.StoreAsync(methodInvocation, cachePolicy, data); return(data); } catch (Exception e) { thrownException = e; } if (cachePolicy.BubbleExceptions) { await _cache.StoreExceptionAsync(methodInvocation, cachePolicy, thrownException); throw thrownException; } else { await _cache.StoreAsync(methodInvocation, cachePolicy, cachedItem.Object); return(cachedItem.Object); } } finally { _taskSyncronizer.Release(requestKey); } } try { Exception thrownException = null; try { var data = await awaitableTask; await _cache.StoreAsync(methodInvocation, cachePolicy, data); return(data); } catch (Exception e) { thrownException = e; } await _cache.StoreExceptionAsync(methodInvocation, cachePolicy, thrownException); throw thrownException; } finally { _taskSyncronizer.Release(requestKey); } }
public static string GetHashString <T, TResult>(this ProxiedMethodInvocation <T, TResult> invocation, string scrambleString = null) where T : class { return(Convert.ToBase64String(GetHashBytes(invocation, scrambleString))); }
public TResult Lookup <TResult>(ProxiedMethodInvocation <T, TResult> methodInvocation) { var cachePolicy = _cachePolicyProvider.GetPolicy(methodInvocation.Method, methodInvocation.Parameters); if (cachePolicy == null || cachePolicy.CacheDuration == 0) { return(methodInvocation.Invoke(_implementation)); } var cachedItem = AsyncContext.Run(() => _cache.GetAsync(methodInvocation, cachePolicy)) ?? new CachedObject <TResult>(CachedObjectState.None, null); if (cachedItem.State == CachedObjectState.Fresh) { return(cachedItem.Object); } if (cachedItem.State == CachedObjectState.Exception) { throw cachedItem.ThrownException; } var requestKey = new RequestKey(methodInvocation.Method, methodInvocation.Parameters); RequestWaitHandle <TResult> waitHandle; if (_syncronizer.ShouldWaitForHandle(requestKey, out waitHandle)) { if (cachedItem.State == CachedObjectState.Stale) { return(cachedItem.Object); } return(waitHandle.WaitForResult()); } if (cachedItem.State == CachedObjectState.Stale) { Func <TResult> loader = () => methodInvocation.Invoke(_implementation); loader.BeginInvoke(callback => { Exception asyncRequestThrownException = null; var asyncResult = default(TResult); try { asyncResult = loader.EndInvoke(callback); AsyncContext.Run(() => _cache.StoreAsync(methodInvocation, cachePolicy, asyncResult)); } catch (Exception e) { if (cachePolicy.BubbleExceptions) { AsyncContext.Run(() => _cache.StoreExceptionAsync(methodInvocation, cachePolicy, e)); asyncRequestThrownException = e; } else { asyncResult = cachedItem.Object; AsyncContext.Run(() => _cache.StoreAsync(methodInvocation, cachePolicy, asyncResult)); } } finally { if (asyncRequestThrownException != null) { _syncronizer.ReleaseWithException <TResult>(requestKey, asyncRequestThrownException); } else { _syncronizer.Release(requestKey, asyncResult); } } }, null); return(cachedItem.Object); } //At this point nothing is in the cache. var realInstanceResult = default(TResult); Exception thrownException = null; try { realInstanceResult = methodInvocation.Invoke(_implementation); AsyncContext.Run(() => _cache.StoreAsync(methodInvocation, cachePolicy, realInstanceResult)); } catch (Exception e) { thrownException = e; AsyncContext.Run(() => _cache.StoreExceptionAsync(methodInvocation, cachePolicy, thrownException)); throw; } finally { if (thrownException != null) { _syncronizer.ReleaseWithException <TResult>(requestKey, thrownException); } else { _syncronizer.Release(requestKey, realInstanceResult); } } return(realInstanceResult); }
public CachePolicy GetPolicy <TResult>(ProxiedMethodInvocation <T, TResult> invocation) { return(GetPolicy(invocation.Method, invocation.Parameters)); }
public TResult Handle <TResult>(ProxiedMethodInvocation <T, TResult> methodInvocation) { return(_syncLookupHandler.Lookup(methodInvocation)); }
public async Task <TResult> HandleAsync <TResult>(ProxiedMethodInvocation <T, TResult> methodInvocation) { return(await _asyncLookupHandler.LookupAsync(methodInvocation)); }