U4-8397 - Cleanup server registration db & cache

This commit is contained in:
Stephan
2016-06-08 13:38:40 +02:00
parent f1fd918120
commit 6e8fc27c13
3 changed files with 28 additions and 76 deletions

View File

@@ -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();
}
}
}

View File

@@ -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.

View File

@@ -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;