/// <summary> /// Attempts to retrieve an item from memory cache /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="dto"></param> /// <returns></returns> private bool TryGetFromMemoryCache <T>(string key, ref CacheResponseDto <T> dto) { Log(eCacheEvent.KeyValueGotFromMemoryAttempt, key); #region Fast uncloned cache if (_fastMemcache.Contains(key)) { dto.Data = (T)_fastMemcache.Get(key); dto.IsFromInMemoryCache = true; Log(eCacheEvent.KeyValueGotFromMemory, key); return(true); } #endregion byte[] buffer = null; if ((buffer = (byte[])_memoryCache.Get(key)) != null) { dto.Data = FromByteBuffer <T>(buffer, true).Object; dto.IsFromInMemoryCache = true; Log(eCacheEvent.KeyValueGotFromMemory, key); return(true); } else { return(false); } }
/// <summary> /// Retrieves an item from the cache, if possible. /// It'll lazily init the cache asynchronously and return null if necessary. /// It will always return in a timely manner; e.g., without waiting for a cache connection /// It will never propagate an exception, unless the throwExceptions flag is set on the constructor /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <returns></returns> public async Task <CacheResponseDto <T> > GetWithMetaDataAsync <T>(string key) { key = CleanKey(key); var dto = new CacheResponseDto <T>().StartTiming(); try { if (!TryGetFromMemoryCache(key, ref dto)) // try memory cache first { if (IsRedisAccessible()) // Couldn't get it from memory, so try redis { var byteBuffer = await _cacheDatabase.StringGetAsync(key); if (!byteBuffer.IsNullOrEmpty) { Log(eCacheEvent.KeyValueGotFromCentralAttempt, key); PostProcessRedisBuffer(key, ref dto, byteBuffer); } } } } catch (Exception ex) { if (_config.IsExceptionPropagationEnabled) { throw; } Log(ex); dto.Exception = ex; } return(dto.StopTiming()); }
/// <summary> /// Deserializes a redis buffer, puts it into the DTO, puts it into the memory cache /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="dto"></param> /// <param name="byteBuffer"></param> private void PostProcessRedisBuffer <T>(string key, ref CacheResponseDto <T> dto, byte[] byteBuffer) { var item = FromByteBuffer <T>(byteBuffer, true); if (item != null) { dto.Data = item.Object; } dto.IsFromCentralCacheServer = true; if (item != null) { Log(eCacheEvent.KeyValueGotFromCentral, key); } // Put it into the in-memory cache if (item != null) { SetInMemoryCache(key, byteBuffer, item.Properties.Get("ExpirationUtc") as DateTime?); PutInFastCache(key, item.Object); } }
/// <summary> /// Retrieves an item from the cache, if possible. /// It'll lazily init the cache asynchronously and return null if necessary. /// It will always return in a timely manner; e.g., without waiting for a cache connection /// It will never propagate an exception, unless the throwExceptions flag is set on the constructor /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <returns></returns> public CacheResponseDto <T> GetWithMetaData <T>(string key) { key = CleanKey(key); var dto = new CacheResponseDto <T>().StartTiming(); try { if (!TryGetFromMemoryCache(key, ref dto)) { if (IsRedisAccessible()) { var byteBuffer = _cacheDatabase.StringGet(key); PostProcessRedisBuffer(key, ref dto, byteBuffer); } } } catch (Exception ex) { Log(ex); dto.Exception = ex; } return(dto.StopTiming()); }