Skip to content

Commit 6141102

Browse files
committed
Add support for Clearing the Lazy Static In-memory Cache. Updated version to release to Nuget. Updated Readme release notes.
1 parent f270451 commit 6141102

File tree

4 files changed

+72
-7
lines changed

4 files changed

+72
-7
lines changed

LazyCacheHelpers.Tests/StaticInMemoryCacheTests.cs

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,8 @@
11
using LazyCacheHelpers;
22
using System;
3-
using System.Collections.Generic;
4-
using System.Diagnostics;
53
using System.Linq;
64
using System.Reflection;
7-
using System.Runtime.Caching;
8-
using System.Threading;
95
using System.Threading.Tasks;
10-
using System.Xml;
116
using Attr = System.ComponentModel;
127
using Microsoft.VisualStudio.TestTools.UnitTesting;
138

@@ -123,6 +118,46 @@ public async Task TestCacheLoadingAndHitsAsync()
123118
Assert.AreEqual("C-3PO", cachedEnumDescriptions[StarWarsEnum.C3PO].FirstOrDefault());
124119
}
125120

121+
[TestMethod]
122+
public async Task TestClearingStaticInMemoryCacheSyncAndAsync()
123+
{
124+
var enumCache = new LazyStaticInMemoryCache<Type, ILookup<Enum, string>>();
125+
int runCount = 0;
126+
127+
var loadCacheAsync = new Func<Task>(async () =>
128+
{
129+
//#1 Load Async Cache item
130+
var asyncCachedEnumDescriptions = await enumCache.GetOrAddAsync(typeof(StarWarsEnum), (t) =>
131+
{
132+
runCount++;
133+
var enumDescriptionLookup = GetEnumDescriptionsLookup<StarWarsEnum>();
134+
//Simulate Async operation by returning the results as a Task!
135+
return Task.FromResult(enumDescriptionLookup);
136+
});
137+
138+
//#2 Load Sync Cache item
139+
var syncCachedEnumDescriptions = enumCache.GetOrAdd(typeof(StarWarsEnum), (t) =>
140+
{
141+
runCount++;
142+
return GetEnumDescriptionsLookup<StarWarsEnum>();
143+
});
144+
});
145+
146+
//New Cache shoudl always have Zero entries...
147+
Assert.AreEqual(0, enumCache.GetCacheCount());
148+
149+
await loadCacheAsync.Invoke();
150+
151+
Assert.AreEqual(runCount, enumCache.GetCacheCount());
152+
Assert.AreEqual(runCount, enumCache.ClearCache());
153+
Assert.AreEqual(0, enumCache.GetCacheCount());
154+
runCount = 0;
155+
156+
//Test Reloading after being cleared with the Exact Same Data, Keys, etc.
157+
await loadCacheAsync.Invoke();
158+
Assert.AreEqual(runCount, enumCache.GetCacheCount());
159+
}
160+
126161
[TestMethod]
127162
public async Task TestCacheExceptionsAsync()
128163
{

LazyCacheHelpers/LazyCacheHelpers.csproj

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@
1111
<RepositoryUrl>https://github.com/cajuncoding/LazyCacheHelpers</RepositoryUrl>
1212
<PackageTags>cache caching memory memorycache in-memory lazy loading load self populate populating abstraction abstract thread threadsafe thread-safe safe performance optimization optimize server utilization</PackageTags>
1313
<PackageReleaseNotes>
14-
- Add support for Clearing the Cache and for getting the Cache Count; implemented for DefaultLazyCache as well as the Static In-memory caches.
14+
- Add support for Clearing the Lazy Static In-memory Cache (wrapper for Lazy caching pattern for sync or async results based on the underlying ConcurrentDictionary&lt;Lazy&lt;T&gt;&gt;).
1515

1616
Prior Release Notes:
17+
- Add support for Clearing the Cache and for getting the Cache Count; implemented for DefaultLazyCache as well as the Static In-memory caches.
1718
- Restored LazyCacheConfig class capabilities for reading values dynamically from Configuration.
1819
- Added support for Bootstrapping a Configuration Reader Func (Delegate) so that all reading of config values from the keys is completely dynamic now.
1920
- Added new LazyStaticInMemoryCache&lt;&gt; class to make it significantly easier to implement in-memory caching of data that rarely or never changes with the lazy loading, blocking cache, pattern; great for minimizing the runtime impact of expensive Reflection or I/O Async logic for data that rarely or never changes.
@@ -22,7 +23,7 @@
2223
- Now fully supported as a .Net Standard 2.0 library (sans Configuration reader helpers) whereby you can specify the timespan directly for Cache Policy initialization.
2324
- Initial nuget release for .Net Framework.
2425
</PackageReleaseNotes>
25-
<Version>1.1.0</Version>
26+
<Version>1.2.0</Version>
2627
</PropertyGroup>
2728

2829
<ItemGroup>

LazyCacheHelpers/LazyStaticInMemoryCache.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ public class LazyStaticInMemoryCache<TKey, TValue>
1717
{
1818
protected readonly ConcurrentDictionary<TKey, Lazy<TValue>> _lazySyncCache = new ConcurrentDictionary<TKey, Lazy<TValue>>();
1919
protected readonly ConcurrentDictionary<TKey, Lazy<Task<TValue>>> _lazyAsyncCache = new ConcurrentDictionary<TKey, Lazy<Task<TValue>>>();
20+
protected readonly object _padLock = new object();
2021

2122
/// Initialize a new Synchronous value factory for lazy loading a value from an expensive Async process, and execute the value factory at most one time (ever, across any/all threads).
2223
/// This provides a robust blocking cache mechanism backed by the Lazy<> class for high performance lazy loading of data that rarely ever changes.
@@ -112,5 +113,26 @@ public virtual bool TryRemoveAsyncValue(TKey key)
112113
return _lazyAsyncCache.TryRemove(key, out _);
113114
}
114115

116+
public virtual int GetCacheCount()
117+
{
118+
return _lazyAsyncCache.Count + _lazySyncCache.Count;
119+
}
120+
121+
public virtual int ClearCache()
122+
{
123+
int clearCount = 0;
124+
if (GetCacheCount() > 0)
125+
lock (_padLock)
126+
if (GetCacheCount() > 0)
127+
{
128+
clearCount += _lazyAsyncCache.Count;
129+
_lazyAsyncCache.Clear();
130+
131+
clearCount += _lazySyncCache.Count;
132+
_lazySyncCache.Clear();
133+
}
134+
135+
return clearCount;
136+
}
115137
}
116138
}

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@ LazyCacheConfig.BootstrapConfigValueReader(configKeyName => {
5656
OR use the ConfigurationManager Bootstrap helper above if you use AppSettings; it'll wire up a default reader for you (see below)!
5757

5858
## Release Notes:
59+
### v1.2
60+
- Add support for Clearing the Lazy Static In-memory Cache
61+
- *The wrapper for Lazy caching pattern for sync or async results based on the underlying ConcurrentDictionary<Lazy<T>>).*
62+
63+
### v1.1
64+
- Add support for Clearing the Cache and for getting the Cache Count; implemented for DefaultLazyCache as well as the Static In-memory caches.
65+
5966
### v1.0.4
6067
- Restored LazyCacheConfig class capabilities for reading values dynamically from Configuration.
6168
- Added support for Bootstrapping a Configuration Reader Func (Delegate) so that all reading of config values from the keys is completely dynamic now.

0 commit comments

Comments
 (0)