Skip to content

Commit eee04f4

Browse files
committed
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]> # Conflicts: # src/Umbraco.Core/Cache/AppCacheExtensions.cs # src/Umbraco.Core/Constants-Cache.cs
1 parent 127c6c4 commit eee04f4

File tree

3 files changed

+21
-8
lines changed

3 files changed

+21
-8
lines changed

src/Umbraco.Core/Cache/AppCacheExtensions.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public static void InsertCacheItem<T>(
4343
public static T? GetCacheItem<T>(this IAppCache provider, string cacheKey)
4444
{
4545
var result = provider.Get(cacheKey);
46-
if (result == null)
46+
if (IsRetrievedItemNull(result))
4747
{
4848
return default;
4949
}
@@ -54,11 +54,13 @@ public static void InsertCacheItem<T>(
5454
public static T? GetCacheItem<T>(this IAppCache provider, string cacheKey, Func<T> getCacheItem)
5555
{
5656
var result = provider.Get(cacheKey, () => getCacheItem());
57-
if (result == null)
57+
if (IsRetrievedItemNull(result))
5858
{
5959
return default;
6060
}
6161

6262
return result.TryConvertTo<T>().Result;
6363
}
64+
65+
private static bool IsRetrievedItemNull(object? result) => result is null or (object)Cms.Core.Constants.Cache.NullRepresentationInCache;
6466
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
namespace Umbraco.Cms.Core;
2+
3+
public static partial class Constants
4+
{
5+
public static class Cache
6+
{
7+
/// <summary>
8+
/// Defines the string used to represent a null value in the cache.
9+
/// </summary>
10+
/// <remarks>
11+
/// Used in conjunction with the option to cache null values on the repository caches, so we
12+
/// can distinguish a true null "not found" value and a cached null value.</remarks>
13+
public const string NullRepresentationInCache = "*NULL*";
14+
}
15+
}

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)