Skip to content

Commit c43bfd2

Browse files
authored
Merge pull request #9 from kevbite/caching
Adding support for caching
2 parents e58e5b4 + 8254641 commit c43bfd2

32 files changed

+675
-43
lines changed

README.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ PM> Install-Package HumbleConfig.MongoDb
2727
```powershell
2828
PM> Install-Package HumbleConfig.Credstash
2929
```
30+
```powershell
31+
PM> Install-Package HumbleConfig.Caching
32+
```
3033
### How to use it?
3134
First, create an `Configuration` instance:
3235
```csharp
@@ -38,7 +41,10 @@ configuration.AddEnvironmentVariables()
3841
.AddConfigurationManager()
3942
.AddConfigR()
4043
.AddMongoDb("mongodb://localhost/settings", "appSettings")
41-
.AddCredstash(RegionEndpoint.EUWest1);
44+
.WithDefaultMemoryCache(TimeSpan.FromHours(1))
45+
.AddCredstash(RegionEndpoint.EUWest1)
46+
.WithCache(MemoryCache.Default, () => new CacheItemPolicy())
47+
.GetConfiguration();
4248
```
4349
The order in which we add the configuration sources will determine which configuration values will take priority, in the above example environment variables will override any configuration values within mongodb.
4450

appveyor.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
only:
44
- master
55
skip_tags: true
6-
version: 3.1.1
6+
version: 4.0.0
77

88
assembly_info:
99
assembly_version: '{version}'
@@ -59,7 +59,7 @@
5959

6060
-
6161
skip_tags: true
62-
version: 3.1.1-{branch}{build}
62+
version: 4.0.0-{branch}{build}
6363

6464
assembly_info:
6565
assembly_version: '{version}'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using System;
2+
using System.Runtime.Caching;
3+
using System.Threading;
4+
using HumbleConfig.Tests;
5+
using Moq;
6+
using NUnit.Framework;
7+
8+
namespace HumbleConfig.Caching.Tests.CachingConfigurationSourceDecoratorTests
9+
{
10+
[TestFixtureSource(typeof(NonNullableTestFixtureCases))]
11+
[TestFixtureSource(typeof(NullableTestFixtureCases))]
12+
public class CachingConfigurationSourceDecoratorForNoneExistingAppSettingKey<TValue> : ConfigurationSourceTestsForNoneExistingKey<TValue>
13+
{
14+
protected override IConfigurationSource CreateConfigurationSource()
15+
{
16+
var innerSource = new Mock<IConfigurationSource>();
17+
innerSource.Setup(x => x.GetAppSettingAsync<TValue>(It.IsAny<string>(), It.IsAny<CancellationToken>()))
18+
.ReturnsAsync(ConfigurationSourceResult<TValue>.FailedResult());
19+
20+
var source = new CachingConfigurationSourceDecorator(innerSource.Object, MemoryCache.Default, () => new CacheItemPolicy());
21+
22+
return source;
23+
}
24+
}
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using System;
2+
using System.Runtime.Caching;
3+
using System.Threading;
4+
using HumbleConfig.Tests;
5+
using Moq;
6+
using NUnit.Framework;
7+
8+
namespace HumbleConfig.Caching.Tests.CachingConfigurationSourceDecoratorTests
9+
{
10+
[TestFixtureSource(typeof(NonNullableTestFixtureCases))]
11+
[TestFixtureSource(typeof(NullableTestFixtureCases))]
12+
public class CachingConfigurationSourceDecoratorForNoneExistingAppSettingKeyWithValueCached<TValue> : ConfigurationSourceTestsForNoneExistingKey<TValue>
13+
{
14+
protected override IConfigurationSource CreateConfigurationSource()
15+
{
16+
var objectCache = new Mock<ObjectCache>();
17+
objectCache.Setup(x => x.Get(It.IsAny<string>(), It.IsAny<string>()))
18+
.Returns(ConfigurationSourceResult<TValue>.FailedResult());
19+
20+
var innerSource = new Mock<IConfigurationSource>();
21+
innerSource.Setup(x => x.GetAppSettingAsync<TValue>(It.IsAny<string>(), It.IsAny<CancellationToken>()))
22+
.Throws(new Exception("Should never get here"));
23+
24+
var source = new CachingConfigurationSourceDecorator(innerSource.Object, objectCache.Object, () => new CacheItemPolicy());
25+
26+
return source;
27+
}
28+
}
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using System;
2+
using System.Runtime.Caching;
3+
using System.Threading;
4+
using HumbleConfig.Tests;
5+
using Moq;
6+
using NUnit.Framework;
7+
8+
namespace HumbleConfig.Caching.Tests.CachingConfigurationSourceDecoratorTests
9+
{
10+
[TestFixtureSource(typeof(NonNullableTestFixtureCases))]
11+
[TestFixtureSource(typeof(NullableTestFixtureCases))]
12+
public class CachingConfigurationSourceDecoratorTestsForExistingKey<TValue> : ConfigurationSourceTestsForExistingKey<TValue>
13+
{
14+
protected override IConfigurationSource GivenConfigurationSourceWithExistingRKey(string key, TValue expectedValue)
15+
{
16+
var innerSource = new Mock<IConfigurationSource>();
17+
var cancellationToken = new CancellationToken();
18+
innerSource.Setup(x => x.GetAppSettingAsync<TValue>(key, cancellationToken))
19+
.ReturnsAsync(ConfigurationSourceResult<TValue>.SuccessResult(expectedValue));
20+
21+
var source = new CachingConfigurationSourceDecorator(innerSource.Object, MemoryCache.Default, () => new CacheItemPolicy());
22+
23+
return source;
24+
}
25+
}
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using System;
2+
using System.Runtime.Caching;
3+
using System.Threading;
4+
using HumbleConfig.Tests;
5+
using Moq;
6+
using NUnit.Framework;
7+
8+
namespace HumbleConfig.Caching.Tests.CachingConfigurationSourceDecoratorTests
9+
{
10+
[TestFixtureSource(typeof(NonNullableTestFixtureCases))]
11+
[TestFixtureSource(typeof(NullableTestFixtureCases))]
12+
public class CachingConfigurationSourceDecoratorTestsForExistingKeyWithValueCached<TValue> : ConfigurationSourceTestsForExistingKey<TValue>
13+
{
14+
protected override IConfigurationSource GivenConfigurationSourceWithExistingRKey(string key, TValue expectedValue)
15+
{
16+
var innerSource = new Mock<IConfigurationSource>();
17+
var cancellationToken = new CancellationToken();
18+
innerSource.SetupSequence(x => x.GetAppSettingAsync<TValue>(key, cancellationToken))
19+
.ReturnsAsync(ConfigurationSourceResult<TValue>.SuccessResult(expectedValue))
20+
.Throws(new Exception("Should never get here"));
21+
22+
var source = new CachingConfigurationSourceDecorator(innerSource.Object, MemoryCache.Default, () => new CacheItemPolicy());
23+
source.GetAppSettingAsync<TValue>(key, cancellationToken).Wait();
24+
25+
return source;
26+
}
27+
}
28+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
4+
<PropertyGroup>
5+
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
6+
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
7+
<ProjectGuid>{93E17785-3E7D-42C6-A44E-FAA26A2A5785}</ProjectGuid>
8+
<OutputType>Library</OutputType>
9+
<AppDesignerFolder>Properties</AppDesignerFolder>
10+
<RootNamespace>HumbleConfig.Caching.Tests</RootNamespace>
11+
<AssemblyName>HumbleConfig.Caching.Tests</AssemblyName>
12+
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
13+
<FileAlignment>512</FileAlignment>
14+
</PropertyGroup>
15+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
16+
<DebugSymbols>true</DebugSymbols>
17+
<DebugType>full</DebugType>
18+
<Optimize>false</Optimize>
19+
<OutputPath>bin\Debug\</OutputPath>
20+
<DefineConstants>DEBUG;TRACE</DefineConstants>
21+
<ErrorReport>prompt</ErrorReport>
22+
<WarningLevel>4</WarningLevel>
23+
</PropertyGroup>
24+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
25+
<DebugType>pdbonly</DebugType>
26+
<Optimize>true</Optimize>
27+
<OutputPath>bin\Release\</OutputPath>
28+
<DefineConstants>TRACE</DefineConstants>
29+
<ErrorReport>prompt</ErrorReport>
30+
<WarningLevel>4</WarningLevel>
31+
</PropertyGroup>
32+
<ItemGroup>
33+
<Reference Include="Castle.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
34+
<HintPath>..\packages\Castle.Core.4.2.1\lib\net45\Castle.Core.dll</HintPath>
35+
</Reference>
36+
<Reference Include="Moq, Version=4.7.145.0, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
37+
<HintPath>..\packages\Moq.4.7.145\lib\net45\Moq.dll</HintPath>
38+
</Reference>
39+
<Reference Include="nunit.framework, Version=3.9.0.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
40+
<HintPath>..\packages\NUnit.3.9.0\lib\net45\nunit.framework.dll</HintPath>
41+
</Reference>
42+
<Reference Include="System" />
43+
<Reference Include="System.Configuration" />
44+
<Reference Include="System.Core" />
45+
<Reference Include="System.Runtime.Caching" />
46+
<Reference Include="System.Xml.Linq" />
47+
<Reference Include="System.Data.DataSetExtensions" />
48+
<Reference Include="Microsoft.CSharp" />
49+
<Reference Include="System.Data" />
50+
<Reference Include="System.Net.Http" />
51+
<Reference Include="System.Xml" />
52+
</ItemGroup>
53+
<ItemGroup>
54+
<Compile Include="CachingConfigurationSourceDecoratorTests\CachingConfigurationSourceDecoratorForNoneExistingAppSettingKey.cs" />
55+
<Compile Include="CachingConfigurationSourceDecoratorTests\CachingConfigurationSourceDecoratorForNoneExistingAppSettingKeyWithValueCached.cs" />
56+
<Compile Include="CachingConfigurationSourceDecoratorTests\CachingConfigurationSourceDecoratorTestsForExistingKey.cs" />
57+
<Compile Include="CachingConfigurationSourceDecoratorTests\CachingConfigurationSourceDecoratorTestsForExistingKeyWithValueCached.cs" />
58+
<Compile Include="Properties\AssemblyInfo.cs" />
59+
</ItemGroup>
60+
<ItemGroup>
61+
<ProjectReference Include="..\HumbleConfig.Caching\HumbleConfig.Caching.csproj">
62+
<Project>{025FC6D3-B42E-4B46-AD36-FA002ED26EA6}</Project>
63+
<Name>HumbleConfig.Caching</Name>
64+
</ProjectReference>
65+
<ProjectReference Include="..\HumbleConfig.Tests\HumbleConfig.Tests.csproj">
66+
<Project>{27C04368-FC7A-4D87-8F60-A14FE965FB71}</Project>
67+
<Name>HumbleConfig.Tests</Name>
68+
</ProjectReference>
69+
<ProjectReference Include="..\HumbleConfig\HumbleConfig.csproj">
70+
<Project>{B04CB40D-08D8-44C6-B66E-F1ED0E97E507}</Project>
71+
<Name>HumbleConfig</Name>
72+
</ProjectReference>
73+
</ItemGroup>
74+
<ItemGroup>
75+
<None Include="packages.config" />
76+
</ItemGroup>
77+
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
78+
</Project>
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using System.Reflection;
2+
using System.Runtime.CompilerServices;
3+
using System.Runtime.InteropServices;
4+
5+
// General Information about an assembly is controlled through the following
6+
// set of attributes. Change these attribute values to modify the information
7+
// associated with an assembly.
8+
[assembly: AssemblyTitle("HumbleConfig.Caching.Tests")]
9+
[assembly: AssemblyDescription("")]
10+
[assembly: AssemblyConfiguration("")]
11+
[assembly: AssemblyCompany("")]
12+
[assembly: AssemblyProduct("HumbleConfig.Caching.Tests")]
13+
[assembly: AssemblyCopyright("Copyright © 2017")]
14+
[assembly: AssemblyTrademark("")]
15+
[assembly: AssemblyCulture("")]
16+
17+
// Setting ComVisible to false makes the types in this assembly not visible
18+
// to COM components. If you need to access a type in this assembly from
19+
// COM, set the ComVisible attribute to true on that type.
20+
[assembly: ComVisible(false)]
21+
22+
// The following GUID is for the ID of the typelib if this project is exposed to COM
23+
[assembly: Guid("93e17785-3e7d-42c6-a44e-faa26a2a5785")]
24+
25+
// Version information for an assembly consists of the following four values:
26+
//
27+
// Major Version
28+
// Minor Version
29+
// Build Number
30+
// Revision
31+
//
32+
// You can specify all the values or you can default the Build and Revision Numbers
33+
// by using the '*' as shown below:
34+
// [assembly: AssemblyVersion("1.0.*")]
35+
[assembly: AssemblyVersion("1.0.0.0")]
36+
[assembly: AssemblyFileVersion("1.0.0.0")]
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<packages>
3+
<package id="Castle.Core" version="4.2.1" targetFramework="net45" />
4+
<package id="Moq" version="4.7.145" targetFramework="net45" />
5+
<package id="NUnit" version="3.9.0" targetFramework="net45" />
6+
</packages>
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using System;
2+
using System.Runtime.Caching;
3+
using System.Threading;
4+
using System.Threading.Tasks;
5+
6+
namespace HumbleConfig.Caching
7+
{
8+
public class CachingConfigurationSourceDecorator : IConfigurationSource
9+
{
10+
private readonly IConfigurationSource _innerSource;
11+
private readonly ObjectCache _objectCache;
12+
private readonly Func<CacheItemPolicy> _cacheItemPolicyFactory;
13+
14+
public CachingConfigurationSourceDecorator(IConfigurationSource innerSource, ObjectCache objectCache, Func<CacheItemPolicy> cacheItemPolicyFactoryFactory)
15+
{
16+
_innerSource = innerSource;
17+
_objectCache = objectCache;
18+
_cacheItemPolicyFactory = cacheItemPolicyFactoryFactory;
19+
}
20+
21+
public async Task<ConfigurationSourceResult<TValue>> GetAppSettingAsync<TValue>(string key, CancellationToken cancellationToken = default(CancellationToken))
22+
{
23+
var appsetting = (ConfigurationSourceResult<TValue>)_objectCache.Get(CreateCacheKey(key));
24+
25+
if (appsetting == null)
26+
{
27+
appsetting = await _innerSource.GetAppSettingAsync<TValue>(key, cancellationToken);
28+
29+
var cacheItemPolicy = _cacheItemPolicyFactory();
30+
_objectCache.Add(CreateCacheItem(key, appsetting), cacheItemPolicy);
31+
}
32+
33+
return appsetting;
34+
}
35+
36+
private static string CreateCacheKey(string key)
37+
{
38+
return $"HumbleConfig-{key}";
39+
}
40+
41+
private CacheItem CreateCacheItem<TValue>(string key, ConfigurationSourceResult<TValue> value)
42+
{
43+
return new CacheItem(CreateCacheKey(key), value);
44+
}
45+
}
46+
}

0 commit comments

Comments
 (0)