public async Task GetAutoReloadDataWithIntervalTestsAsync(bool shouldReloadInBackground)
        {
            ICacheInstance cache = MemoryCache.GetNamedInstance(Guid.NewGuid().ToString());
            var            key   = Guid.NewGuid().ToString();
            var            dataReloadInterval = TimeSpan.FromMilliseconds(200);
            var            ref1 = GetOrCreate(cache, key, dataReloadInterval, shouldReloadInBackground: shouldReloadInBackground);
            await Task.Delay(TimeSpan.FromMilliseconds(100));

            var ref2 = GetOrCreate(cache, key, dataReloadInterval, shouldReloadInBackground: shouldReloadInBackground);
            await Task.Delay(TimeSpan.FromMilliseconds(150));

            var ref3 = GetOrCreate(cache, key, dataReloadInterval, shouldReloadInBackground: shouldReloadInBackground);
            await Task.Delay(TimeSpan.FromMilliseconds(100));

            var ref4 = GetOrCreate(cache, key, dataReloadInterval, shouldReloadInBackground: shouldReloadInBackground);

            ref1.Should().Be(ref2);
            if (shouldReloadInBackground)
            {
                ref2.Should().Be(ref3);
                ref3.Should().NotBe(ref4);
            }
            else
            {
                ref2.Should().NotBe(ref3);
                ref3.Should().Be(ref4);
            }
        }
        public async Task TestAutoReloadOnExceptionAsync(bool shouldReloadInBackground)
        {
            ICacheInstance cache = MemoryCache.GetNamedInstance(nameof(TestAutoReloadOnExceptionAsync));
            var            key   = Guid.NewGuid().ToString();
            var            data  = cache.GetAutoReloadDataWithInterval(key, () => 8, TimeSpan.MaxValue, TimeSpan.FromMilliseconds(100), shouldReloadInBackground: shouldReloadInBackground);

            data.Should().Be(8);

            var exceptionCount = 0;
            Func <Task <int> > exceptionFunc = async() =>
            {
                await Task.Delay(RandomUtils.Random.Next(20) + 20).ConfigureAwait(false);

                Interlocked.Increment(ref exceptionCount);
                throw new InvalidOperationException();
            };

            for (var i = 0; i < 10; i++)
            {
                await Task.Delay(150);

                using (new PerfMonitorScope(sw => Console.WriteLine($"[{i}] {sw.ElapsedMilliseconds}ms")))
                {
                    data = cache.GetAutoReloadDataWithInterval(key, exceptionFunc, TimeSpan.MaxValue, TimeSpan.FromMilliseconds(100), shouldReloadInBackground: shouldReloadInBackground);
                }

                if (shouldReloadInBackground)
                {
                    await Task.Delay(80);

                    using (new PerfMonitorScope(sw => Console.WriteLine($"[{i}] {sw.ElapsedMilliseconds}ms")))
                    {
                        data = cache.GetAutoReloadDataWithInterval(key, exceptionFunc, TimeSpan.MaxValue, TimeSpan.FromMilliseconds(100), shouldReloadInBackground: shouldReloadInBackground);
                    }
                }

                data.Should().Be(8);
                exceptionCount.Should().Be(i + 1);
            }

            await Task.Delay(150);

            using (new PerfMonitorScope(sw => Console.WriteLine($"{sw.ElapsedMilliseconds}ms")))
            {
                data = cache.GetAutoReloadDataWithInterval(key, () => 6, TimeSpan.MaxValue, TimeSpan.FromMilliseconds(100), shouldReloadInBackground: shouldReloadInBackground);
            }

            if (shouldReloadInBackground)
            {
                await Task.Delay(80);

                data.Should().Be(8);
                using (new PerfMonitorScope(sw => Console.WriteLine($"{sw.ElapsedMilliseconds}ms")))
                {
                    data = cache.GetAutoReloadDataWithInterval(key, exceptionFunc, TimeSpan.MaxValue, TimeSpan.FromMilliseconds(100), shouldReloadInBackground: shouldReloadInBackground);
                }
            }

            data.Should().Be(6);
        }
        public void TestDeleteKey()
        {
            ICacheInstance cache = MemoryCache.GetNamedInstance(nameof(TestDeleteKey));
            var            key   = Guid.NewGuid().ToString();

            cache.SetData(key, new object(), TimeSpan.MaxValue);
            cache.TryDeleteKey(key).Should().BeTrue();
            cache.TryDeleteKey(key).Should().BeFalse();
        }
Example #4
0
        public static ICacheInstance GetNamedInstance(string name)
        {
            _ = name ?? throw new ArgumentNullException(nameof(name));

            ICacheInstance result = s_namedCacheInstances.GetOrAdd(
                name,
                key => new MemoryCacheInstance(name));

            return(result);
        }
        public static ICacheInstance GetCurrentClassNamedCacheInstance()
        {
            var            callingMethod = new StackTrace().GetFrame(1).GetMethod();
            var            name          = callingMethod.DeclaringType.FullName;
            ICacheInstance result        = s_namedCacheInstances.GetOrAdd(
                name,
                key => new MemoryCacheInstance(name));

            return(result);
        }
        public void TestGetAutoReloadDataWithCache_SetAsyncDataOnException()
        {
            ICacheInstance cache = MemoryCache.GetNamedInstance(nameof(TestGetAutoReloadDataWithInterval_SetAsyncDataOnException));
            var            key   = Guid.NewGuid().ToString();
            var            obj   = cache.GetAutoReloadDataWithCache(key, async() => new object(), async() => key, TimeSpan.MaxValue, TimeSpan.MaxValue);

            obj.Should().NotBeNull();
            cache.GetAutoReloadDataWithCache <object>(key, async() => throw new InvalidOperationException("dummy"), async() => key, TimeSpan.MaxValue, TimeSpan.MaxValue).Should().Be(obj);

            Action act = () => cache.GetAutoReloadDataWithCache <object>(Guid.NewGuid().ToString(), () => throw new InvalidOperationException("dummy"), async() => key, TimeSpan.MaxValue, TimeSpan.MaxValue);

            act.Should().Throw <InvalidOperationException>();
        }
        public async Task TestGetData_NonGenericAsync()
        {
            ICacheInstance cache = MemoryCache.GetNamedInstance(nameof(TestGetData_NonGenericAsync));
            var            key   = Guid.NewGuid().ToString();

            (int, int, int)data = (1, 2, 3);
            cache.SetData(key, data, TimeSpan.FromMilliseconds(100));
            cache.GetData(key).Should().NotBeNull();

            await Task.Delay(TimeSpan.FromMilliseconds(101));

            cache.GetData(key).Should().BeNull();
        }
Example #8
0
        public async Task TestGetData_GenericAsync()
        {
            ICacheInstance cache = MemoryCache.GetNamedInstance(Guid.NewGuid().ToString());
            var            key   = Guid.NewGuid().ToString();

            (int, int, int)data = (1, 2, 3);
            cache.SetData(key, data, TimeSpan.FromMilliseconds(100));
            (int, int, int)dataRef = cache.GetData <(int, int, int)>(key);
            dataRef.Should().NotBeNull();
            dataRef.Should().Be(data);

            await Task.Delay(TimeSpan.FromMilliseconds(200));

            cache.GetData <(int, int, int)>(key).Should().Be(default);
Example #9
0
        public async Task TestCacheDelete_CollectionDataShouldBeDisposedAsync()
        {
            ICacheInstance cache = MemoryCache.GetNamedInstance(nameof(TestCacheDelete_DataShouldBeDisposedAsync));

            cache.CleanInternal = TimeSpan.FromSeconds(1);
            var data = new DummyDisposable();
            var key  = Guid.NewGuid().ToString();

            cache.SetData(key, new[] { data }, TimeSpan.MaxValue);
            cache.TryDeleteKey(key).Should().BeTrue();
            data.IsDisposed.Should().Be(false);
            await Task.Delay(cache.CleanInternal.Add(TimeSpan.FromMilliseconds(500)));

            cache.CleanIfNeeded();
            data.IsDisposed.Should().Be(true);
        }
Example #10
0
        public async Task TestCacheDelete_LazyCollectionDataShouldBeDisposedAsync()
        {
            ICacheInstance cache = MemoryCache.GetNamedInstance(nameof(TestCacheDelete_LazyDataShouldBeDisposedAsync));

            cache.CleanInternal = TimeSpan.FromSeconds(1);
            var data = LazyUtils.ToLazy(() => new[] { new DummyDisposable() });
            var key  = Guid.NewGuid().ToString();

            cache.SetData(key, data, TimeSpan.MaxValue);
            Console.WriteLine(data.Value.GetHashCode());
            cache.TryDeleteKey(key).Should().BeTrue();
            data.Value.ForEach(_ => _.IsDisposed.Should().Be(false));
            await Task.Delay(cache.CleanInternal.Add(TimeSpan.FromMilliseconds(500)));

            cache.CleanIfNeeded();
            data.Value.ForEach(_ => _.IsDisposed.Should().Be(true));
        }
        public async Task TestDeleteKey_DisposableAsync()
        {
            ICacheInstance cache = MemoryCache.GetNamedInstance(nameof(TestDeleteKey_DisposableAsync));

            cache.CleanInternal = TimeSpan.FromMilliseconds(200);
            var key  = Guid.NewGuid().ToString();
            var data = new DummyDisposable();

            cache.SetData(key, data, TimeSpan.MaxValue);
            data.IsDisposed.Should().BeFalse();
            cache.TryDeleteKey(key).Should().BeTrue();
            cache.TryDeleteKey(key).Should().BeFalse();
            data.IsDisposed.Should().BeFalse();
            await Task.Delay(TimeSpan.FromMilliseconds(300));

            data.IsDisposed.Should().BeTrue();
        }
Example #12
0
 public static T GetAutoReloadDataWithInterval <T>(
     this ICacheInstance cache,
     string key,
     Func <T> dataFactory,
     TimeSpan timeToLive,
     TimeSpan dataReloadInternal,
     bool shouldReloadInBackground = true)
 {
     return(cache.GetAutoReloadDataWithCache <T>(
                key: key,
                dataFactory: dataFactory,
                eTagFactory: null,
                timeToLive: timeToLive,
                dataUpdateDetectInternal: dataReloadInternal,
                eTag: out _,
                shouldReloadInBackground: shouldReloadInBackground));
 }
        public async Task TestClearAsync()
        {
            ICacheInstance cache = MemoryCache.GetNamedInstance(Guid.NewGuid().ToString());

            cache.CleanInternal = TimeSpan.FromMilliseconds(200);
            var key  = Guid.NewGuid().ToString();
            var data = new DummyDisposable();

            cache.SetData(key, data, TimeSpan.MaxValue);
            cache.Size.Should().Be(1);
            data.IsDisposed.Should().BeFalse();
            cache.Clear();
            cache.Size.Should().Be(0);
            data.IsDisposed.Should().BeFalse();
            await Task.Delay(TimeSpan.FromMilliseconds(300));

            cache.CleanIfNeeded();
            data.IsDisposed.Should().BeTrue();
        }
        public void TestCreateDeleteInstance()
        {
            var            cacheName = Guid.NewGuid().ToString();
            ICacheInstance cache     = MemoryCache.GetNamedInstance(cacheName);

            cache.Should().NotBeNull();

            var data = new DummyDisposable();

            cache.SetData(nameof(data), data, Timeout.InfiniteTimeSpan);

            MemoryCache.GetNamedInstance(cacheName).Should().Be(cache);

            data.IsDisposed.Should().BeFalse();
            MemoryCache.TryDeleteNamedInstance(cacheName).Should().BeTrue();
            data.IsDisposed.Should().BeTrue();

            MemoryCache.GetNamedInstance(cacheName).Should().NotBe(cache);
        }
        public void TestGetData_Generic_InvalidCast()
        {
            ICacheInstance cache = MemoryCache.GetNamedInstance(nameof(TestGetData_Generic_InvalidCast));
            var            key   = Guid.NewGuid().ToString();

            (int, int, int)data = (1, 2, 3);
            cache.SetData(key, data, TimeSpan.MaxValue);

            (int, int, int)dataRef = cache.GetData <(int, int, int)>(key);
            dataRef.Should().NotBeNull();
            dataRef.Should().Be(data);

            var dataRefInvalid = cache.GetData <string>(key);

            dataRefInvalid.Should().Be(default(string));

            dataRef = cache.GetData <(int, int, int)>(key);
            dataRef.Should().NotBeNull();
            dataRef.Should().Be(data);
        }
        public async Task TestCacheCleanBehaviourAsync(bool shouldReloadInBackground)
        {
            var            cacheName = $"{nameof(TestCacheCleanBehaviourAsync)}|{shouldReloadInBackground}";
            ICacheInstance cache     = MemoryCache.GetNamedInstance(cacheName);

            cache.CleanInternal = TimeSpan.FromMilliseconds(200);

            cache.Size.Should().Be(0);
            GetOrCreate(cache, Guid.NewGuid().ToString(), TimeSpan.FromMilliseconds(200), shouldReloadInBackground: shouldReloadInBackground);
            cache.Size.Should().Be(1);
            GetOrCreate(cache, Guid.NewGuid().ToString(), TimeSpan.FromMilliseconds(500), shouldReloadInBackground: shouldReloadInBackground);
            cache.Size.Should().Be(2);
            await Task.Delay(TimeSpan.FromMilliseconds(100));

            cache.Size.Should().Be(2);
            await Task.Delay(TimeSpan.FromMilliseconds(1000));

            cache.Size.Should().Be(0);

            MemoryCache.TryDeleteNamedInstance(cacheName).Should().BeTrue();
        }
Example #17
0
        public static T GetAutoReloadDataWithCache <T>(
            this ICacheInstance cache,
            string key,
            Func <Task <T> > dataFactory,
            Func <Task <string> > eTagFactory,
            TimeSpan timeToLive,
            TimeSpan dataUpdateDetectInternal,
            out string eTag,
            bool shouldReloadInBackground = true)
        {
            Func <T>      df = () => dataFactory().ConfigureAwait(false).GetAwaiter().GetResult();
            Func <string> ef = () => eTagFactory?.Invoke().ConfigureAwait(false).GetAwaiter().GetResult();

            return(cache.GetAutoReloadDataWithCache <T>(
                       key: key,
                       dataFactory: df,
                       eTagFactory: ef,
                       timeToLive: timeToLive,
                       dataUpdateDetectInternal: dataUpdateDetectInternal,
                       eTag: out eTag,
                       shouldReloadInBackground: shouldReloadInBackground));
        }
Example #18
0
        public void TestCacheFuntionConcurrencyPerf(int numberOfConcurrentTasks, bool shouldReloadInBackground)
        {
            var            key     = Guid.NewGuid().ToString();
            ICacheInstance cache   = MemoryCache.GetNamedInstance(nameof(TestCacheFuntionConcurrency));
            var            counter = 0;

            Parallel.For(0, numberOfConcurrentTasks, i =>
            {
                cache.GetAutoReloadDataWithInterval(
                    key,
                    async() =>
                {
                    await Task.Delay(500).ConfigureAwait(false);
                    Interlocked.Increment(ref counter);
                    return(i);
                },
                    TimeSpan.FromDays(1),
                    TimeSpan.FromHours(1),
                    shouldReloadInBackground: shouldReloadInBackground);
            });

            counter.Should().Be(1);
        }
 private static void GetOrCreate(ICacheInstance cache, string key, TimeSpan timeToLive, bool shouldReloadInBackground)
 {
     cache.GetAutoReloadDataWithInterval(key, () => new object(), timeToLive, TimeSpan.MaxValue, shouldReloadInBackground: shouldReloadInBackground);
 }
 private static object GetOrCreate(ICacheInstance cache, string key, TimeSpan dataReloadInterval, bool shouldReloadInBackground)
 {
     return(cache.GetAutoReloadDataWithInterval(key, () => new object(), TimeSpan.MaxValue, dataReloadInterval, shouldReloadInBackground: shouldReloadInBackground));
 }
 public Get()
 {
     memoryCache = new MemoryCache(new MemoryCacheOptions());
     instance = new CacheInstance(memoryCache, new CacheSettings(cacheDurationInSeconds: 45));
 }
 public UpdateSettings()
 {
     instance = new CacheInstance(new MemoryCache(new MemoryCacheOptions()), new CacheSettings(cacheDurationInSeconds: 45));
 }
        public async Task HttpGetETagCacheTestsAsync()
        {
            ICacheInstance cache = MemoryCache.GetNamedInstance(Guid.NewGuid().ToString());

            using (var client = new HttpClient())
            {
                var baseUrl = $"https://httpbin.org/etag/";
                var etag    = Guid.NewGuid();

                int counter1 = 0;
                int counter2 = 0;

                var lazyResponse = LazyUtils.ToLazy(async() =>
                {
                    Interlocked.Increment(ref counter1);
                    var request = new HttpRequestMessage(HttpMethod.Get, $"{baseUrl}{etag}");
                    return(await client.SendAsync(request).ConfigureAwait(false));
                });
                cache.GetAutoReloadDataWithCache(
                    baseUrl,
                    async() =>
                {
                    Interlocked.Increment(ref counter2);
                    return(await lazyResponse.Value.Content.ReadAsStringAsync().ConfigureAwait(false));
                },
                    () => Task.FromResult(lazyResponse.Value.Headers.ETag?.Tag),
                    TimeSpan.FromHours(1),
                    TimeSpan.FromMilliseconds(100));
                counter1.Should().Be(1);
                counter2.Should().Be(1);

                lazyResponse = LazyUtils.ToLazy(async() =>
                {
                    Interlocked.Increment(ref counter1);
                    var request = new HttpRequestMessage(HttpMethod.Get, $"{baseUrl}{etag}");
                    return(await client.SendAsync(request).ConfigureAwait(false));
                });
                cache.GetAutoReloadDataWithCache(
                    baseUrl,
                    async() =>
                {
                    Interlocked.Increment(ref counter2);
                    return(await lazyResponse.Value.Content.ReadAsStringAsync().ConfigureAwait(false));
                },
                    () => Task.FromResult(lazyResponse.Value.Headers.ETag?.Tag),
                    TimeSpan.FromHours(1),
                    TimeSpan.FromMilliseconds(100));
                counter1.Should().Be(1);
                counter2.Should().Be(1);

                await Task.Delay(150);

                lazyResponse = LazyUtils.ToLazy(async() =>
                {
                    Interlocked.Increment(ref counter1);
                    var request = new HttpRequestMessage(HttpMethod.Get, $"{baseUrl}{etag}");
                    return(await client.SendAsync(request).ConfigureAwait(false));
                });
                cache.GetAutoReloadDataWithCache(
                    baseUrl,
                    async() =>
                {
                    Interlocked.Increment(ref counter2);
                    return(await lazyResponse.Value.Content.ReadAsStringAsync().ConfigureAwait(false));
                },
                    () => Task.FromResult(lazyResponse.Value.Headers.ETag?.Tag),
                    TimeSpan.FromHours(1),
                    TimeSpan.FromMilliseconds(100));
                counter1.Should().Be(1);
                counter2.Should().Be(1);

                etag = Guid.NewGuid();
                await Task.Delay(50);

                lazyResponse = LazyUtils.ToLazy(async() =>
                {
                    Interlocked.Increment(ref counter1);
                    var request = new HttpRequestMessage(HttpMethod.Get, $"{baseUrl}{etag}");
                    return(await client.SendAsync(request).ConfigureAwait(false));
                });
                cache.GetAutoReloadDataWithCache(
                    baseUrl,
                    async() =>
                {
                    Interlocked.Increment(ref counter2);
                    return(await lazyResponse.Value.Content.ReadAsStringAsync().ConfigureAwait(false));
                },
                    () => Task.FromResult(lazyResponse.Value.Headers.ETag?.Tag),
                    TimeSpan.FromHours(1),
                    TimeSpan.FromMilliseconds(100));
                counter1.Should().Be(2);
                counter2.Should().Be(1);

                await Task.Delay(150);

                lazyResponse = LazyUtils.ToLazy(async() =>
                {
                    Interlocked.Increment(ref counter1);
                    var request = new HttpRequestMessage(HttpMethod.Get, $"{baseUrl}{etag}");
                    return(await client.SendAsync(request).ConfigureAwait(false));
                });
                cache.GetAutoReloadDataWithCache(
                    baseUrl,
                    async() =>
                {
                    Interlocked.Increment(ref counter2);
                    return(await lazyResponse.Value.Content.ReadAsStringAsync().ConfigureAwait(false));
                },
                    () => Task.FromResult(lazyResponse.Value.Headers.ETag?.Tag),
                    TimeSpan.FromHours(1),
                    TimeSpan.FromMilliseconds(100));
                counter1.Should().Be(3);
                counter2.Should().Be(2);
            }
        }