Пример #1
0
        public void CacheEntryDependencies()
        {
            var cts   = new CancellationTokenSource();
            var pause = new ManualResetEvent(false);

            using (var cacheLink = _memoryCache.CreateLinkingScope())
            {
                _memoryCache.Set("master key", "some value",
                                 new MemoryCacheEntryOptions()
                                 .AddExpirationToken(new CancellationChangeToken(cts.Token)));

                _memoryCache.Set(_cacheKey, _cacheItem,
                                 new MemoryCacheEntryOptions()
                                 .AddEntryLink(cacheLink)
                                 .RegisterPostEvictionCallback(
                                     (key, value, reason, substate) =>
                {
                    _result = $"'{key}':'{value}' was evicted because: {reason}";
                    pause.Set();
                }
                                     ));
            }

            // trigger the token to expire the master item
            cts.Cancel();

            Assert.True(pause.WaitOne(500));

            Assert.Equal("'key':'value' was evicted because: TokenExpired", _result);
        }
Пример #2
0
        /// <inheritdoc />
        public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
        {
            TagHelperContent result = null;

            if (Enabled)
            {
                var key = GenerateKey(context);
                if (!MemoryCache.TryGetValue(key, out result))
                {
                    // Create an entry link scope and flow it so that any triggers related to the cache entries
                    // created within this scope get copied to this scope.
                    using (var link = MemoryCache.CreateLinkingScope())
                    {
                        result = await context.GetChildContentAsync();

                        MemoryCache.Set(key, result, GetMemoryCacheEntryOptions(link));
                    }
                }
            }

            // Clear the contents of the "cache" element since we don't want to render it.
            output.SuppressOutput();
            if (Enabled)
            {
                output.Content.SetContent(result);
            }
            else
            {
                result = await context.GetChildContentAsync();

                output.Content.SetContent(result);
            }
        }
Пример #3
0
        /// <inheritdoc />
        public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (output == null)
            {
                throw new ArgumentNullException(nameof(output));
            }

            IHtmlContent result = null;

            if (Enabled)
            {
                var key = GenerateKey(context);
                if (!MemoryCache.TryGetValue(key, out result))
                {
                    // Create an entry link scope and flow it so that any tokens related to the cache entries
                    // created within this scope get copied to this scope.
                    using (var link = MemoryCache.CreateLinkingScope())
                    {
                        var content = await output.GetChildContentAsync();

                        var stringBuilder = new StringBuilder();
                        using (var writer = new StringWriter(stringBuilder))
                        {
                            content.WriteTo(writer, HtmlEncoder);
                        }

                        result = new StringBuilderHtmlContent(stringBuilder);
                        MemoryCache.Set(key, result, GetMemoryCacheEntryOptions(link));
                    }
                }
            }

            // Clear the contents of the "cache" element since we don't want to render it.
            output.SuppressOutput();
            if (Enabled)
            {
                output.Content.SetContent(result);
            }
            else
            {
                result = await output.GetChildContentAsync();

                output.Content.SetContent(result);
            }
        }
Пример #4
0
        public void Main()
        {
            IMemoryCache cache = new MemoryCache(new MemoryCacheOptions());
            object       result;
            string       key       = "Key";
            object       newObject = new object();
            object       state     = new object();

            // Basic CRUD operations:

            // Create / Overwrite
            result = cache.Set(key, newObject);
            result = cache.Set(key, new object());

            // Retrieve, null if not found
            result = cache.Get(key);

            // Retrieve
            bool found = cache.TryGetValue(key, out result);

            // Delete
            cache.Remove(key);

            // Cache entry configuration:

            // Stays in the cache as long as possible
            result = cache.Set(
                key,
                new object(),
                new MemoryCacheEntryOptions().SetPriority(CacheItemPriority.NeverRemove));

            // Automatically remove if not accessed in the given time
            result = cache.Set(
                key,
                new object(),
                new MemoryCacheEntryOptions().SetSlidingExpiration(TimeSpan.FromMinutes(5)));

            // Automatically remove at a certain time
            result = cache.Set(
                key,
                new object(),
                new MemoryCacheEntryOptions().SetAbsoluteExpiration(DateTimeOffset.UtcNow.AddDays(2)));

            // Automatically remove at a certain time, which is relative to UTC now
            result = cache.Set(
                key,
                new object(),
                new MemoryCacheEntryOptions().SetAbsoluteExpiration(relative: TimeSpan.FromMinutes(10)));

            // Automatically remove if not accessed in the given time
            // Automatically remove at a certain time (if it lives that long)
            result = cache.Set(
                key,
                new object(),
                new MemoryCacheEntryOptions()
                .SetSlidingExpiration(TimeSpan.FromMinutes(5))
                .SetAbsoluteExpiration(DateTimeOffset.UtcNow.AddDays(2)));

            // Callback when evicted
            var options = new MemoryCacheEntryOptions()
                          .RegisterPostEvictionCallback(
                (echoKey, value, reason, substate) =>
            {
                Console.WriteLine(echoKey + ": '" + value + "' was evicted due to " + reason);
            });

            result = cache.Set(key, new object(), options);

            // Remove on token expiration
            var cts = new CancellationTokenSource();

            options = new MemoryCacheEntryOptions()
                      .AddExpirationToken(new CancellationChangeToken(cts.Token))
                      .RegisterPostEvictionCallback(
                (echoKey, value, reason, substate) =>
            {
                Console.WriteLine(echoKey + ": '" + value + "' was evicted due to " + reason);
            });
            result = cache.Set(key, new object(), options);

            // Fire the token to see the registered callback being invoked
            cts.Cancel();

            // Expire an entry if the dependent entry expires
            using (var link = cache.CreateLinkingScope())
            {
                cts = new CancellationTokenSource();
                cache.Set("key1", "value1", new MemoryCacheEntryOptions()
                          .AddExpirationToken(new CancellationChangeToken(cts.Token)));

                // expire this entry if the entry with key "key1" expires.
                cache.Set("key2", "value2", new MemoryCacheEntryOptions()
                          .AddEntryLink(link)
                          .RegisterPostEvictionCallback(
                              (echoKey, value, reason, substate) =>
                {
                    Console.WriteLine(echoKey + ": '" + value + "' was evicted due to " + reason);
                }));
            }

            // Fire the token to see the registered callback being invoked
            cts.Cancel();
        }
Пример #5
0
        /// <inheritdoc />
        public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (output == null)
            {
                throw new ArgumentNullException(nameof(output));
            }

            IHtmlContent content = null;

            if (Enabled)
            {
                var key = GenerateKey(context);
                MemoryCacheEntryOptions options;

                while (content == null)
                {
                    Task <IHtmlContent> result = null;

                    if (!MemoryCache.TryGetValue(key, out result))
                    {
                        var tokenSource = new CancellationTokenSource();

                        // Create an entry link scope and flow it so that any tokens related to the cache entries
                        // created within this scope get copied to this scope.

                        options = GetMemoryCacheEntryOptions();
                        options.AddExpirationToken(new CancellationChangeToken(tokenSource.Token));

                        var tcs = new TaskCompletionSource <IHtmlContent>();

                        MemoryCache.Set(key, tcs.Task, options);

                        try
                        {
                            using (var link = MemoryCache.CreateLinkingScope())
                            {
                                result  = ProcessContentAsync(output);
                                content = await result;
                                options.AddEntryLink(link);
                            }

                            // The entry is set instead of assigning a value to the
                            // task so that the expiration options are are not impacted
                            // by the time it took to compute it.

                            MemoryCache.Set(key, result, options);
                        }
                        catch
                        {
                            // Remove the worker task from the cache in case it can't complete.
                            tokenSource.Cancel();
                            throw;
                        }
                        finally
                        {
                            // If an exception occurs, ensure the other awaiters
                            // render the output by themselves.
                            tcs.SetResult(null);
                        }
                    }
                    else
                    {
                        // There is either some value already cached (as a Task)
                        // or a worker processing the output. In the case of a worker,
                        // the result will be null, and the request will try to acquire
                        // the result from memory another time.

                        content = await result;
                    }
                }
            }
            else
            {
                content = await output.GetChildContentAsync();
            }

            // Clear the contents of the "cache" element since we don't want to render it.
            output.SuppressOutput();

            output.Content.SetContent(content);
        }