Skip to content

Commit

Permalink
Update MonkeyCache to 2.0
Browse files Browse the repository at this point in the history
- Drop Newtonsoft and use System.Text.Json instead
    - Allow for source generators to be used in IBarrel
- Drop Xamarin TFMs and just target net6.0
- Mark MonkeyCache assemblies as IsTrimmable=true, so unused code can be trimmed
  • Loading branch information
eerhardt committed Mar 22, 2022
1 parent 9438c3b commit 0fe2e02
Show file tree
Hide file tree
Showing 10 changed files with 199 additions and 219 deletions.
87 changes: 42 additions & 45 deletions src/MonkeyCache.FileStore/Barrel.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization.Metadata;
using System.Threading;
using Newtonsoft.Json;

namespace MonkeyCache.FileStore
{
public class Barrel : IBarrel
{
ReaderWriterLockSlim indexLocker;
readonly JsonSerializerSettings jsonSettings;
Lazy<string> baseDirectory;
HashAlgorithm hashAlgorithm;

Expand All @@ -36,13 +37,6 @@ public class Barrel : IBarrel

indexLocker = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);

jsonSettings = new JsonSerializerSettings
{
ObjectCreationHandling = ObjectCreationHandling.Replace,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
TypeNameHandling = TypeNameHandling.All,
};

index = new Dictionary<string, Tuple<string, DateTime>>();

LoadIndex();
Expand All @@ -68,14 +62,7 @@ public class Barrel : IBarrel
public static IBarrel Create(string cacheDirectory, HashAlgorithm hash = null) =>
new Barrel(cacheDirectory, hash);

/// <summary>
/// Adds an entry to the barrel
/// </summary>
/// <param name="key">Unique identifier for the entry</param>
/// <param name="data">Data object to store</param>
/// <param name="expireIn">Time from UtcNow to expire entry in</param>
/// <param name="eTag">Optional eTag information</param>
void Add(string key, string data, TimeSpan expireIn, string eTag = null)
void Add(string key, string data, TimeSpan expireIn, string eTag)
{
indexLocker.EnterWriteLock();

Expand All @@ -99,42 +86,45 @@ void Add(string key, string data, TimeSpan expireIn, string eTag = null)
}
}

/// <summary>
/// Adds an entry to the barrel
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key">Unique identifier for the entry</param>
/// <param name="data">Data object to store</param>
/// <param name="expireIn">Time from UtcNow to expire entry in</param>
/// <param name="eTag">Optional eTag information</param>
/// <param name="jsonSerializationSettings">Custom json serialization settings to use</param>
public void Add<T>(string key,
T data,
TimeSpan expireIn,
string eTag = null,
JsonSerializerSettings jsonSerializationSettings = null)
void Add<T>(
string key,
T data,
TimeSpan expireIn,
string eTag,
Func<T, string> serializer)
{

if (string.IsNullOrWhiteSpace(key))
throw new ArgumentException("Key can not be null or empty.", nameof(key));

if (data == null)
throw new ArgumentNullException("Data can not be null.", nameof(data));

var dataJson = string.Empty;

string dataJson;
if (BarrelUtils.IsString(data))
{
dataJson = data as string;
}
else
{
dataJson = JsonConvert.SerializeObject(data, jsonSerializationSettings ?? jsonSettings);
dataJson = serializer(data);
}

Add(key, dataJson, expireIn, eTag);
}

/// <inheritdoc/>
[RequiresUnreferencedCode("JSON serialization and deserialization might require types that cannot be statically analyzed. Use the overload that takes a JsonTypeInfo, or make sure all of the required types are preserved.")]
public void Add<T>(string key, T data, TimeSpan expireIn, JsonSerializerOptions options = null, string eTag = null) =>
Add(key, data, expireIn, eTag, data => JsonSerialize(data, options));

[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Workaround https://github.com/dotnet/linker/issues/2001")]
static string JsonSerialize<T>(T data, JsonSerializerOptions options) =>
JsonSerializer.Serialize(data, options);

/// <inheritdoc/>
public void Add<T>(string key, T data, TimeSpan expireIn, JsonTypeInfo<T> jsonTypeInfo, string eTag = null) =>
Add(key, data, expireIn, eTag, data => JsonSerializer.Serialize(data, jsonTypeInfo));

/// <summary>
/// Empties all specified entries regardless if they are expired.
/// Throws an exception if any deletions fail and rolls back changes.
Expand All @@ -152,7 +142,7 @@ public void Empty(params string[] key)
continue;

var file = Path.Combine(baseDirectory.Value, Hash(k));
if(File.Exists(file))
if (File.Exists(file))
File.Delete(file);

index.Remove(k);
Expand Down Expand Up @@ -180,7 +170,7 @@ public void EmptyAll()
{
var hash = Hash(item.Key);
var file = Path.Combine(baseDirectory.Value, hash);
if(File.Exists(file))
if (File.Exists(file))
File.Delete(file);
}

Expand Down Expand Up @@ -295,13 +285,7 @@ public IEnumerable<string> GetKeys(CacheState state = CacheState.Active)
}
}

/// <summary>
/// Gets the data entry for the specified key.
/// </summary>
/// <param name="key">Unique identifier for the entry to get</param>
/// <param name="jsonSerializationSettings">Custom json serialization settings to use</param>
/// <returns>The data object that was stored if found, else default(T)</returns>
public T Get<T>(string key, JsonSerializerSettings jsonSerializationSettings = null)
T Get<T>(string key, Func<string, T> deserialize)
{
if (string.IsNullOrWhiteSpace(key))
throw new ArgumentException("Key can not be null or empty.", nameof(key));
Expand All @@ -324,7 +308,7 @@ public T Get<T>(string key, JsonSerializerSettings jsonSerializationSettings = n
return (T)final;
}

result = JsonConvert.DeserializeObject<T>(contents, jsonSerializationSettings ?? jsonSettings);
result = deserialize(contents);
}
}
finally
Expand All @@ -335,6 +319,19 @@ public T Get<T>(string key, JsonSerializerSettings jsonSerializationSettings = n
return result;
}

/// <inheritdoc/>
[RequiresUnreferencedCode("JSON serialization and deserialization might require types that cannot be statically analyzed. Use the overload that takes a JsonTypeInfo, or make sure all of the required types are preserved.")]
public T Get<T>(string key, JsonSerializerOptions options = null) =>
Get(key, contents => JsonDeserialize<T>(contents, options));

[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Workaround https://github.com/dotnet/linker/issues/2001")]
static T JsonDeserialize<T>(string contents, JsonSerializerOptions options) =>
JsonSerializer.Deserialize<T>(contents, options);

/// <inheritdoc/>
public T Get<T>(string key, JsonTypeInfo<T> jsonTypeInfo) => Get(key, contents =>
JsonSerializer.Deserialize(contents, jsonTypeInfo));

/// <summary>
/// Gets the DateTime that the item will expire for the specified key.
/// </summary>
Expand Down
30 changes: 10 additions & 20 deletions src/MonkeyCache.FileStore/MonkeyCache.FileStore.csproj
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
<Project Sdk="MSBuild.Sdk.Extras/3.0.44">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>netstandard2.0;MonoAndroid10.0;Xamarin.iOS10;Xamarin.TVOS10;Xamarin.Mac20;net6.0-android;net6.0-ios;net6.0-maccatalyst</TargetFrameworks>
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">$(TargetFrameworks);uap10.0.19041;net6.0-windows10.0.19041;net461</TargetFrameworks>
<Product>$(AssemblyName) ($(TargetFramework))</Product>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
<AssemblyFileVersion>1.0.0.0</AssemblyFileVersion>
<Version>1.0.0.0</Version>
<PackageVersion>1.0.0.0</PackageVersion>
<TargetFrameworks>net6.0-android;net6.0-ios;net6.0-maccatalyst;net6.0-windows10.0.19041</TargetFrameworks>
<Product>$(AssemblyName) ($(TargetFramework))</Product>
<AssemblyVersion>2.0.0.0</AssemblyVersion>
<AssemblyFileVersion>2.0.0.0</AssemblyFileVersion>
<Version>2.0.0.0</Version>
<PackageVersion>2.0.0.0</PackageVersion>
<Authors>James Montemagno</Authors>
<PackageId>MonkeyCache.FileStore</PackageId>
<PackOnBuild>true</PackOnBuild>
Expand All @@ -33,6 +32,7 @@
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<GenerateDocumentationFile Condition=" '$(Configuration)' == 'Release' ">true</GenerateDocumentationFile>
<DebugType>portable</DebugType>
<IsTrimmable>true</IsTrimmable>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)'=='Debug' ">
<DebugSymbols>true</DebugSymbols>
Expand All @@ -50,29 +50,19 @@
</ItemGroup>

<PropertyGroup>
<SupportedOSPlatformVersion Condition="$(TargetFramework.Contains('-android'))">21.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$(TargetFramework.Contains('-ios'))">10.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$(TargetFramework.Contains('-tvos'))">10.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$(TargetFramework.Contains('-maccatalyst'))">13.1</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$(TargetFramework.Contains('-macos'))">10.14</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$(TargetFramework.Contains('-android'))">21.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$(TargetFramework.Contains('-windows10'))">10.0.16299.0</SupportedOSPlatformVersion>
<TargetPlatformMinVersion Condition="$(TargetFramework.Contains('-windows10'))">10.0.16299.0</TargetPlatformMinVersion>
</PropertyGroup>
<PropertyGroup Condition=" $(TargetFramework.StartsWith('uap10.0')) ">
<TargetPlatformMinVersion>10.0.16299.0</TargetPlatformMinVersion>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>

<ItemGroup>
<ItemGroup>
<Compile Include="..\MonkeyCache.Shared\**\*.cs" LinkBase="Shared" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\MonkeyCache\MonkeyCache.csproj" />
<Reference Condition=" '$(TargetFramework)' == 'Xamarin.Mac20' " Include="netstandard" />
</ItemGroup>

</Project>
74 changes: 35 additions & 39 deletions src/MonkeyCache.LiteDB/Barrel.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization.Metadata;
using LiteDB;
using Newtonsoft.Json;
using JsonSerializer = System.Text.Json.JsonSerializer;

namespace MonkeyCache.LiteDB
{
Expand Down Expand Up @@ -44,7 +47,6 @@ public static IBarrel Create(string cacheDirectory, bool cache = false)
return instance;
}

readonly JsonSerializerSettings jsonSettings;
Barrel(string cacheDirectory = null)
{
var directory = string.IsNullOrEmpty(cacheDirectory) ? baseCacheDir.Value : cacheDirectory;
Expand Down Expand Up @@ -72,13 +74,6 @@ public static IBarrel Create(string cacheDirectory, bool cache = false)

db = new LiteDatabase(path);
col = db.GetCollection<Banana>();

jsonSettings = new JsonSerializerSettings
{
ObjectCreationHandling = ObjectCreationHandling.Replace,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
TypeNameHandling = TypeNameHandling.All,
};
}

#region Exist and Expiration Methods
Expand Down Expand Up @@ -148,13 +143,7 @@ public IEnumerable<string> GetKeys(CacheState state = CacheState.Active)
return new string[0];
}

/// <summary>
/// Gets the data entry for the specified key.
/// </summary>
/// <param name="key">Unique identifier for the entry to get</param>
/// <param name="jsonSerializationSettings">Custom json serialization settings to use</param>
/// <returns>The data object that was stored if found, else default(T)</returns>
public T Get<T>(string key, JsonSerializerSettings jsonSerializationSettings = null)
T Get<T>(string key, Func<string, T> deserialize)
{
if (string.IsNullOrWhiteSpace(key))
throw new ArgumentException("Key can not be null or empty.", nameof(key));
Expand All @@ -172,9 +161,21 @@ public T Get<T>(string key, JsonSerializerSettings jsonSerializationSettings = n
return (T)final;
}

return JsonConvert.DeserializeObject<T>(ent.Contents, jsonSerializationSettings ?? jsonSettings);
return deserialize(ent.Contents);
}

/// <inheritdoc/>
[RequiresUnreferencedCode("JSON serialization and deserialization might require types that cannot be statically analyzed. Use the overload that takes a JsonTypeInfo, or make sure all of the required types are preserved.")]
public T Get<T>(string key, JsonSerializerOptions options = null) =>
Get(key, contents => JsonDeserialize<T>(contents, options));

[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Workaround https://github.com/dotnet/linker/issues/2001")]
private static T JsonDeserialize<T>(string contents, JsonSerializerOptions options) =>
JsonSerializer.Deserialize<T>(contents, options);

/// <inheritdoc/>
public T Get<T>(string key, JsonTypeInfo<T> jsonTypeInfo) =>
Get(key, contents => JsonSerializer.Deserialize(contents, jsonTypeInfo));

/// <summary>
/// Gets the ETag for the specified key.
Expand Down Expand Up @@ -216,15 +217,7 @@ public string GetETag(string key)

#region Add Methods

/// <summary>
/// Adds a string netry to the barrel
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key">Unique identifier for the entry</param>
/// <param name="data">Data string to store</param>
/// <param name="expireIn">Time from UtcNow to expire entry in</param>
/// <param name="eTag">Optional eTag information</param>
void Add(string key, string data, TimeSpan expireIn, string eTag = null)
void Add(string key, string data, TimeSpan expireIn, string eTag)
{
if (data == null)
return;
Expand All @@ -240,37 +233,40 @@ void Add(string key, string data, TimeSpan expireIn, string eTag = null)
col.Upsert(ent);
}

/// <summary>
/// Adds an entry to the barrel
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key">Unique identifier for the entry</param>
/// <param name="data">Data object to store</param>
/// <param name="expireIn">Time from UtcNow to expire entry in</param>
/// <param name="eTag">Optional eTag information</param>
/// <param name="jsonSerializationSettings">Custom json serialization settings to use</param>
public void Add<T>(string key, T data, TimeSpan expireIn, string eTag = null, JsonSerializerSettings jsonSerializationSettings = null)
void Add<T>(string key, T data, TimeSpan expireIn, string eTag, Func<T, string> serializer)
{
if (string.IsNullOrWhiteSpace(key))
throw new ArgumentException("Key can not be null or empty.", nameof(key));

if (data == null)
throw new ArgumentNullException("Data can not be null.", nameof(data));

var dataJson = string.Empty;

string dataJson;
if (BarrelUtils.IsString(data))
{
dataJson = data as string;
}
else
{
dataJson = JsonConvert.SerializeObject(data, jsonSerializationSettings ?? jsonSettings);
dataJson = serializer(data);
}

Add(key, dataJson, expireIn, eTag);
}

/// <inheritdoc/>
[RequiresUnreferencedCode("JSON serialization and deserialization might require types that cannot be statically analyzed. Use the overload that takes a JsonTypeInfo, or make sure all of the required types are preserved.")]
public void Add<T>(string key, T data, TimeSpan expireIn, JsonSerializerOptions options = null, string eTag = null) =>
Add(key, data, expireIn, eTag, data => JsonSerialize(data, options));

[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Workaround https://github.com/dotnet/linker/issues/2001")]
static string JsonSerialize<T>(T data, JsonSerializerOptions options) =>
JsonSerializer.Serialize(data, options);

/// <inheritdoc/>
public void Add<T>(string key, T data, TimeSpan expireIn, JsonTypeInfo<T> jsonTypeInfo, string eTag = null) =>
Add(key, data, expireIn, eTag, data => JsonSerializer.Serialize(data, jsonTypeInfo));

#endregion

#region Empty Methods
Expand Down
Loading

0 comments on commit 0fe2e02

Please sign in to comment.