Example #1
0
        protected async Task RemoveLeastRecentlyUsedCacheItemWhenOverMaxCacheSize(CancellationToken cancellationToken)
        {
            var cacheStore = await StateManager.GetOrAddAsync <IReliableDictionary <string, CachedItem> >(CacheStoreName);

            var cacheStoreMetadata = await StateManager.GetOrAddAsync <IReliableDictionary <string, CacheStoreMetadata> >(CacheStoreMetadataName);

            bool continueRemovingItems = true;

            while (continueRemovingItems)
            {
                continueRemovingItems = false;
                cancellationToken.ThrowIfCancellationRequested();

                await RetryHelper.ExecuteWithRetry(StateManager, async (tx, cancelToken, state) =>
                {
                    var metadata = await cacheStoreMetadata.TryGetValueAsync(tx, CacheStoreMetadataKey, LockMode.Update);

                    if (metadata.HasValue)
                    {
                        _log?.Invoke($"Size: {metadata.Value.Size}  Max Size: {GetMaxSizeInBytes()}");

                        if (metadata.Value.Size > GetMaxSizeInBytes())
                        {
                            Func <string, Task <ConditionalValue <CachedItem> > > getCacheItem = async(string cacheKey) => await cacheStore.TryGetValueAsync(tx, cacheKey, LockMode.Update);
                            var linkedDictionaryHelper = new LinkedDictionaryHelper(getCacheItem, ByteSizeOffset);

                            var firstItemKey    = metadata.Value.FirstCacheKey;
                            var firstCachedItem = (await getCacheItem(firstItemKey)).Value;

                            // Move item to last item if cached item is not expired
                            if (firstCachedItem.AbsoluteExpiration > _systemClock.UtcNow)
                            {
                                // remove cached item
                                var removeResult = await linkedDictionaryHelper.Remove(metadata.Value, firstCachedItem);
                                await ApplyChanges(tx, cacheStore, cacheStoreMetadata, removeResult);

                                // add to last
                                var addLastResult = await linkedDictionaryHelper.AddLast(removeResult.CacheStoreMetadata, firstItemKey, firstCachedItem, firstCachedItem.Value);
                                await ApplyChanges(tx, cacheStore, cacheStoreMetadata, addLastResult);

                                continueRemovingItems = addLastResult.CacheStoreMetadata.Size > GetMaxSizeInBytes();
                            }
                            else  // Remove
                            {
                                _log?.Invoke($"Auto Removing: {metadata.Value.FirstCacheKey}");

                                var result = await linkedDictionaryHelper.Remove(metadata.Value, firstCachedItem);
                                await ApplyChanges(tx, cacheStore, cacheStoreMetadata, result);
                                await cacheStore.TryRemoveAsync(tx, metadata.Value.FirstCacheKey);

                                continueRemovingItems = result.CacheStoreMetadata.Size > GetMaxSizeInBytes();
                            }
                        }
                    }
                });

                await Task.Delay(TimeSpan.FromMilliseconds(100), cancellationToken);
            }
        }
Example #2
0
        public async Task SetCachedItemAsync(string key, byte[] value, TimeSpan?slidingExpiration, DateTimeOffset?absoluteExpiration)
        {
            if (slidingExpiration.HasValue)
            {
                var now = _systemClock.UtcNow;
                absoluteExpiration = now.AddMilliseconds(slidingExpiration.Value.TotalMilliseconds);
            }

            var cacheStore = await StateManager.GetOrAddAsync <IReliableDictionary <string, CachedItem> >(CacheStoreName);

            var cacheStoreMetadata = await StateManager.GetOrAddAsync <IReliableDictionary <string, CacheStoreMetadata> >(CacheStoreMetadataName);

            await RetryHelper.ExecuteWithRetry(StateManager, async (tx, cancellationToken, state) =>
            {
                _log?.Invoke($"Set cached item called with key: {key} on partition id: {Partition?.PartitionInfo.Id}");

                Func <string, Task <ConditionalValue <CachedItem> > > getCacheItem = async(string cacheKey) => await cacheStore.TryGetValueAsync(tx, cacheKey, LockMode.Update);
                var linkedDictionaryHelper = new LinkedDictionaryHelper(getCacheItem, ByteSizeOffset);

                var cacheStoreInfo    = (await cacheStoreMetadata.TryGetValueAsync(tx, CacheStoreMetadataKey, LockMode.Update)).Value ?? new CacheStoreMetadata(0, null, null);
                var existingCacheItem = (await getCacheItem(key)).Value;
                var cachedItem        = ApplyAbsoluteExpiration(existingCacheItem, absoluteExpiration) ?? new CachedItem(value, null, null, slidingExpiration, absoluteExpiration);

                // empty linked dictionary
                if (cacheStoreInfo.FirstCacheKey == null)
                {
                    var metadata = new CacheStoreMetadata(value.Length + ByteSizeOffset, key, key);
                    await cacheStoreMetadata.SetAsync(tx, CacheStoreMetadataKey, metadata);
                    await cacheStore.SetAsync(tx, key, cachedItem);
                }
                else
                {
                    var cacheMetadata = cacheStoreInfo;

                    // linked node already exists in dictionary
                    if (existingCacheItem != null)
                    {
                        var removeResult = await linkedDictionaryHelper.Remove(cacheStoreInfo, cachedItem);
                        cacheMetadata    = removeResult.CacheStoreMetadata;
                        await ApplyChanges(tx, cacheStore, cacheStoreMetadata, removeResult);
                    }

                    // add to last
                    var addLastResult = await linkedDictionaryHelper.AddLast(cacheMetadata, key, cachedItem, value);
                    await ApplyChanges(tx, cacheStore, cacheStoreMetadata, addLastResult);
                }
            });
        }
Example #3
0
        public async Task RemoveCachedItemAsync(string key)
        {
            var cacheStore = await StateManager.GetOrAddAsync <IReliableDictionary <string, CachedItem> >(CacheStoreName);

            var cacheStoreMetadata = await StateManager.GetOrAddAsync <IReliableDictionary <string, CacheStoreMetadata> >(CacheStoreMetadataName);

            await RetryHelper.ExecuteWithRetry(StateManager, async (tx, cancellationToken, state) =>
            {
                _log?.Invoke($"Remove cached item called with key: {key} on partition id: {Partition?.PartitionInfo.Id}");

                var cacheResult = await cacheStore.TryRemoveAsync(tx, key);
                if (cacheResult.HasValue)
                {
                    Func <string, Task <ConditionalValue <CachedItem> > > getCacheItem = async(string cacheKey) => await cacheStore.TryGetValueAsync(tx, cacheKey, LockMode.Update);
                    var linkedDictionaryHelper = new LinkedDictionaryHelper(getCacheItem, ByteSizeOffset);

                    var cacheStoreInfo = (await cacheStoreMetadata.TryGetValueAsync(tx, CacheStoreMetadataKey, LockMode.Update)).Value ?? new CacheStoreMetadata(0, null, null);
                    var result         = await linkedDictionaryHelper.Remove(cacheStoreInfo, cacheResult.Value);

                    await ApplyChanges(tx, cacheStore, cacheStoreMetadata, result);
                }
            });
        }