From 660d877cbfa8e8fd5ee27a971ea2eb755953cedd Mon Sep 17 00:00:00 2001 From: Shayne van Asperen Date: Tue, 3 Nov 2020 13:29:54 +0000 Subject: [PATCH] Make CacheKey member of base CachedQuery class abstract so that implementors don't forget to set the VaryBy property --- samples/Samples/Controllers/UsersController.cs | 2 ++ src/Magneto/Core/CachedQuery.cs | 5 ++--- src/Magneto/IKeyConfig.cs | 16 ++++++++++++++-- .../Core/OperationTests/OperationTests.cs | 4 ++++ 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/samples/Samples/Controllers/UsersController.cs b/samples/Samples/Controllers/UsersController.cs index 428caea..9d70d66 100644 --- a/samples/Samples/Controllers/UsersController.cs +++ b/samples/Samples/Controllers/UsersController.cs @@ -73,6 +73,8 @@ protected override Task TransformCachedResult(User[] cachedResult, Cancell public class AlbumsByUserId : SyncTransformedCachedQuery<(IFileProvider, ILogger), MemoryCacheEntryOptions, Album[], Album[]> { + protected override void CacheKey(IKeyConfig keyConfig) => keyConfig.VaryByNothing(); + protected override MemoryCacheEntryOptions CacheEntryOptions((IFileProvider, ILogger) context) { var (fileProvider, logger) = context; diff --git a/src/Magneto/Core/CachedQuery.cs b/src/Magneto/Core/CachedQuery.cs index 00c05ba..573e927 100644 --- a/src/Magneto/Core/CachedQuery.cs +++ b/src/Magneto/Core/CachedQuery.cs @@ -107,11 +107,10 @@ public abstract class CachedQuery : internal readonly Store State; /// - /// Configures details for constructing a cache key. - /// Implementors can choose not to override this method if the cache key doesn't need to vary by anything. + /// Configures details for constructing a cache key. /// /// The configuration object. - protected virtual void CacheKey(IKeyConfig keyConfig) { } + protected abstract void CacheKey(IKeyConfig keyConfig); /// /// Returns options pertaining to the cache entry (such as expiration policy). diff --git a/src/Magneto/IKeyConfig.cs b/src/Magneto/IKeyConfig.cs index 879651d..a3d4a85 100644 --- a/src/Magneto/IKeyConfig.cs +++ b/src/Magneto/IKeyConfig.cs @@ -1,4 +1,6 @@ using System; +using System.ComponentModel; +using System.Linq; namespace Magneto { @@ -33,6 +35,7 @@ public interface IKeyConfig /// /// An extension class for fluent configuration of instances. /// + [EditorBrowsable(EditorBrowsableState.Never)] public static class KeyConfigExtensions { /// @@ -59,10 +62,19 @@ public static IKeyConfig UsePrefix(this IKeyConfig keyConfig, string value) /// keyConfig.VaryBy($"{Foo}_{Baz.Id}")
/// ///
- public static IKeyConfig VaryBy(this IKeyConfig keyConfig, params object[] value) + public static IKeyConfig VaryBy(this IKeyConfig keyConfig, object firstValue, params object[] additionalValues) + { + if (keyConfig == null) throw new ArgumentNullException(nameof(keyConfig)); + keyConfig.VaryBy = new[] { firstValue }.Concat(additionalValues); + return keyConfig; + } + + /// + /// A convenience method to express that the cache key should not vary by anything. + /// + public static IKeyConfig VaryByNothing(this IKeyConfig keyConfig) { if (keyConfig == null) throw new ArgumentNullException(nameof(keyConfig)); - keyConfig.VaryBy = value; return keyConfig; } } diff --git a/test/Magneto.Tests/Core/OperationTests/OperationTests.cs b/test/Magneto.Tests/Core/OperationTests/OperationTests.cs index a2940bd..094a632 100644 --- a/test/Magneto.Tests/Core/OperationTests/OperationTests.cs +++ b/test/Magneto.Tests/Core/OperationTests/OperationTests.cs @@ -306,18 +306,21 @@ public class AsyncQueryWithoutProperties : AsyncQuery public class SyncCachedQueryWithoutProperties : SyncCachedQuery { + protected override void CacheKey(IKeyConfig keyConfig) => throw new NotImplementedException(); protected override object CacheEntryOptions(object context) => throw new NotImplementedException(); protected override object Query(object context) => throw new NotImplementedException(); } public class AsyncCachedQueryWithoutProperties : AsyncCachedQuery { + protected override void CacheKey(IKeyConfig keyConfig) => throw new NotImplementedException(); protected override object CacheEntryOptions(object context) => throw new NotImplementedException(); protected override Task Query(object context, CancellationToken cancellationToken) => throw new NotImplementedException(); } public class SyncTransformedCachedQueryWithoutProperties : SyncTransformedCachedQuery { + protected override void CacheKey(IKeyConfig keyConfig) => throw new NotImplementedException(); protected override object CacheEntryOptions(object context) => throw new NotImplementedException(); protected override object Query(object context) => throw new NotImplementedException(); protected override object TransformCachedResult(object cachedResult) => throw new NotImplementedException(); @@ -325,6 +328,7 @@ public class SyncTransformedCachedQueryWithoutProperties : SyncTransformedCached public class AsyncTransformedCachedQueryWithoutProperties : AsyncTransformedCachedQuery { + protected override void CacheKey(IKeyConfig keyConfig) => throw new NotImplementedException(); protected override object CacheEntryOptions(object context) => throw new NotImplementedException(); protected override Task Query(object context, CancellationToken cancellationToken) => throw new NotImplementedException(); protected override Task TransformCachedResult(object cachedResult, CancellationToken cancellationToken) => throw new NotImplementedException();