U4-8400 - kill repository cache policy factories

This commit is contained in:
Stephan
2016-06-01 14:31:33 +02:00
parent 743a1451f5
commit bc375e5fc2
24 changed files with 429 additions and 484 deletions

View File

@@ -21,120 +21,129 @@ namespace Umbraco.Core.Cache
where TEntity : class, IAggregateRoot
{
private readonly Func<TEntity, TId> _entityGetId;
private readonly Func<IEnumerable<TEntity>> _repoGetAll;
private readonly bool _expires;
public FullDataSetRepositoryCachePolicy(IRuntimeCacheProvider cache, Func<TEntity, TId> entityGetId, Func<IEnumerable<TEntity>> repoGetAll, bool expires)
public FullDataSetRepositoryCachePolicy(IRuntimeCacheProvider cache,
Func<TEntity, TId> entityGetId,
bool expires)
: base(cache)
{
_entityGetId = entityGetId;
_repoGetAll = repoGetAll;
_expires = expires;
}
protected static readonly TId[] EmptyIds = new TId[0];
protected string GetEntityTypeCacheKey()
{
return $"uRepo_{typeof (TEntity).Name}_";
}
private void SetCacheActionToClearAll()
protected void InsertEntities(TEntity[] entities)
{
SetCacheAction(() =>
{
// clear all, force reload
Cache.ClearCacheItem(GetEntityTypeCacheKey());
});
}
// cache is expected to be a deep-cloning cache ie it deep-clones whatever is
// IDeepCloneable when it goes in, and out. it also resets dirty properties,
// making sure that no 'dirty' entity is cached.
//
// this policy is caching the entire list of entities. to ensure that entities
// are properly deep-clones when cached, it uses a DeepCloneableList. however,
// we don't want to deep-clone *each* entity in the list when fetching it from
// cache as that would not be efficient for Get(id). so the DeepCloneableList is
// set to ListCloneBehavior.CloneOnce ie it will clone *once* when inserting,
// and then will *not* clone when retrieving.
protected void SetCacheActionToInsertEntities(TEntity[] entities)
{
SetCacheAction(() =>
if (_expires)
{
// cache is expected to be a deep-cloning cache ie it deep-clones whatever is
// IDeepCloneable when it goes in, and out. it also resets dirty properties,
// making sure that no 'dirty' entity is cached.
//
// this policy is caching the entire list of entities. to ensure that entities
// are properly deep-clones when cached, it uses a DeepCloneableList. however,
// we don't want to deep-clone *each* entity in the list when fetching it from
// cache as that would not be efficient for Get(id). so the DeepCloneableList is
// set to ListCloneBehavior.CloneOnce ie it will clone *once* when inserting,
// and then will *not* clone when retrieving.
if (_expires)
{
Cache.InsertCacheItem(GetEntityTypeCacheKey(), () => new DeepCloneableList<TEntity>(entities), TimeSpan.FromMinutes(5), true);
}
else
{
Cache.InsertCacheItem(GetEntityTypeCacheKey(), () => new DeepCloneableList<TEntity>(entities));
}
});
Cache.InsertCacheItem(GetEntityTypeCacheKey(), () => new DeepCloneableList<TEntity>(entities), TimeSpan.FromMinutes(5), true);
}
else
{
Cache.InsertCacheItem(GetEntityTypeCacheKey(), () => new DeepCloneableList<TEntity>(entities));
}
}
/// <inheritdoc />
public override void CreateOrUpdate(TEntity entity, Action<TEntity> repoCreateOrUpdate)
public override void Create(TEntity entity, Action<TEntity> persistNew)
{
if (entity == null) throw new ArgumentNullException(nameof(entity));
if (repoCreateOrUpdate == null) throw new ArgumentNullException(nameof(repoCreateOrUpdate));
try
{
repoCreateOrUpdate(entity);
persistNew(entity);
}
finally
{
SetCacheActionToClearAll();
ClearAll();
}
}
/// <inheritdoc />
public override void Remove(TEntity entity, Action<TEntity> repoRemove)
public override void Update(TEntity entity, Action<TEntity> persistUpdated)
{
if (entity == null) throw new ArgumentNullException(nameof(entity));
if (repoRemove == null) throw new ArgumentNullException(nameof(repoRemove));
try
{
repoRemove(entity);
persistUpdated(entity);
}
finally
{
SetCacheActionToClearAll();
ClearAll();
}
}
/// <inheritdoc />
public override TEntity Get(TId id, Func<TId, TEntity> repoGet)
public override void Delete(TEntity entity, Action<TEntity> persistDeleted)
{
return Get(id);
if (entity == null) throw new ArgumentNullException(nameof(entity));
try
{
persistDeleted(entity);
}
finally
{
ClearAll();
}
}
/// <inheritdoc />
public override TEntity Get(TId id)
public override TEntity Get(TId id, Func<TId, TEntity> performGet, Func<TId[], IEnumerable<TEntity>> performGetAll)
{
// get all from the cache, the look for the entity
var all = GetAllCached();
// get all from the cache, then look for the entity
var all = GetAllCached(performGetAll);
var entity = all.FirstOrDefault(x => _entityGetId(x).Equals(id));
// see note in SetCacheActionToInsertEntities - what we get here is the original
// see note in InsertEntities - what we get here is the original
// cached entity, not a clone, so we need to manually ensure it is deep-cloned.
return (TEntity)entity?.DeepClone();
}
/// <inheritdoc />
public override TEntity GetCached(TId id)
{
// get all from the cache -- and only the cache, then look for the entity
var all = Cache.GetCacheItem<DeepCloneableList<TEntity>>(GetEntityTypeCacheKey());
var entity = all?.FirstOrDefault(x => _entityGetId(x).Equals(id));
// see note in InsertEntities - what we get here is the original
// cached entity, not a clone, so we need to manually ensure it is deep-cloned.
return (TEntity) entity?.DeepClone();
}
/// <inheritdoc />
public override bool Exists(TId id, Func<TId, bool> repoExists)
public override bool Exists(TId id, Func<TId, bool> performExits, Func<TId[], IEnumerable<TEntity>> performGetAll)
{
// get all as one set, then look for the entity
var all = GetAllCached();
var all = GetAllCached(performGetAll);
return all.Any(x => _entityGetId(x).Equals(id));
}
/// <inheritdoc />
public override TEntity[] GetAll(TId[] ids, Func<TId[], IEnumerable<TEntity>> repoGet)
public override TEntity[] GetAll(TId[] ids, Func<TId[], IEnumerable<TEntity>> performGetAll)
{
// get all as one set, from cache if possible, else repo
var all = GetAllCached();
var all = GetAllCached(performGetAll);
// if ids have been specified, filter
if (ids.Length > 0) all = all.Where(x => ids.Contains(_entityGetId(x)));
@@ -146,16 +155,22 @@ namespace Umbraco.Core.Cache
}
// does NOT clone anything, so be nice with the returned values
private IEnumerable<TEntity> GetAllCached()
private IEnumerable<TEntity> GetAllCached(Func<TId[], IEnumerable<TEntity>> performGetAll)
{
// try the cache first
var all = Cache.GetCacheItem<DeepCloneableList<TEntity>>(GetEntityTypeCacheKey());
if (all != null) return all.ToArray();
// else get from repo and cache
var entities = _repoGetAll().WhereNotNull().ToArray();
SetCacheActionToInsertEntities(entities); // may be an empty array...
var entities = performGetAll(EmptyIds).WhereNotNull().ToArray();
InsertEntities(entities); // may be an empty array...
return entities;
}
/// <inheritdoc />
public override void ClearAll()
{
Cache.ClearCacheItem(GetEntityTypeCacheKey());
}
}
}