Esempio n. 1
0
        /// <summary>
        /// Gets a TTL for a cacheable item, given the current execution context.
        /// </summary>
        /// <param name="context">The execution context.</param>
        /// <returns>A <see cref="Ttl"/> representing the remaining Ttl of the cached item.</returns>
        public Ttl GetTtl(Context context)
        {
            TimeSpan untilPointInTime = absoluteExpirationTime.Subtract(SystemClock.DateTimeOffsetUtcNow());
            TimeSpan remaining        = untilPointInTime > TimeSpan.Zero ? untilPointInTime : TimeSpan.Zero;

            return(new Ttl(remaining, false));
        }
        /// <summary>
        /// Puts the specified value in the cache.
        /// </summary>
        /// <param name="key">The cache key.</param>
        /// <param name="value">The value to put into the cache.</param>
        /// <param name="ttl">The time-to-live for the cache entry.</param>
        public void Put(string key, object value, Ttl ttl)
        {
#if PORTABLE
            using (Microsoft.Extensions.Caching.Memory.ICacheEntry entry = _cache.CreateEntry(key)) {
                entry.Value = value;
                if (ttl.SlidingExpiration)
                {
                    entry.SlidingExpiration = ttl.Timespan;
                }
                else
                {
                    entry.AbsoluteExpirationRelativeToNow = ttl.Timespan;
                }
            }
#else
            System.Runtime.Caching.CacheItemPolicy cacheItemPolicy = new System.Runtime.Caching.CacheItemPolicy();
            if (ttl.SlidingExpiration)
            {
                cacheItemPolicy.SlidingExpiration = ttl.Timespan;
            }
            else
            {
                cacheItemPolicy.AbsoluteExpiration = SystemClock.DateTimeOffsetUtcNow().Add(ttl.Timespan);
            }
            _cache.Set(key, value, cacheItemPolicy);
#endif
        }
        public async Task Should_execute_delegate_and_put_value_in_cache_but_when_it_expires_execute_delegate_again()
        {
            const string valueToReturn = "valueToReturn";
            const string operationKey  = "SomeOperationKey";

            IAsyncCacheProvider stubCacheProvider = new StubCacheProvider();
            TimeSpan            ttl = TimeSpan.FromMinutes(30);
            var cache = Policy.CacheAsync <string>(stubCacheProvider, ttl);

            (bool cacheHit1, object fromCache1) = await stubCacheProvider.TryGetAsync(operationKey, CancellationToken.None, false).ConfigureAwait(false);

            cacheHit1.Should().BeFalse();
            fromCache1.Should().BeNull();

            int delegateInvocations             = 0;
            Func <Context, Task <string> > func = async ctx =>
            {
                delegateInvocations++;
                await TaskHelper.EmptyTask.ConfigureAwait(false);

                return(valueToReturn);
            };

            DateTimeOffset fixedTime = SystemClock.DateTimeOffsetUtcNow();

            SystemClock.DateTimeOffsetUtcNow = () => fixedTime;

            // First execution should execute delegate and put result in the cache.
            (await cache.ExecuteAsync(func, new Context(operationKey)).ConfigureAwait(false)).Should().Be(valueToReturn);
            delegateInvocations.Should().Be(1);

            (bool cacheHit2, object fromCache2) = await stubCacheProvider.TryGetAsync(operationKey, CancellationToken.None, false).ConfigureAwait(false);

            cacheHit2.Should().BeTrue();
            fromCache2.Should().Be(valueToReturn);

            // Second execution (before cache expires) should get it from the cache - no further delegate execution.
            // (Manipulate time so just prior cache expiry).
            SystemClock.DateTimeOffsetUtcNow = () => fixedTime.Add(ttl).AddSeconds(-1);
            (await cache.ExecuteAsync(func, new Context(operationKey)).ConfigureAwait(false)).Should().Be(valueToReturn);
            delegateInvocations.Should().Be(1);

            // Manipulate time to force cache expiry.
            SystemClock.DateTimeOffsetUtcNow = () => fixedTime.Add(ttl).AddSeconds(1);

            // Third execution (cache expired) should not get it from the cache - should cause further delegate execution.
            (await cache.ExecuteAsync(func, new Context(operationKey)).ConfigureAwait(false)).Should().Be(valueToReturn);
            delegateInvocations.Should().Be(2);
        }
Esempio n. 4
0
 public (bool, object) TryGet(string key)
 {
     if (cachedValues.ContainsKey(key))
     {
         if (SystemClock.DateTimeOffsetUtcNow() < cachedValues[key].Expiry)
         {
             return(true, cachedValues[key].Value);
         }
         else
         {
             cachedValues.Remove(key);
         }
     }
     return(false, null);
 }
Esempio n. 5
0
        public void Should_return_configured_timespan_from_time_requested()
        {
            DateTimeOffset fixedTime = SystemClock.DateTimeOffsetUtcNow();
            TimeSpan       ttl       = TimeSpan.FromSeconds(30);
            TimeSpan       delay     = TimeSpan.FromSeconds(5);

            RelativeTtl ttlStrategy = new RelativeTtl(ttl);

            SystemClock.DateTimeOffsetUtcNow = () => fixedTime.Add(delay);

            Ttl retrieved = ttlStrategy.GetTtl(new Context("someExecutionKey"), null);

            retrieved.Timespan.Should().BeCloseTo(ttl);
            retrieved.SlidingExpiration.Should().BeFalse();
        }
Esempio n. 6
0
 public object Get(string key)
 {
     if (cachedValues.ContainsKey(key))
     {
         if (SystemClock.DateTimeOffsetUtcNow() < cachedValues[key].Expiry)
         {
             return(cachedValues[key].Value);
         }
         else
         {
             cachedValues.Remove(key);
         }
     }
     return(null);
 }
Esempio n. 7
0
        public void Should_execute_delegate_and_put_value_in_cache_but_when_it_expires_execute_delegate_again()
        {
            const string valueToReturn = "valueToReturn";
            const string operationKey  = "SomeOperationKey";

            ISyncCacheProvider   stubCacheProvider = new StubCacheProvider();
            TimeSpan             ttl   = TimeSpan.FromMinutes(30);
            CachePolicy <string> cache = Policy.Cache <string>(stubCacheProvider, ttl);

            (bool cacheHit1, object fromCache1) = stubCacheProvider.TryGet(operationKey);
            cacheHit1.Should().BeFalse();
            fromCache1.Should().BeNull();

            int delegateInvocations     = 0;
            Func <Context, string> func = _ =>
            {
                delegateInvocations++;
                return(valueToReturn);
            };

            DateTimeOffset fixedTime = SystemClock.DateTimeOffsetUtcNow();

            SystemClock.DateTimeOffsetUtcNow = () => fixedTime;

            // First execution should execute delegate and put result in the cache.
            cache.Execute(func, new Context(operationKey)).Should().Be(valueToReturn);
            delegateInvocations.Should().Be(1);

            (bool cacheHit2, object fromCache2) = stubCacheProvider.TryGet(operationKey);
            cacheHit2.Should().BeTrue();
            fromCache2.Should().Be(valueToReturn);

            // Second execution (before cache expires) should get it from the cache - no further delegate execution.
            // (Manipulate time so just prior cache expiry).
            SystemClock.DateTimeOffsetUtcNow = () => fixedTime.Add(ttl).AddSeconds(-1);
            cache.Execute(func, new Context(operationKey)).Should().Be(valueToReturn);
            delegateInvocations.Should().Be(1);

            // Manipulate time to force cache expiry.
            SystemClock.DateTimeOffsetUtcNow = () => fixedTime.Add(ttl).AddSeconds(1);

            // Third execution (cache expired) should not get it from the cache - should cause further delegate execution.
            cache.Execute(func, new Context(operationKey)).Should().Be(valueToReturn);
            delegateInvocations.Should().Be(2);
        }
        /// <summary>
        /// Puts the specified value in the cache.
        /// </summary>
        /// <param name="key">The cache key.</param>
        /// <param name="value">The value to put into the cache.</param>
        /// <param name="ttl">The time-to-live for the cache entry.</param>
        public void Put(string key, object value, Ttl ttl)
        {
            TimeSpan remaining = DateTimeOffset.MaxValue - SystemClock.DateTimeOffsetUtcNow();
            MemoryCacheEntryOptions options = new MemoryCacheEntryOptions();

            if (ttl.SlidingExpiration)
            {
                options.SlidingExpiration = ttl.Timespan < remaining ? ttl.Timespan : remaining;
            }
            else
            {
                if (ttl.Timespan == TimeSpan.MaxValue)
                {
                    options.AbsoluteExpiration = DateTimeOffset.MaxValue;
                }
                else
                {
                    options.AbsoluteExpirationRelativeToNow = ttl.Timespan < remaining ? ttl.Timespan : remaining;
                }
            }

            _cache.Set(key, value, options);
        }
Esempio n. 9
0
 public CacheItem(object value, Ttl ttl)
 {
     Expiry = DateTimeOffset.MaxValue - SystemClock.DateTimeOffsetUtcNow() > ttl.Timespan ? SystemClock.DateTimeOffsetUtcNow().Add(ttl.Timespan) : DateTimeOffset.MaxValue;
     Value  = value;
 }
Esempio n. 10
0
        public void Should_return_zero_ttl_if_configured_to_expire_in_past()
        {
            AbsoluteTtl ttlStrategy = new AbsoluteTtl(SystemClock.DateTimeOffsetUtcNow().Subtract(TimeSpan.FromTicks(1)));

            ttlStrategy.GetTtl(new Context("someExecutionKey"), null).Timespan.Should().Be(TimeSpan.Zero);
        }
Esempio n. 11
0
        protected static void AdvanceClock(TimeSpan advance)
        {
            DateTimeOffset now = SystemClock.DateTimeOffsetUtcNow();

            SystemClock.DateTimeOffsetUtcNow = () => now + advance;
        }