Skip to content

Commit 0f53ba8

Browse files
crjcAndyButland
andauthored
fix: check for NullRepresentationInCache in AppCacheExtensions (#19350)
* fix: add appcache null check * Moved constant into standard location. Removed now unnecessary comment. --------- Co-authored-by: Andy Butland <[email protected]>
1 parent 45593c6 commit 0f53ba8

File tree

3 files changed

+15
-9
lines changed

3 files changed

+15
-9
lines changed

src/Umbraco.Core/Cache/AppCacheExtensions.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public static void InsertCacheItem<T>(
4141
public static T? GetCacheItem<T>(this IAppCache provider, string cacheKey)
4242
{
4343
var result = provider.Get(cacheKey);
44-
if (result == null)
44+
if (IsRetrievedItemNull(result))
4545
{
4646
return default;
4747
}
@@ -52,14 +52,16 @@ public static void InsertCacheItem<T>(
5252
public static T? GetCacheItem<T>(this IAppCache provider, string cacheKey, Func<T> getCacheItem)
5353
{
5454
var result = provider.Get(cacheKey, () => getCacheItem());
55-
if (result == null)
55+
if (IsRetrievedItemNull(result))
5656
{
5757
return default;
5858
}
5959

6060
return result.TryConvertTo<T>().Result;
6161
}
6262

63+
private static bool IsRetrievedItemNull(object? result) => result is null or (object)Cms.Core.Constants.Cache.NullRepresentationInCache;
64+
6365
public static async Task<T?> GetCacheItemAsync<T>(
6466
this IAppPolicyCache provider,
6567
string cacheKey,

src/Umbraco.Core/Constants-Cache.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
namespace Umbraco.Cms.Core;
1+
namespace Umbraco.Cms.Core;
22
public static partial class Constants
33
{
44
public static class Cache
@@ -9,5 +9,13 @@ public static class Tags
99

1010
public const string Media = "media";
1111
}
12+
13+
/// <summary>
14+
/// Defines the string used to represent a null value in the cache.
15+
/// </summary>
16+
/// <remarks>
17+
/// Used in conjunction with the option to cache null values on the repository caches, so we
18+
/// can distinguish a true null "not found" value and a cached null value.</remarks>
19+
public const string NullRepresentationInCache = "*NULL*";
1220
}
1321
}

src/Umbraco.Infrastructure/Cache/DefaultRepositoryCachePolicy.cs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@ public class DefaultRepositoryCachePolicy<TEntity, TId> : RepositoryCachePolicyB
2424
private static readonly TEntity[] _emptyEntities = new TEntity[0]; // const
2525
private readonly RepositoryCachePolicyOptions _options;
2626

27-
private const string NullRepresentationInCache = "*NULL*";
28-
2927
public DefaultRepositoryCachePolicy(IAppPolicyCache cache, IScopeAccessor scopeAccessor, RepositoryCachePolicyOptions options)
3028
: base(cache, scopeAccessor) =>
3129
_options = options ?? throw new ArgumentNullException(nameof(options));
@@ -139,10 +137,8 @@ public override void Delete(TEntity entity, Action<TEntity> persistDeleted)
139137
return fromCache;
140138
}
141139

142-
// Because TEntity can never be a string, we will never be in a position where the proxy value collides withs a real value.
143-
// Therefore this point can only be reached if there is a proxy null value => becomes null when cast to TEntity above OR the item simply does not exist.
144140
// If we've cached a "null" value, return null.
145-
if (_options.CacheNullValues && Cache.GetCacheItem<string>(cacheKey) == NullRepresentationInCache)
141+
if (_options.CacheNullValues && Cache.GetCacheItem<string>(cacheKey) == Constants.Cache.NullRepresentationInCache)
146142
{
147143
return null;
148144
}
@@ -273,7 +269,7 @@ protected virtual void InsertNull(string cacheKey)
273269
// a value that does exist but isn't yet cached, or a value that has been explicitly cached with a null value.
274270
// Both would return null when we retrieve from the cache and we couldn't distinguish between the two.
275271
// So we cache a special value that represents null, and then we can check for that value when we retrieve from the cache.
276-
Cache.Insert(cacheKey, () => NullRepresentationInCache, TimeSpan.FromMinutes(5), true);
272+
Cache.Insert(cacheKey, () => Constants.Cache.NullRepresentationInCache, TimeSpan.FromMinutes(5), true);
277273
}
278274

279275
protected virtual void InsertEntities(TId[]? ids, TEntity[]? entities)

0 commit comments

Comments
 (0)