Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added missing locks and use timeout on all of them in ObjectCacheAppCache #15902

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 45 additions & 8 deletions src/Umbraco.Core/Cache/ObjectCacheAppCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,10 @@ private IEnumerable<object> SearchByPredicate(Func<string, bool> predicate)
object[] entries;
try
{
_locker.EnterReadLock();

if (_locker.TryEnterReadLock(_readLockTimeout) is false)
{
throw new TimeoutException("Timeout exceeded to the memory cache when getting item");
}
entries = _keys.Where(predicate)
.Select(key => MemoryCache.Get(key))
.WhereNotNull()
Expand Down Expand Up @@ -125,11 +127,15 @@ private IEnumerable<object> SearchByPredicate(Func<string, bool> predicate)
if (result == null || SafeLazy.GetSafeLazyValue(result, true) == null)
{
result = SafeLazy.GetSafeLazy(factory);

MemoryCacheEntryOptions options = GetOptions(timeout, isSliding);

try
{
_locker.EnterWriteLock();
if (_locker.TryEnterWriteLock(_writeLockTimeout) is false)
{
throw new TimeoutException("Timeout exceeded to the memory cache when using factory to insert");
}

// NOTE: This does an add or update
MemoryCache.Set(key, result, options);
Expand Down Expand Up @@ -173,12 +179,26 @@ public void Insert(string key, Func<object?> factory, TimeSpan? timeout = null,
{
return; // do not store null values (backward compat)
}

MemoryCacheEntryOptions options = GetOptions(timeout, isSliding);

// NOTE: This does an add or update
MemoryCache.Set(key, result, options);
_keys.Add(key);
try
{
if (_locker.TryEnterWriteLock(_writeLockTimeout) is false)
{
throw new TimeoutException("Cannot insert value into cache, due to timeout for lock.");
}

// NOTE: This does an add or update
MemoryCache.Set(key, result, options);
_keys.Add(key);
}
finally
{
if (_locker.IsWriteLockHeld)
{
_locker.ExitWriteLock();
}
}
}

/// <inheritdoc />
Expand Down Expand Up @@ -348,6 +368,23 @@ private MemoryCacheEntryOptions GetOptions(TimeSpan? timeout = null, bool isSlid
}

// Ensure key is removed from set when evicted from cache
return options.RegisterPostEvictionCallback((key, _, _, _) => _keys.Remove((string)key));
return options.RegisterPostEvictionCallback((key, _, _, _) =>
{
try
{
if (_locker.TryEnterWriteLock(_writeLockTimeout) is false)
{
throw new TimeoutException("Timeout exceeded to the memory cache when using factory to insert");
}
_keys.Remove((string)key);
}
finally
{
if (_locker.IsWriteLockHeld)
{
_locker.ExitWriteLock();
}
}
});
}
}
Loading