Load Balancing: Clear request cache in cache version accessor on cache version update to prevent unnecessary cache roll forwards (#20831)

* Clear request cache on version update

* Update src/Umbraco.Core/Cache/IRepositoryCacheVersionAccessor.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Mole
2025-11-14 14:14:28 +01:00
committed by GitHub
parent 342cb171eb
commit 2a609e1eca
3 changed files with 22 additions and 2 deletions

View File

@@ -20,7 +20,14 @@ public interface IRepositoryCacheVersionAccessor
/// <returns> /// <returns>
/// The cache version if found, or <see langword="null"/> if the version doesn't exist or the request is a client-side request. /// The cache version if found, or <see langword="null"/> if the version doesn't exist or the request is a client-side request.
/// </returns> /// </returns>
public Task<RepositoryCacheVersion?> GetAsync(string cacheKey); Task<RepositoryCacheVersion?> GetAsync(string cacheKey);
/// <summary>
/// Notifies of a version change on a given cache key.
/// </summary>
/// <param name="cacheKey">Key of the changed version.</param>
void VersionChanged(string cacheKey)
{ }
/// <summary> /// <summary>
/// Notifies the accessor that caches have been synchronized. /// Notifies the accessor that caches have been synchronized.
@@ -29,5 +36,5 @@ public interface IRepositoryCacheVersionAccessor
/// This method is called after cache synchronization to temporarily bypass version checking, /// This method is called after cache synchronization to temporarily bypass version checking,
/// preventing recursive sync attempts while repositories reload data from the database. /// preventing recursive sync attempts while repositories reload data from the database.
/// </remarks> /// </remarks>
public void CachesSynced(); void CachesSynced();
} }

View File

@@ -88,6 +88,7 @@ internal class RepositoryCacheVersionService : IRepositoryCacheVersionService
_logger.LogDebug("Setting cache for {EntityType} to version {Version}", typeof(TEntity).Name, newVersion); _logger.LogDebug("Setting cache for {EntityType} to version {Version}", typeof(TEntity).Name, newVersion);
await _repositoryCacheVersionRepository.SaveAsync(new RepositoryCacheVersion { Identifier = cacheKey, Version = newVersion.ToString() }); await _repositoryCacheVersionRepository.SaveAsync(new RepositoryCacheVersion { Identifier = cacheKey, Version = newVersion.ToString() });
_cacheVersions[cacheKey] = newVersion; _cacheVersions[cacheKey] = newVersion;
_repositoryCacheVersionAccessor.VersionChanged(cacheKey);
scope.Complete(); scope.Complete();
} }

View File

@@ -77,5 +77,17 @@ public class RepositoryCacheVersionAccessor : IRepositoryCacheVersionAccessor
return databaseVersion; return databaseVersion;
} }
/// <inheritdoc />
public void VersionChanged(string cacheKey)
{
var removed = _requestCache.Remove(cacheKey);
if (removed is false)
{
_logger.LogDebug("Cache version for key {CacheKey} wasn't removed from request cache, possibly missing HTTP context", cacheKey);
}
}
/// <inheritdoc />
public void CachesSynced() => _requestCache.ClearOfType<RepositoryCacheVersion>(); public void CachesSynced() => _requestCache.ClearOfType<RepositoryCacheVersion>();
} }