U4-8397 - Cleanup server registration db & cache
This commit is contained in:
@@ -10,19 +10,24 @@ using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence.Factories;
|
||||
using Umbraco.Core.Persistence.Mappers;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
internal class ServerRegistrationRepository : NPocoRepositoryBase<int, IServerRegistration>, IServerRegistrationRepository
|
||||
{
|
||||
private readonly ICacheProvider _staticCache;
|
||||
private IRepositoryCachePolicy<IServerRegistration, int> _cachePolicy;
|
||||
|
||||
public ServerRegistrationRepository(IDatabaseUnitOfWork work, CacheHelper cacheHelper, ILogger logger, IMappingResolver mappingResolver)
|
||||
: base(work, CacheHelper.CreateDisabledCacheHelper(), logger, mappingResolver)
|
||||
{ }
|
||||
|
||||
protected override IRepositoryCachePolicy<IServerRegistration, int> CachePolicy => _cachePolicy
|
||||
?? (_cachePolicy = new FullDataSetRepositoryCachePolicy<IServerRegistration, int>(RuntimeCache, GetEntityId, /*expires:*/ false));
|
||||
|
||||
public void ClearCache()
|
||||
{
|
||||
_staticCache = cacheHelper.StaticCache;
|
||||
CachePolicy.ClearAll();
|
||||
}
|
||||
|
||||
protected override int PerformCount(IQuery<IServerRegistration> query)
|
||||
@@ -44,15 +49,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
protected override IEnumerable<IServerRegistration> PerformGetAll(params int[] ids)
|
||||
{
|
||||
// we do NOT want to populate the cache on-demand, because then it might happen
|
||||
// during a ReadCommited transaction, and reading the registrations under ReadCommited
|
||||
// is NOT safe because they could be updated in the middle of the read.
|
||||
//
|
||||
// the cache is populated by ReloadCache which should only be called from methods
|
||||
// that ensure proper locking (at least, read-lock in ReadCommited) of the repo.
|
||||
|
||||
var all = _staticCache.GetCacheItem<IEnumerable<IServerRegistration>>(CacheKey, Enumerable.Empty<IServerRegistration>);
|
||||
return ids.Length == 0 ? all : all.Where(x => ids.Contains(x.Id));
|
||||
var factory = new ServerRegistrationFactory();
|
||||
return Database.Fetch<ServerRegistrationDto>("WHERE id > 0")
|
||||
.Select(x => factory.BuildEntity(x));
|
||||
}
|
||||
|
||||
protected override IEnumerable<IServerRegistration> PerformGetByQuery(IQuery<IServerRegistration> query)
|
||||
@@ -104,7 +103,6 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
entity.Id = id;
|
||||
|
||||
entity.ResetDirtyProperties();
|
||||
ReloadCache();
|
||||
}
|
||||
|
||||
protected override void PersistUpdatedItem(IServerRegistration entity)
|
||||
@@ -117,26 +115,6 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
Database.Update(dto);
|
||||
|
||||
entity.ResetDirtyProperties();
|
||||
ReloadCache();
|
||||
}
|
||||
|
||||
public override void PersistDeletedItem(IEntity entity)
|
||||
{
|
||||
base.PersistDeletedItem(entity);
|
||||
ReloadCache();
|
||||
}
|
||||
|
||||
private static readonly string CacheKey = GetCacheTypeKey<IServerRegistration>() + "all";
|
||||
|
||||
public void ReloadCache()
|
||||
{
|
||||
var factory = new ServerRegistrationFactory();
|
||||
var all = Database.Fetch<ServerRegistrationDto>("WHERE id > 0")
|
||||
.Select(x => factory.BuildEntity(x))
|
||||
.Cast<IServerRegistration>()
|
||||
.ToArray();
|
||||
_staticCache.ClearCacheItem(CacheKey);
|
||||
_staticCache.GetCacheItem(CacheKey, () => all);
|
||||
}
|
||||
|
||||
public void DeactiveStaleServers(TimeSpan staleTimeout)
|
||||
@@ -144,7 +122,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
var timeoutDate = DateTime.Now.Subtract(staleTimeout);
|
||||
|
||||
Database.Update<ServerRegistrationDto>("SET isActive=0, isMaster=0 WHERE lastNotifiedDate < @timeoutDate", new { /*timeoutDate =*/ timeoutDate });
|
||||
ReloadCache();
|
||||
ClearCache();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,8 +30,13 @@ namespace Umbraco.Core.Services
|
||||
/// <summary>
|
||||
/// Return all active servers.
|
||||
/// </summary>
|
||||
/// <param name="refresh">A value indicating whether to force-refresh the cache.</param>
|
||||
/// <returns>All active servers.</returns>
|
||||
IEnumerable<IServerRegistration> GetActiveServers();
|
||||
/// <remarks>By default this method will rely on the repository's cache, which is updated each
|
||||
/// time the current server is touched, and the period depends on the configuration. Use the
|
||||
/// <paramref name="refresh"/> parameter to force a cache refresh and reload active servers
|
||||
/// from the database.</remarks>
|
||||
IEnumerable<IServerRegistration> GetActiveServers(bool refresh = false);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current server identity.
|
||||
|
||||
@@ -5,7 +5,6 @@ using System.Web;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.Repositories;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
using Umbraco.Core.Sync;
|
||||
@@ -45,7 +44,7 @@ namespace Umbraco.Core.Services
|
||||
uow.WriteLock(Constants.Locks.Servers);
|
||||
var repo = uow.CreateRepository<IServerRegistrationRepository>();
|
||||
|
||||
((ServerRegistrationRepository) repo).ReloadCache(); // ensure we have up-to-date cache
|
||||
((ServerRegistrationRepository) repo).ClearCache(); // ensure we have up-to-date cache
|
||||
|
||||
var regs = repo.GetAll().ToArray();
|
||||
var hasMaster = regs.Any(x => ((ServerRegistration)x).IsMaster);
|
||||
@@ -88,17 +87,6 @@ namespace Umbraco.Core.Services
|
||||
/// <param name="serverIdentity">The server unique identity.</param>
|
||||
public void DeactiveServer(string serverIdentity)
|
||||
{
|
||||
//_lrepo.WithWriteLocked(xr =>
|
||||
//{
|
||||
// var query = Query<IServerRegistration>.Builder.Where(x => x.ServerIdentity.ToUpper() == serverIdentity.ToUpper());
|
||||
// var server = xr.Repository.GetByQuery(query).FirstOrDefault();
|
||||
// if (server == null) return;
|
||||
|
||||
// server.IsActive = false;
|
||||
// server.IsMaster = false;
|
||||
// xr.Repository.AddOrUpdate(server);
|
||||
//});
|
||||
|
||||
// because the repository caches "all" and has queries disabled...
|
||||
|
||||
using (var uow = UowProvider.CreateUnitOfWork())
|
||||
@@ -106,7 +94,7 @@ namespace Umbraco.Core.Services
|
||||
uow.WriteLock(Constants.Locks.Servers);
|
||||
var repo = uow.CreateRepository<IServerRegistrationRepository>();
|
||||
|
||||
((ServerRegistrationRepository) repo).ReloadCache(); // ensure we have up-to-date cache
|
||||
((ServerRegistrationRepository) repo).ClearCache(); // ensure we have up-to-date cache
|
||||
|
||||
var server = repo.GetAll().FirstOrDefault(x => x.ServerIdentity.InvariantEquals(serverIdentity));
|
||||
if (server == null) return;
|
||||
@@ -135,38 +123,19 @@ namespace Umbraco.Core.Services
|
||||
/// <summary>
|
||||
/// Return all active servers.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<IServerRegistration> GetActiveServers()
|
||||
/// <param name="refresh">A value indicating whether to force-refresh the cache.</param>
|
||||
/// <returns>All active servers.</returns>
|
||||
/// <remarks>By default this method will rely on the repository's cache, which is updated each
|
||||
/// time the current server is touched, and the period depends on the configuration. Use the
|
||||
/// <paramref name="refresh"/> parameter to force a cache refresh and reload active servers
|
||||
/// from the database.</remarks>
|
||||
public IEnumerable<IServerRegistration> GetActiveServers(bool refresh = false)
|
||||
{
|
||||
// fixme - this needs to be refactored entirely now that we have repeatable read everywhere
|
||||
|
||||
//return _lrepo.WithReadLocked(xr =>
|
||||
//{
|
||||
// var query = Query<IServerRegistration>.Builder.Where(x => x.IsActive);
|
||||
// return xr.Repository.GetByQuery(query).ToArray();
|
||||
//});
|
||||
|
||||
// because the repository caches "all" we should use the following code
|
||||
// in order to ensure we use the cache and not hit the database each time
|
||||
|
||||
//return _lrepo.WithReadLocked(xr => xr.Repository.GetAll().Where(x => x.IsActive).ToArray());
|
||||
|
||||
// however, WithReadLocked (as any other LockingRepository methods) will attempt
|
||||
// to properly lock the repository using a database-level lock, which wants
|
||||
// the transaction isolation level to be RepeatableRead, which it is not by default,
|
||||
// and then, see U4-7046.
|
||||
//
|
||||
// in addition, LockingRepository methods need to hit the database in order to
|
||||
// ensure proper locking, and so if we know that the repository might not need the
|
||||
// database, we cannot use these methods - and then what?
|
||||
//
|
||||
// this raises a good number of questions, including whether caching anything in
|
||||
// repositories works at all in a LB environment - TODO: figure it out
|
||||
|
||||
using (var uow = UowProvider.CreateUnitOfWork())
|
||||
{
|
||||
uow.ReadLock(Constants.Locks.Servers);
|
||||
var repo = uow.CreateRepository<IServerRegistrationRepository>();
|
||||
if (refresh) ((ServerRegistrationRepository) repo).ClearCache();
|
||||
var servers = repo.GetAll().Where(x => x.IsActive).ToArray(); // fast, cached
|
||||
uow.Complete();
|
||||
return servers;
|
||||
|
||||
Reference in New Issue
Block a user