Skip to content

Commit

Permalink
(GH-613) Re-factor the in-memory caching provider
Browse files Browse the repository at this point in the history
  • Loading branch information
johelvisguzman committed Oct 18, 2021
1 parent 75665e0 commit 4c2d6fc
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 181 deletions.
136 changes: 0 additions & 136 deletions src/DotNetToolkit.Repository.Caching.InMemory/InMemoryCache.cs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
namespace DotNetToolkit.Repository.Caching.InMemory
{
using DotNetToolkit.Repository.Utility;
using JetBrains.Annotations;
using Microsoft.Extensions.Internal;
using System;

/// <summary>
/// The options to be used by the in-memory caching provider.
/// </summary>
public class InMemoryCacheOptions
{
internal ISystemClock Clock { get; set; }
internal TimeSpan? ExpirationScanFrequency { get; set; }
internal TimeSpan? Expiry { get; set; }

internal InMemoryCacheOptions() { }

/// <summary>
/// Adds the giving system clock vaue to the options.
/// </summary>
/// <param name="clock">The system clock to be added.</param>
public InMemoryCacheOptions WithClock([NotNull] ISystemClock clock)
{
Clock = Guard.NotNull(clock, nameof(clock));

return this;
}

/// <summary>
/// Adds the giving system clock vaue to the options.
/// </summary>
/// <param name="expirationScanFrequency">The minimum length of time between successive scans for expired items to be added.</param>
public InMemoryCacheOptions WithExpirationScanFrequency([NotNull] TimeSpan expirationScanFrequency)
{
ExpirationScanFrequency = Guard.NotNull(expirationScanFrequency, nameof(expirationScanFrequency));

return this;
}

/// <summary>
/// Adds the giving caching expiration time to the options.
/// </summary>
/// <param name="expiry">The caching expiration time to be added.</param>
public InMemoryCacheOptions WithExpiry([NotNull] TimeSpan expiry)
{
Expiry = Guard.NotNull(expiry, nameof(expiry));

return this;
}
}
}
129 changes: 84 additions & 45 deletions src/DotNetToolkit.Repository.Caching.InMemory/InMemoryCacheProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,72 +3,111 @@
using Configuration.Caching;
using JetBrains.Annotations;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Internal;
using System;
using Utility;

/// <summary>
/// An implementation of <see cref="ICacheProvider{TCache}" />.
/// </summary>
public class InMemoryCacheProvider : CacheProviderBase<InMemoryCache>
internal class InMemoryCacheProvider : ICacheProvider
{
#region Properties

public IMemoryCache Cache { get; }
public TimeSpan? Expiry { get; set; }

#endregion

#region Constructors

/// <summary>
/// Initializes a new instance of the <see cref="InMemoryCacheProvider" /> class.
/// </summary>
public InMemoryCacheProvider() : this((TimeSpan?)null) { }

/// <summary>
/// Initializes a new instance of the <see cref="InMemoryCacheProvider" /> class.
/// </summary>
/// <param name="expiry">The caching expiration time.</param>
public InMemoryCacheProvider([CanBeNull] TimeSpan? expiry) : this(new MemoryCache(new MemoryCacheOptions()), expiry) { }

/// <summary>
/// Initializes a new instance of the <see cref="InMemoryCacheProvider" /> class.
/// </summary>
/// <param name="optionsAction">The configuration options action.</param>
public InMemoryCacheProvider([NotNull] Action<MemoryCacheOptions> optionsAction) : this(optionsAction, (TimeSpan?)null) { }

/// <summary>
/// Initializes a new instance of the <see cref="InMemoryCacheProvider" /> class.
/// </summary>
/// <param name="optionsAction">The configuration options action.</param>
/// <param name="expiry">The caching expiration time.</param>
public InMemoryCacheProvider([NotNull] Action<MemoryCacheOptions> optionsAction, [CanBeNull] TimeSpan? expiry) : this(new MemoryCache(GetConfigurationOptions(optionsAction)), expiry) { }

/// <summary>
/// Initializes a new instance of the <see cref="InMemoryCacheProvider" /> class.
/// </summary>
/// <param name="cache">The underlying caching storage.</param>
public InMemoryCacheProvider([NotNull] IMemoryCache cache) : this(cache, (TimeSpan?)null) { }

/// <summary>
/// Initializes a new instance of the <see cref="InMemoryCacheProvider" /> class.
/// </summary>
/// <param name="cache">The underlying caching storage.</param>
/// <param name="expiry">The caching expiration time.</param>
public InMemoryCacheProvider([NotNull] IMemoryCache cache, [CanBeNull] TimeSpan? expiry)
public InMemoryCacheProvider() : this(null, null, null) { }

public InMemoryCacheProvider(ISystemClock clock, TimeSpan? expirationScanFrequency, TimeSpan? expiry)
: this (GetMemoryCacheOptions(clock, expirationScanFrequency), expiry) { }

private InMemoryCacheProvider(MemoryCacheOptions options, TimeSpan? expiry)
{
Cache = new InMemoryCache(Guard.NotNull(cache, nameof(cache)));
Cache = new MemoryCache(Guard.NotNull(options, nameof(options)));
Expiry = expiry;
}

#endregion

#region Private Methods

private static MemoryCacheOptions GetConfigurationOptions(Action<MemoryCacheOptions> optionsAction)
private static MemoryCacheOptions GetMemoryCacheOptions(ISystemClock clock, TimeSpan? expirationScanFrequency)
{
Guard.NotNull(optionsAction, nameof(optionsAction));

var options = new MemoryCacheOptions();

optionsAction(options);
options.Clock = clock;

if (expirationScanFrequency.HasValue)
{
options.ExpirationScanFrequency = expirationScanFrequency.Value;
}

return options;
}

private void Set<T>(string key, T value, CacheItemPriority priority, TimeSpan? expiry, Action<string> cacheRemovedCallback = null)
{
Guard.NotEmpty(key, nameof(key));

var policy = new MemoryCacheEntryOptions();

if (cacheRemovedCallback != null)
{
policy.PostEvictionCallbacks.Add(new PostEvictionCallbackRegistration
{
EvictionCallback = (o, val, reason, state) =>
{
cacheRemovedCallback(reason.ToString());
}
});
}

if (expiry.HasValue && expiry.Value != TimeSpan.Zero)
policy.AbsoluteExpiration = DateTimeOffset.Now.Add(expiry.Value);

if (expiry.HasValue && expiry.Value == TimeSpan.Zero && priority != CacheItemPriority.NeverRemove)
policy.Priority = CacheItemPriority.NeverRemove;
else
policy.Priority = priority;

Cache.Set<T>(key, value, policy);
}

#endregion

#region Implementation of ICacheProvider

public void Set<T>([NotNull] string key, T value, TimeSpan? expiry = null, Action<string> cacheRemovedCallback = null)
{
Set<T>(key, value, CacheItemPriority.Normal, expiry ?? Expiry, cacheRemovedCallback);
}

public void Remove([NotNull] string key)
{
Cache.Remove(Guard.NotEmpty(key, nameof(key)));
}

public bool TryGetValue<T>([NotNull] string key, out T value)
{
return Cache.TryGetValue<T>(Guard.NotEmpty(key, nameof(key)), out value);
}

public int Increment([NotNull] string key, int defaultValue, int incrementValue)
{
Guard.NotEmpty(key, nameof(key));

if (!TryGetValue<int>(key, out var current))
current = defaultValue;

var value = current + incrementValue;

Set<int>(key, value, CacheItemPriority.NeverRemove, expiry: null);

return value;
}

#endregion
}
}

0 comments on commit 4c2d6fc

Please sign in to comment.