Skip to content

Commit dda3452

Browse files
Provide distributed cache factories
* Move the MemoryDistributedCacheFactory to its own package for avoiding an undue dependency. * Add a RedisCache factory. * Add a SqlServerCache factory. To be squashed.
1 parent da3799f commit dda3452

15 files changed

+456
-10
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
using System;
2+
using System.Reflection;
3+
4+
[assembly: CLSCompliant(true)]
5+
[assembly: AssemblyDelaySign(false)]

CoreDistributedCache/NHibernate.Caches.CoreDistributedCache/MemoryDistributedCacheFactory.cs renamed to CoreDistributedCache/NHibernate.Caches.CoreDistributedCache.Memory/MemoryDistributedCacheFactory.cs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
using Microsoft.Extensions.Caching.Memory;
55
using Microsoft.Extensions.Options;
66

7-
namespace NHibernate.Caches.CoreDistributedCache
7+
namespace NHibernate.Caches.CoreDistributedCache.Memory
88
{
99
/// <summary>
1010
/// A memory "distributed" cache factory. Use for testing purpose. Otherwise consider using <c>CoreMemoryCache</c>
@@ -68,9 +68,10 @@ public MemoryDistributedCacheFactory(IDictionary<string, string> properties)
6868
options.ExpirationScanFrequency = TimeSpan.FromMinutes(minutes);
6969
else if (TimeSpan.TryParse(esf, out var expirationScanFrequency))
7070
options.ExpirationScanFrequency = expirationScanFrequency;
71-
Log.Warn(
72-
"Invalid value '{0}' for {1} setting: it is neither an int nor a TimeSpan. Ignoring.",
73-
esf, _expirationScanFrequency);
71+
else
72+
Log.Warn(
73+
"Invalid value '{0}' for {1} setting: it is neither an int nor a TimeSpan. Ignoring.",
74+
esf, _expirationScanFrequency);
7475
}
7576
else
7677
{
@@ -84,9 +85,10 @@ public MemoryDistributedCacheFactory(IDictionary<string, string> properties)
8485
{
8586
if (long.TryParse(sl, out var bytes))
8687
options.SizeLimit = bytes;
87-
Log.Warn(
88-
"Invalid value '{0}' for {1} setting: it is not an integer. Ignoring.",
89-
sl, _sizeLimit);
88+
else
89+
Log.Warn(
90+
"Invalid value '{0}' for {1} setting: it is not an integer. Ignoring.",
91+
sl, _sizeLimit);
9092
}
9193
else
9294
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<Import Project="../../NHibernate.Caches.props" />
3+
<PropertyGroup>
4+
<Product>NHibernate.Caches.CoreDistributedCache.Memory</Product>
5+
<Title>NHibernate.Caches.CoreDistributedCache.Memory</Title>
6+
<Description>Memory cache provider for NHibernate using .Net Core IDistributedCache (Microsoft.Extensions.Caching.Redis).
7+
Meant for testing purpose, consider NHibernate.Caches.CoreMemoryCache for other usages.</Description>
8+
<!-- Targeting net461 explicitly in order to avoid https://github.com/dotnet/standard/issues/506 for net461 consumers-->
9+
<TargetFrameworks>net461;netstandard2.0</TargetFrameworks>
10+
<NoWarn>$(NoWarn);3001;3002</NoWarn>
11+
<SignAssembly>True</SignAssembly>
12+
<AssemblyOriginatorKeyFile>..\..\NHibernate.Caches.snk</AssemblyOriginatorKeyFile>
13+
<PackageReleaseNotes>* New feature
14+
* #28 - Add a .Net Core DistributedCache</PackageReleaseNotes>
15+
</PropertyGroup>
16+
<PropertyGroup Condition="'$(TargetFramework)' == 'net461'">
17+
<DefineConstants>NETFX;$(DefineConstants)</DefineConstants>
18+
</PropertyGroup>
19+
<ItemGroup>
20+
<None Include="..\..\NHibernate.Caches.snk" Link="NHibernate.snk" />
21+
</ItemGroup>
22+
<ItemGroup>
23+
<ProjectReference Include="..\NHibernate.Caches.CoreDistributedCache\NHibernate.Caches.CoreDistributedCache.csproj" />
24+
</ItemGroup>
25+
<ItemGroup>
26+
<Content Include="../../readme.md">
27+
<PackagePath>./NHibernate.Caches.readme.md</PackagePath>
28+
</Content>
29+
<Content Include="../../LICENSE.txt">
30+
<PackagePath>./NHibernate.Caches.license.txt</PackagePath>
31+
</Content>
32+
</ItemGroup>
33+
<ItemGroup>
34+
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="2.0.0" />
35+
</ItemGroup>
36+
</Project>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
using System;
2+
using System.Reflection;
3+
4+
[assembly: CLSCompliant(true)]
5+
[assembly: AssemblyDelaySign(false)]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<Import Project="../../NHibernate.Caches.props" />
3+
<PropertyGroup>
4+
<Product>NHibernate.Caches.CoreDistributedCache.Redis</Product>
5+
<Title>NHibernate.Caches.CoreDistributedCache.Redis</Title>
6+
<Description>Redis cache provider for NHibernate using .Net Core IDistributedCache (Microsoft.Extensions.Caching.Redis).</Description>
7+
<!-- Targeting net461 explicitly in order to avoid https://github.com/dotnet/standard/issues/506 for net461 consumers-->
8+
<TargetFrameworks>net461;netstandard2.0</TargetFrameworks>
9+
<NoWarn>$(NoWarn);3001;3002</NoWarn>
10+
<SignAssembly>True</SignAssembly>
11+
<AssemblyOriginatorKeyFile>..\..\NHibernate.Caches.snk</AssemblyOriginatorKeyFile>
12+
<PackageReleaseNotes>* New feature
13+
* #28 - Add a .Net Core DistributedCache</PackageReleaseNotes>
14+
</PropertyGroup>
15+
<PropertyGroup Condition="'$(TargetFramework)' == 'net461'">
16+
<DefineConstants>NETFX;$(DefineConstants)</DefineConstants>
17+
</PropertyGroup>
18+
<ItemGroup>
19+
<None Include="..\..\NHibernate.Caches.snk" Link="NHibernate.snk" />
20+
</ItemGroup>
21+
<ItemGroup>
22+
<ProjectReference Include="..\NHibernate.Caches.CoreDistributedCache\NHibernate.Caches.CoreDistributedCache.csproj" />
23+
</ItemGroup>
24+
<ItemGroup>
25+
<Content Include="../../readme.md">
26+
<PackagePath>./NHibernate.Caches.readme.md</PackagePath>
27+
</Content>
28+
<Content Include="../../LICENSE.txt">
29+
<PackagePath>./NHibernate.Caches.license.txt</PackagePath>
30+
</Content>
31+
</ItemGroup>
32+
<ItemGroup>
33+
<PackageReference Include="Microsoft.Extensions.Caching.Redis" Version="2.0.0" />
34+
</ItemGroup>
35+
</Project>
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
using System.Collections.Generic;
2+
using Microsoft.Extensions.Caching.Distributed;
3+
using Microsoft.Extensions.Caching.Redis;
4+
5+
namespace NHibernate.Caches.CoreDistributedCache.Redis
6+
{
7+
/// <summary>
8+
/// A Redis distributed cache factory. See <see cref="RedisCache" />.
9+
/// </summary>
10+
public class RedisDistributedCacheFactory : IDistributedCacheFactory
11+
{
12+
private static readonly INHibernateLogger Log = NHibernateLogger.For(typeof(RedisDistributedCacheFactory));
13+
private const string _configuration = "configuration";
14+
private const string _instanceName = "instance-name";
15+
16+
private readonly RedisCacheOptions _options;
17+
18+
/// <summary>
19+
/// Constructor with explicit configuration properties.
20+
/// </summary>
21+
/// <param name="configuration">See <see cref="RedisCacheOptions.Configuration" />.</param>
22+
/// <param name="instanceName">See <see cref="RedisCacheOptions.InstanceName" />.</param>
23+
public RedisDistributedCacheFactory(string configuration, string instanceName)
24+
{
25+
_options = new RedisCacheOptions
26+
{
27+
Configuration = configuration,
28+
InstanceName = instanceName
29+
};
30+
}
31+
32+
/// <summary>
33+
/// Constructor with configuration properties. It supports <c>configuration</c> and
34+
/// <c>instance-name</c> properties. See <see cref="RedisCacheOptions.Configuration" /> and
35+
/// <see cref="RedisCacheOptions.InstanceName" />.
36+
/// </summary>
37+
/// <param name="properties">The configurations properties.</param>
38+
public RedisDistributedCacheFactory(IDictionary<string, string> properties)
39+
{
40+
_options = new RedisCacheOptions();
41+
42+
if (properties == null)
43+
return;
44+
45+
if (properties.TryGetValue(_configuration, out var configuration))
46+
{
47+
_options.Configuration = configuration;
48+
Log.Info("Configuration set as '{0}'", configuration);
49+
}
50+
else
51+
{
52+
// Configuration is supposed to be mandatory.
53+
Log.Warn("No {0} property provided", _configuration);
54+
}
55+
56+
if (properties.TryGetValue(_instanceName, out var instanceName))
57+
{
58+
_options.InstanceName = instanceName;
59+
Log.Info("InstanceName set as '{0}'", instanceName);
60+
}
61+
else
62+
Log.Info("No {0} property provided", _instanceName);
63+
}
64+
65+
/// <inheritdoc />
66+
public IDistributedCache BuildCache()
67+
{
68+
// According to https://docs.microsoft.com/en-us/aspnet/core/performance/caching/distributed#the-idistributedcache-interface
69+
// (see its paragraph end note) there is no need for a singleton lifetime.
70+
return new RedisCache(_options);
71+
}
72+
}
73+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
using System;
2+
using System.Reflection;
3+
4+
[assembly: CLSCompliant(true)]
5+
[assembly: AssemblyDelaySign(false)]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<Import Project="../../NHibernate.Caches.props" />
3+
<PropertyGroup>
4+
<Product>NHibernate.Caches.CoreDistributedCache.SqlServer</Product>
5+
<Title>NHibernate.Caches.CoreDistributedCache.SqlServer</Title>
6+
<Description>SQL Server cache provider for NHibernate using .Net Core IDistributedCache (Microsoft.Extensions.Caching.SqlServer).</Description>
7+
<!-- Targeting net461 explicitly in order to avoid https://github.com/dotnet/standard/issues/506 for net461 consumers-->
8+
<TargetFrameworks>net461;netstandard2.0</TargetFrameworks>
9+
<NoWarn>$(NoWarn);3001;3002</NoWarn>
10+
<SignAssembly>True</SignAssembly>
11+
<AssemblyOriginatorKeyFile>..\..\NHibernate.Caches.snk</AssemblyOriginatorKeyFile>
12+
<PackageReleaseNotes>* New feature
13+
* #28 - Add a .Net Core DistributedCache</PackageReleaseNotes>
14+
</PropertyGroup>
15+
<PropertyGroup Condition="'$(TargetFramework)' == 'net461'">
16+
<DefineConstants>NETFX;$(DefineConstants)</DefineConstants>
17+
</PropertyGroup>
18+
<ItemGroup>
19+
<None Include="..\..\NHibernate.Caches.snk" Link="NHibernate.snk" />
20+
</ItemGroup>
21+
<ItemGroup>
22+
<ProjectReference Include="..\NHibernate.Caches.CoreDistributedCache\NHibernate.Caches.CoreDistributedCache.csproj" />
23+
</ItemGroup>
24+
<ItemGroup>
25+
<Content Include="../../readme.md">
26+
<PackagePath>./NHibernate.Caches.readme.md</PackagePath>
27+
</Content>
28+
<Content Include="../../LICENSE.txt">
29+
<PackagePath>./NHibernate.Caches.license.txt</PackagePath>
30+
</Content>
31+
</ItemGroup>
32+
<ItemGroup>
33+
<PackageReference Include="Microsoft.Extensions.Caching.SqlServer" Version="2.0.0" />
34+
</ItemGroup>
35+
</Project>
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Microsoft.Extensions.Caching.Distributed;
4+
using Microsoft.Extensions.Caching.SqlServer;
5+
6+
namespace NHibernate.Caches.CoreDistributedCache.SqlServer
7+
{
8+
/// <summary>
9+
/// A Redis distributed cache factory. See <see cref="SqlServerCache" />.
10+
/// </summary>
11+
public class SqlServerDistributedCacheFactory : IDistributedCacheFactory
12+
{
13+
private static readonly INHibernateLogger Log = NHibernateLogger.For(typeof(SqlServerDistributedCacheFactory));
14+
private const string _connectionString = "connection-string";
15+
private const string _schemaName = "schema-name";
16+
private const string _tableName = "table-name";
17+
private const string _expiredItemsDeletionInterval = "expired-items-deletion-interval";
18+
19+
private readonly SqlServerCacheOptions _options;
20+
21+
/// <summary>
22+
/// Constructor with explicit configuration properties.
23+
/// </summary>
24+
/// <param name="connectionString">See <see cref="SqlServerCacheOptions.ConnectionString" />.</param>
25+
/// <param name="schemaName">See <see cref="SqlServerCacheOptions.SchemaName" />.</param>
26+
/// <param name="tableName">See <see cref="SqlServerCacheOptions.TableName" />.</param>
27+
/// <param name="expiredItemsDeletionInterval">See <see cref="SqlServerCacheOptions.ExpiredItemsDeletionInterval" />.</param>
28+
public SqlServerDistributedCacheFactory(
29+
string connectionString, string schemaName, string tableName, TimeSpan? expiredItemsDeletionInterval)
30+
{
31+
_options = new SqlServerCacheOptions
32+
{
33+
ConnectionString = connectionString,
34+
SchemaName = schemaName,
35+
TableName = tableName,
36+
ExpiredItemsDeletionInterval = expiredItemsDeletionInterval
37+
};
38+
}
39+
40+
/// <summary>
41+
/// Constructor with configuration properties. It supports <c>connection-string</c>, <c>schema-name</c>,
42+
/// <c>table-name</c> and <c>expired-items-deletion-interval</c> properties.
43+
/// See <see cref="SqlServerCacheOptions" />.
44+
/// </summary>
45+
/// <param name="properties">The configurations properties.</param>
46+
/// <remarks>
47+
/// If <c>expired-items-deletion-interval</c> is provided as an integer, this integer will be used as a number
48+
/// of minutes. Otherwise the setting will be parsed as a <see cref="TimeSpan" />.
49+
/// </remarks>
50+
public SqlServerDistributedCacheFactory(IDictionary<string, string> properties)
51+
{
52+
_options = new SqlServerCacheOptions();
53+
54+
if (properties == null)
55+
return;
56+
57+
if (properties.TryGetValue(_connectionString, out var connectionString))
58+
{
59+
_options.ConnectionString = connectionString;
60+
Log.Info("ConnectionString set as '{0}'", connectionString);
61+
}
62+
else
63+
Log.Warn("No {0} property provided", _connectionString);
64+
65+
if (properties.TryGetValue(_schemaName, out var schemaName))
66+
{
67+
_options.SchemaName = schemaName;
68+
Log.Info("SchemaName set as '{0}'", schemaName);
69+
}
70+
else
71+
Log.Warn("No {0} property provided", _schemaName);
72+
73+
if (properties.TryGetValue(_tableName, out var tableName))
74+
{
75+
_options.TableName = tableName;
76+
Log.Info("TableName set as '{0}'", tableName);
77+
}
78+
else
79+
Log.Warn("No {0} property provided", _tableName);
80+
81+
if (properties.TryGetValue(_expiredItemsDeletionInterval, out var eidi))
82+
{
83+
if (eidi != null)
84+
{
85+
if (int.TryParse(eidi, out var minutes))
86+
_options.ExpiredItemsDeletionInterval = TimeSpan.FromMinutes(minutes);
87+
else if (TimeSpan.TryParse(eidi, out var expirationScanFrequency))
88+
_options.ExpiredItemsDeletionInterval = expirationScanFrequency;
89+
else
90+
Log.Warn(
91+
"Invalid value '{0}' for {1} setting: it is neither an int nor a TimeSpan. Ignoring.",
92+
eidi, _expiredItemsDeletionInterval);
93+
}
94+
else
95+
{
96+
Log.Warn("Invalid property {0}: it lacks a value. Ignoring.", _expiredItemsDeletionInterval);
97+
}
98+
}
99+
}
100+
101+
/// <inheritdoc />
102+
public IDistributedCache BuildCache()
103+
{
104+
// According to https://docs.microsoft.com/en-us/aspnet/core/performance/caching/distributed#the-idistributedcache-interface
105+
// (see its paragraph end note) there is no need for a singleton lifetime.
106+
return new SqlServerCache(_options);
107+
}
108+
}
109+
}

CoreDistributedCache/NHibernate.Caches.CoreDistributedCache.Tests/CoreDistributedCacheProviderFixture.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
using Microsoft.Extensions.Caching.Memory;
2828
using NHibernate.Cache;
2929
using NHibernate.Caches.Common.Tests;
30+
using NHibernate.Caches.CoreDistributedCache.Memory;
3031
using NUnit.Framework;
3132

3233
namespace NHibernate.Caches.CoreDistributedCache.Tests

0 commit comments

Comments
 (0)