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
@@ -40,158 +40,155 @@ namespace Umbraco.Core.Cache
return $"uRepo_{typeof (TEntity).Name}_";
}
/// <summary>
/// Sets the action to execute on disposal for a single entity
/// </summary>
/// <param name="cacheKey"></param>
/// <param name="entity"></param>
protected virtual void SetCacheActionToInsertEntity(string cacheKey, TEntity entity)
protected virtual void InsertEntity(string cacheKey, TEntity entity)
{
SetCacheAction(() =>
{
Cache.InsertCacheItem(cacheKey, () => entity, TimeSpan.FromMinutes(5), true);
});
Cache.InsertCacheItem(cacheKey, () => entity, TimeSpan.FromMinutes(5), true);
}
/// <summary>
/// Sets the action to execute on disposal for an entity collection
/// </summary>
/// <param name="ids"></param>
/// <param name="entities"></param>
protected virtual void SetCacheActionToInsertEntities(TId[] ids, TEntity[] entities)
protected virtual void InsertEntities(TId[] ids, TEntity[] entities)
{
SetCacheAction(() =>
if (ids.Length == 0 && entities.Length == 0 && _options.GetAllCacheAllowZeroCount)
{
if (ids.Length == 0 && entities.Length == 0 && _options.GetAllCacheAllowZeroCount)
// getting all of them, and finding nothing.
// if we can cache a zero count, cache an empty array,
// for as long as the cache is not cleared (no expiration)
Cache.InsertCacheItem(GetEntityTypeCacheKey(), () => EmptyEntities);
}
else
{
// individually cache each item
foreach (var entity in entities)
{
// getting all of them, and finding nothing.
// if we can cache a zero count, cache an empty array,
// for as long as the cache is not cleared (no expiration)
Cache.InsertCacheItem(GetEntityTypeCacheKey(), () => EmptyEntities);
var capture = entity;
Cache.InsertCacheItem(GetEntityCacheKey(entity.Id), () => capture, TimeSpan.FromMinutes(5), true);
}
else
{
// individually cache each item
foreach (var entity in entities)
{
var capture = entity;
Cache.InsertCacheItem(GetEntityCacheKey(entity.Id), () => capture, TimeSpan.FromMinutes(5), true);
}
}
});
}
}
/// <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);
SetCacheAction(() =>
// just to be safe, we cannot cache an item without an identity
if (entity.HasIdentity)
{
// just to be safe, we cannot cache an item without an identity
if (entity.HasIdentity)
{
Cache.InsertCacheItem(GetEntityCacheKey(entity.Id), () => entity, TimeSpan.FromMinutes(5), true);
}
// if there's a GetAllCacheAllowZeroCount cache, ensure it is cleared
Cache.ClearCacheItem(GetEntityTypeCacheKey());
});
Cache.InsertCacheItem(GetEntityCacheKey(entity.Id), () => entity, TimeSpan.FromMinutes(5), true);
}
// if there's a GetAllCacheAllowZeroCount cache, ensure it is cleared
Cache.ClearCacheItem(GetEntityTypeCacheKey());
}
catch
{
SetCacheAction(() =>
{
// if an exception is thrown we need to remove the entry from cache,
// this is ONLY a work around because of the way
// that we cache entities: http://issues.umbraco.org/issue/U4-4259
Cache.ClearCacheItem(GetEntityCacheKey(entity.Id));
// if an exception is thrown we need to remove the entry from cache,
// this is ONLY a work around because of the way
// that we cache entities: http://issues.umbraco.org/issue/U4-4259
Cache.ClearCacheItem(GetEntityCacheKey(entity.Id));
// if there's a GetAllCacheAllowZeroCount cache, ensure it is cleared
Cache.ClearCacheItem(GetEntityTypeCacheKey());
});
// if there's a GetAllCacheAllowZeroCount cache, ensure it is cleared
Cache.ClearCacheItem(GetEntityTypeCacheKey());
throw;
}
}
/// <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);
// just to be safe, we cannot cache an item without an identity
if (entity.HasIdentity)
{
Cache.InsertCacheItem(GetEntityCacheKey(entity.Id), () => entity, TimeSpan.FromMinutes(5), true);
}
// if there's a GetAllCacheAllowZeroCount cache, ensure it is cleared
Cache.ClearCacheItem(GetEntityTypeCacheKey());
}
catch
{
// if an exception is thrown we need to remove the entry from cache,
// this is ONLY a work around because of the way
// that we cache entities: http://issues.umbraco.org/issue/U4-4259
Cache.ClearCacheItem(GetEntityCacheKey(entity.Id));
// if there's a GetAllCacheAllowZeroCount cache, ensure it is cleared
Cache.ClearCacheItem(GetEntityTypeCacheKey());
throw;
}
}
/// <inheritdoc />
public override void Delete(TEntity entity, Action<TEntity> persistDeleted)
{
if (entity == null) throw new ArgumentNullException(nameof(entity));
try
{
persistDeleted(entity);
}
finally
{
// whatever happens, clear the cache
var cacheKey = GetEntityCacheKey(entity.Id);
SetCacheAction(() =>
{
Cache.ClearCacheItem(cacheKey);
// if there's a GetAllCacheAllowZeroCount cache, ensure it is cleared
Cache.ClearCacheItem(GetEntityTypeCacheKey());
});
Cache.ClearCacheItem(cacheKey);
// if there's a GetAllCacheAllowZeroCount cache, ensure it is cleared
Cache.ClearCacheItem(GetEntityTypeCacheKey());
}
}
/// <inheritdoc />
public override TEntity Get(TId id, Func<TId, TEntity> repoGet)
public override TEntity Get(TId id, Func<TId, TEntity> performGet, Func<TId[], IEnumerable<TEntity>> performGetAll)
{
if (repoGet == null) throw new ArgumentNullException(nameof(repoGet));
var cacheKey = GetEntityCacheKey(id);
var fromCache = Cache.GetCacheItem<TEntity>(cacheKey);
// if found in cache then return else fetch and cache
if (fromCache != null)
return fromCache;
var entity = repoGet(id);
var entity = performGet(id);
if (entity != null && entity.HasIdentity)
SetCacheActionToInsertEntity(cacheKey, entity);
InsertEntity(cacheKey, entity);
return entity;
}
/// <inheritdoc />
public override TEntity Get(TId id)
public override TEntity GetCached(TId id)
{
var cacheKey = GetEntityCacheKey(id);
return Cache.GetCacheItem<TEntity>(cacheKey);
}
/// <inheritdoc />
public override bool Exists(TId id, Func<TId, bool> repoExists)
public override bool Exists(TId id, Func<TId, bool> performExists, Func<TId[], IEnumerable<TEntity>> performGetAll)
{
if (repoExists == null) throw new ArgumentNullException(nameof(repoExists));
// if found in cache the return else check
var cacheKey = GetEntityCacheKey(id);
var fromCache = Cache.GetCacheItem<TEntity>(cacheKey);
return fromCache != null || repoExists(id);
return fromCache != null || performExists(id);
}
/// <inheritdoc />
public override TEntity[] GetAll(TId[] ids, Func<TId[], IEnumerable<TEntity>> repoGet)
public override TEntity[] GetAll(TId[] ids, Func<TId[], IEnumerable<TEntity>> performGetAll)
{
if (repoGet == null) throw new ArgumentNullException(nameof(repoGet));
if (ids.Length > 0)
{
// try to get each entity from the cache
// if we can find all of them, return
var entities = ids.Select(Get).ToArray();
var entities = ids.Select(GetCached).WhereNotNull().ToArray();
if (ids.Length.Equals(entities.Length))
return entities; // no need for null checks, we are not caching nulls
}
@@ -227,15 +224,21 @@ namespace Umbraco.Core.Cache
}
// cache failed, get from repo and cache
var repoEntities = repoGet(ids)
var repoEntities = performGetAll(ids)
.WhereNotNull() // exclude nulls!
.Where(x => x.HasIdentity) // be safe, though would be weird...
.ToArray();
// note: if empty & allow zero count, will cache a special (empty) entry
SetCacheActionToInsertEntities(ids, repoEntities);
InsertEntities(ids, repoEntities);
return repoEntities;
}
/// <inheritdoc />
public override void ClearAll()
{
Cache.ClearCacheByKeySearch(GetEntityTypeCacheKey());
}
}
}
@@ -1,27 +0,0 @@
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Cache
{
/// <summary>
/// Creates cache policies
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TId"></typeparam>
internal class DefaultRepositoryCachePolicyFactory<TEntity, TId> : IRepositoryCachePolicyFactory<TEntity, TId>
where TEntity : class, IAggregateRoot
{
private readonly IRuntimeCacheProvider _runtimeCache;
private readonly RepositoryCachePolicyOptions _options;
public DefaultRepositoryCachePolicyFactory(IRuntimeCacheProvider runtimeCache, RepositoryCachePolicyOptions options)
{
_runtimeCache = runtimeCache;
_options = options;
}
public virtual IRepositoryCachePolicy<TEntity, TId> CreatePolicy()
{
return new DefaultRepositoryCachePolicy<TEntity, TId>(_runtimeCache, _options);
}
}
}
@@ -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());
}
}
}
@@ -1,33 +0,0 @@
using System;
using System.Collections.Generic;
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Cache
{
/// <summary>
/// Creates cache policies
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TId"></typeparam>
internal class FullDataSetRepositoryCachePolicyFactory<TEntity, TId> : IRepositoryCachePolicyFactory<TEntity, TId>
where TEntity : class, IAggregateRoot
{
private readonly IRuntimeCacheProvider _runtimeCache;
private readonly Func<TEntity, TId> _getEntityId;
private readonly Func<IEnumerable<TEntity>> _getAllFromRepo;
private readonly bool _expires;
public FullDataSetRepositoryCachePolicyFactory(IRuntimeCacheProvider runtimeCache, Func<TEntity, TId> getEntityId, Func<IEnumerable<TEntity>> getAllFromRepo, bool expires)
{
_runtimeCache = runtimeCache;
_getEntityId = getEntityId;
_getAllFromRepo = getAllFromRepo;
_expires = expires;
}
public virtual IRepositoryCachePolicy<TEntity, TId> CreatePolicy()
{
return new FullDataSetRepositoryCachePolicy<TEntity, TId>(_runtimeCache, _getEntityId, _getAllFromRepo, _expires);
}
}
}
@@ -4,17 +4,28 @@ using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Cache
{
internal interface IRepositoryCachePolicy<TEntity, TId> : IDisposable
internal interface IRepositoryCachePolicy<TEntity, TId>
where TEntity : class, IAggregateRoot
{
// note:
// at the moment each repository instance creates its corresponding cache policy instance
// we could reduce allocations by using static cache policy instances but then we would need
// to modify all methods here to pass the repository and cache eg:
//
// TEntity Get(TRepository repository, IRuntimeCacheProvider cache, TId id);
//
// it is not *that* complicated but then RepositoryBase needs to have a TRepository generic
// type parameter and it all becomes convoluted - keeping it simple for the time being.
/// <summary>
/// Gets an entity from the cache, else from the repository.
/// </summary>
/// <param name="id">The identifier.</param>
/// <param name="repoGet">The repository method to get the entity.</param>
/// <param name="performGet">The repository PerformGet method.</param>
/// <param name="performGetAll">The repository PerformGetAll method.</param>
/// <returns>The entity with the specified identifier, if it exits, else null.</returns>
/// <remarks>First considers the cache then the repository.</remarks>
TEntity Get(TId id, Func<TId, TEntity> repoGet);
TEntity Get(TId id, Func<TId, TEntity> performGet, Func<TId[], IEnumerable<TEntity>> performGetAll);
/// <summary>
/// Gets an entity from the cache.
@@ -22,40 +33,54 @@ namespace Umbraco.Core.Cache
/// <param name="id">The identifier.</param>
/// <returns>The entity with the specified identifier, if it is in the cache already, else null.</returns>
/// <remarks>Does not consider the repository at all.</remarks>
TEntity Get(TId id);
TEntity GetCached(TId id);
/// <summary>
/// Gets a value indicating whether an entity with a specified identifier exists.
/// </summary>
/// <param name="id">The identifier.</param>
/// <param name="repoExists">The repository method to check for the existence of the entity.</param>
/// <param name="performExists">The repository PerformExists method.</param>
/// <param name="performGetAll">The repository PerformGetAll method.</param>
/// <returns>A value indicating whether an entity with the specified identifier exists.</returns>
/// <remarks>First considers the cache then the repository.</remarks>
bool Exists(TId id, Func<TId, bool> repoExists);
bool Exists(TId id, Func<TId, bool> performExists, Func<TId[], IEnumerable<TEntity>> performGetAll);
/// <summary>
/// Creates or updates an entity.
/// Creates an entity.
/// </summary>
/// <param name="entity">The entity.</param>
/// <param name="repoCreateOrUpdate">The repository method to create or update the entity.</param>
/// <remarks>Creates or updates the entity in the repository, and updates the cache accordingly.</remarks>
void CreateOrUpdate(TEntity entity, Action<TEntity> repoCreateOrUpdate);
/// <param name="persistNew">The repository PersistNewItem method.</param>
/// <remarks>Creates the entity in the repository, and updates the cache accordingly.</remarks>
void Create(TEntity entity, Action<TEntity> persistNew);
/// <summary>
/// Updates an entity.
/// </summary>
/// <param name="entity">The entity.</param>
/// <param name="persistUpdated">The reopsitory PersistUpdatedItem method.</param>
/// <remarks>Updates the entity in the repository, and updates the cache accordingly.</remarks>
void Update(TEntity entity, Action<TEntity> persistUpdated);
/// <summary>
/// Removes an entity.
/// </summary>
/// <param name="entity">The entity.</param>
/// <param name="repoRemove">The repository method to remove the entity.</param>
/// <param name="persistDeleted">The repository PersistDeletedItem method.</param>
/// <remarks>Removes the entity from the repository and clears the cache.</remarks>
void Remove(TEntity entity, Action<TEntity> repoRemove);
void Delete(TEntity entity, Action<TEntity> persistDeleted);
/// <summary>
/// Gets entities.
/// </summary>
/// <param name="ids">The identifiers.</param>
/// <param name="repoGet">The repository method to get entities.</param>
/// <param name="performGetAll">The repository PerformGetAll method.</param>
/// <returns>If <paramref name="ids"/> is empty, all entities, else the entities with the specified identifiers.</returns>
/// <remarks>fixme explain what it should do!</remarks>
TEntity[] GetAll(TId[] ids, Func<TId[], IEnumerable<TEntity>> repoGet);
/// <remarks>Get all the entities. Either from the cache or the repository depending on the implementation.</remarks>
TEntity[] GetAll(TId[] ids, Func<TId[], IEnumerable<TEntity>> performGetAll);
/// <summary>
/// Clears the entire cache.
/// </summary>
void ClearAll();
}
}
@@ -1,9 +0,0 @@
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Cache
{
internal interface IRepositoryCachePolicyFactory<TEntity, TId> where TEntity : class, IAggregateRoot
{
IRepositoryCachePolicy<TEntity, TId> CreatePolicy();
}
}
@@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Cache
{
class NoCacheRepositoryCachePolicy<TEntity, TId> : IRepositoryCachePolicy<TEntity, TId>
where TEntity : class, IAggregateRoot
{
public void ClearAll()
{
// nothing to clear - not caching
}
public void Create(TEntity entity, Action<TEntity> persistNew)
{
persistNew(entity);
}
public void Delete(TEntity entity, Action<TEntity> persistDeleted)
{
persistDeleted(entity);
}
public bool Exists(TId id, Func<TId, bool> performExists, Func<TId[], IEnumerable<TEntity>> performGetAll)
{
return performExists(id);
}
public TEntity Get(TId id, Func<TId, TEntity> performGet, Func<TId[], IEnumerable<TEntity>> performGetAll)
{
return performGet(id);
}
public TEntity[] GetAll(TId[] ids, Func<TId[], IEnumerable<TEntity>> performGetAll)
{
return performGetAll(ids).ToArray();
}
public TEntity GetCached(TId id)
{
return null;
}
public void Update(TEntity entity, Action<TEntity> persistUpdated)
{
persistUpdated(entity);
}
}
}
@@ -1,27 +0,0 @@
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Cache
{
/// <summary>
/// Creates cache policies
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TId"></typeparam>
internal class OnlySingleItemsRepositoryCachePolicyFactory<TEntity, TId> : IRepositoryCachePolicyFactory<TEntity, TId>
where TEntity : class, IAggregateRoot
{
private readonly IRuntimeCacheProvider _runtimeCache;
private readonly RepositoryCachePolicyOptions _options;
public OnlySingleItemsRepositoryCachePolicyFactory(IRuntimeCacheProvider runtimeCache, RepositoryCachePolicyOptions options)
{
_runtimeCache = runtimeCache;
_options = options;
}
public virtual IRepositoryCachePolicy<TEntity, TId> CreatePolicy()
{
return new SingleItemsOnlyRepositoryCachePolicy<TEntity, TId>(_runtimeCache, _options);
}
}
}
@@ -9,52 +9,39 @@ namespace Umbraco.Core.Cache
/// </summary>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
/// <typeparam name="TId">The type of the identifier.</typeparam>
internal abstract class RepositoryCachePolicyBase<TEntity, TId> : DisposableObject, IRepositoryCachePolicy<TEntity, TId>
internal abstract class RepositoryCachePolicyBase<TEntity, TId> : IRepositoryCachePolicy<TEntity, TId>
where TEntity : class, IAggregateRoot
{
private Action _action;
protected RepositoryCachePolicyBase(IRuntimeCacheProvider cache)
{
if (cache == null) throw new ArgumentNullException(nameof(cache));
Cache = cache;
}
}
protected IRuntimeCacheProvider Cache { get; }
/// <summary>
/// Disposing performs the actual caching action.
/// </summary>
protected override void DisposeResources()
{
_action?.Invoke();
}
/// <summary>
/// Sets the action to execute when being disposed.
/// </summary>
/// <param name="action">An action to perform when being disposed.</param>
protected void SetCacheAction(Action action)
{
_action = action;
}
/// <inheritdoc />
public abstract TEntity Get(TId id, Func<TId, TEntity> performGet, Func<TId[], IEnumerable<TEntity>> performGetAll);
/// <inheritdoc />
public abstract TEntity Get(TId id, Func<TId, TEntity> repoGet);
public abstract TEntity GetCached(TId id);
/// <inheritdoc />
public abstract TEntity Get(TId id);
public abstract bool Exists(TId id, Func<TId, bool> performExists, Func<TId[], IEnumerable<TEntity>> performGetAll);
/// <inheritdoc />
public abstract bool Exists(TId id, Func<TId, bool> repoExists);
public abstract void Create(TEntity entity, Action<TEntity> persistNew);
/// <inheritdoc />
public abstract void CreateOrUpdate(TEntity entity, Action<TEntity> repoCreateOrUpdate);
public abstract void Update(TEntity entity, Action<TEntity> persistUpdated);
/// <inheritdoc />
public abstract void Remove(TEntity entity, Action<TEntity> repoRemove);
public abstract void Delete(TEntity entity, Action<TEntity> persistDeleted);
/// <inheritdoc />
public abstract TEntity[] GetAll(TId[] ids, Func<TId[], IEnumerable<TEntity>> repoGet);
public abstract TEntity[] GetAll(TId[] ids, Func<TId[], IEnumerable<TEntity>> performGetAll);
/// <inheritdoc />
public abstract void ClearAll();
}
}
@@ -1,3 +1,5 @@
using System;
using System.Collections.Generic;
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Cache
@@ -19,7 +21,7 @@ namespace Umbraco.Core.Cache
: base(cache, options)
{ }
protected override void SetCacheActionToInsertEntities(TId[] ids, TEntity[] entities)
protected override void InsertEntities(TId[] ids, TEntity[] entities)
{
// nop
}
@@ -20,6 +20,7 @@ namespace Umbraco.Core.Persistence.Repositories
internal class ContentTypeRepository : ContentTypeRepositoryBase<IContentType>, IContentTypeRepository
{
private readonly ITemplateRepository _templateRepository;
private IRepositoryCachePolicy<IContentType, int> _cachePolicy;
public ContentTypeRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ITemplateRepository templateRepository, IMappingResolver mappingResolver)
: base(work, cache, logger, mappingResolver)
@@ -27,16 +28,15 @@ namespace Umbraco.Core.Persistence.Repositories
_templateRepository = templateRepository;
}
private FullDataSetRepositoryCachePolicyFactory<IContentType, int> _cachePolicyFactory;
protected override IRepositoryCachePolicyFactory<IContentType, int> CachePolicyFactory
protected override IRepositoryCachePolicy<IContentType, int> CachePolicy
{
get
{
//Use a FullDataSet cache policy - this will cache the entire GetAll result in a single collection
return _cachePolicyFactory ?? (_cachePolicyFactory = new FullDataSetRepositoryCachePolicyFactory<IContentType, int>(
RuntimeCache, GetEntityId, () => PerformGetAll(),
//allow this cache to expire
expires:true));
if (_cachePolicy != null) return _cachePolicy;
_cachePolicy = new FullDataSetRepositoryCachePolicy<IContentType, int>(RuntimeCache, GetEntityId, /*expires:*/ true);
return _cachePolicy;
}
}
@@ -20,6 +20,7 @@ namespace Umbraco.Core.Persistence.Repositories
/// </summary>
internal class DictionaryRepository : NPocoRepositoryBase<int, IDictionaryItem>, IDictionaryRepository
{
private IRepositoryCachePolicy<IDictionaryItem, int> _cachePolicy;
private readonly IMappingResolver _mappingResolver;
public DictionaryRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, IMappingResolver mappingResolver)
@@ -28,16 +29,23 @@ namespace Umbraco.Core.Persistence.Repositories
_mappingResolver = mappingResolver;
}
private IRepositoryCachePolicyFactory<IDictionaryItem, int> _cachePolicyFactory;
protected override IRepositoryCachePolicyFactory<IDictionaryItem, int> CachePolicyFactory => _cachePolicyFactory ??
// custom cache policy which will not cache any results for GetAll
(_cachePolicyFactory = new OnlySingleItemsRepositoryCachePolicyFactory<IDictionaryItem, int>(
RuntimeCache,
new RepositoryCachePolicyOptions
protected override IRepositoryCachePolicy<IDictionaryItem, int> CachePolicy
{
get
{
if (_cachePolicy != null) return _cachePolicy;
var options = new RepositoryCachePolicyOptions
{
//allow zero to be cached
GetAllCacheAllowZeroCount = true
}));
};
_cachePolicy = new SingleItemsOnlyRepositoryCachePolicy<IDictionaryItem, int>(RuntimeCache, options);
return _cachePolicy;
}
}
#region Overrides of RepositoryBase<int,DictionaryItem>
@@ -286,6 +294,7 @@ namespace Umbraco.Core.Persistence.Repositories
private class DictionaryByUniqueIdRepository : SimpleGetRepository<Guid, IDictionaryItem, DictionaryDto>
{
private IRepositoryCachePolicy<IDictionaryItem, Guid> _cachePolicy;
private readonly DictionaryRepository _dictionaryRepository;
public DictionaryByUniqueIdRepository(DictionaryRepository dictionaryRepository, IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, IMappingResolver mappingResolver)
@@ -325,20 +334,28 @@ namespace Umbraco.Core.Persistence.Repositories
return "cmsDictionary." + SqlSyntax.GetQuotedColumnName("id") + " in (@ids)";
}
private IRepositoryCachePolicyFactory<IDictionaryItem, Guid> _cachePolicyFactory;
protected override IRepositoryCachePolicyFactory<IDictionaryItem, Guid> CachePolicyFactory => _cachePolicyFactory ??
// custom cache policy which will not cache any results for GetAll
(_cachePolicyFactory = new OnlySingleItemsRepositoryCachePolicyFactory<IDictionaryItem, Guid>(
RuntimeCache,
new RepositoryCachePolicyOptions
protected override IRepositoryCachePolicy<IDictionaryItem, Guid> CachePolicy
{
get
{
if (_cachePolicy != null) return _cachePolicy;
var options = new RepositoryCachePolicyOptions
{
//allow zero to be cached
GetAllCacheAllowZeroCount = true
}));
};
_cachePolicy = new SingleItemsOnlyRepositoryCachePolicy<IDictionaryItem, Guid>(RuntimeCache, options);
return _cachePolicy;
}
}
}
private class DictionaryByKeyRepository : SimpleGetRepository<string, IDictionaryItem, DictionaryDto>
{
private IRepositoryCachePolicy<IDictionaryItem, string> _cachePolicy;
private readonly DictionaryRepository _dictionaryRepository;
public DictionaryByKeyRepository(DictionaryRepository dictionaryRepository, IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, IMappingResolver mappingResolver)
@@ -378,16 +395,23 @@ namespace Umbraco.Core.Persistence.Repositories
return "cmsDictionary." + SqlSyntax.GetQuotedColumnName("key") + " in (@ids)";
}
private IRepositoryCachePolicyFactory<IDictionaryItem, string> _cachePolicyFactory;
protected override IRepositoryCachePolicyFactory<IDictionaryItem, string> CachePolicyFactory => _cachePolicyFactory ??
// custom cache policy which will not cache any results for GetAll
(_cachePolicyFactory = new OnlySingleItemsRepositoryCachePolicyFactory<IDictionaryItem, string>(
RuntimeCache,
new RepositoryCachePolicyOptions
protected override IRepositoryCachePolicy<IDictionaryItem, string> CachePolicy
{
get
{
if (_cachePolicy != null) return _cachePolicy;
var options = new RepositoryCachePolicyOptions
{
//allow zero to be cached
GetAllCacheAllowZeroCount = true
}));
};
_cachePolicy = new SingleItemsOnlyRepositoryCachePolicy<IDictionaryItem, string>(RuntimeCache, options);
return _cachePolicy;
}
}
}
}
}
@@ -20,19 +20,22 @@ namespace Umbraco.Core.Persistence.Repositories
internal class DomainRepository : NPocoRepositoryBase<int, IDomain>, IDomainRepository
{
private IRepositoryCachePolicy<IDomain, int> _cachePolicy;
public DomainRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, IMappingResolver mappingResolver)
: base(work, cache, logger, mappingResolver)
{
}
private FullDataSetRepositoryCachePolicyFactory<IDomain, int> _cachePolicyFactory;
protected override IRepositoryCachePolicyFactory<IDomain, int> CachePolicyFactory
protected override IRepositoryCachePolicy<IDomain, int> CachePolicy
{
get
{
//Use a FullDataSet cache policy - this will cache the entire GetAll result in a single collection
return _cachePolicyFactory ?? (_cachePolicyFactory = new FullDataSetRepositoryCachePolicyFactory<IDomain, int>(
RuntimeCache, GetEntityId, () => PerformGetAll(), false));
if (_cachePolicy != null) return _cachePolicy;
_cachePolicy = new FullDataSetRepositoryCachePolicy<IDomain, int>(RuntimeCache, GetEntityId, /*expires:*/ false);
return _cachePolicy;
}
}
@@ -21,19 +21,22 @@ namespace Umbraco.Core.Persistence.Repositories
/// </summary>
internal class LanguageRepository : NPocoRepositoryBase<int, ILanguage>, ILanguageRepository
{
private IRepositoryCachePolicy<ILanguage, int> _cachePolicy;
public LanguageRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, IMappingResolver mappingResolver)
: base(work, cache, logger, mappingResolver)
{
}
private FullDataSetRepositoryCachePolicyFactory<ILanguage, int> _cachePolicyFactory;
protected override IRepositoryCachePolicyFactory<ILanguage, int> CachePolicyFactory
protected override IRepositoryCachePolicy<ILanguage, int> CachePolicy
{
get
{
//Use a FullDataSet cache policy - this will cache the entire GetAll result in a single collection
return _cachePolicyFactory ?? (_cachePolicyFactory = new FullDataSetRepositoryCachePolicyFactory<ILanguage, int>(
RuntimeCache, GetEntityId, () => PerformGetAll(), false));
if (_cachePolicy != null) return _cachePolicy;
_cachePolicy = new FullDataSetRepositoryCachePolicy<ILanguage, int>(RuntimeCache, GetEntityId, /*expires:*/ false);
return _cachePolicy;
}
}
@@ -17,20 +17,21 @@ namespace Umbraco.Core.Persistence.Repositories
/// </summary>
internal class MediaTypeRepository : ContentTypeRepositoryBase<IMediaType>, IMediaTypeRepository
{
private IRepositoryCachePolicy<IMediaType, int> _cachePolicy;
public MediaTypeRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, IMappingResolver mappingResolver)
: base(work, cache, logger, mappingResolver)
{ }
private FullDataSetRepositoryCachePolicyFactory<IMediaType, int> _cachePolicyFactory;
protected override IRepositoryCachePolicyFactory<IMediaType, int> CachePolicyFactory
protected override IRepositoryCachePolicy<IMediaType, int> CachePolicy
{
get
{
//Use a FullDataSet cache policy - this will cache the entire GetAll result in a single collection
return _cachePolicyFactory ?? (_cachePolicyFactory = new FullDataSetRepositoryCachePolicyFactory<IMediaType, int>(
RuntimeCache, GetEntityId, () => PerformGetAll(),
//allow this cache to expire
expires: true));
if (_cachePolicy != null) return _cachePolicy;
_cachePolicy = new FullDataSetRepositoryCachePolicy<IMediaType, int>(RuntimeCache, GetEntityId, /*expires:*/ true);
return _cachePolicy;
}
}
@@ -19,20 +19,21 @@ namespace Umbraco.Core.Persistence.Repositories
/// </summary>
internal class MemberTypeRepository : ContentTypeRepositoryBase<IMemberType>, IMemberTypeRepository
{
private IRepositoryCachePolicy<IMemberType, int> _cachePolicy;
public MemberTypeRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, IMappingResolver mappingResolver)
: base(work, cache, logger, mappingResolver)
{ }
private FullDataSetRepositoryCachePolicyFactory<IMemberType, int> _cachePolicyFactory;
protected override IRepositoryCachePolicyFactory<IMemberType, int> CachePolicyFactory
protected override IRepositoryCachePolicy<IMemberType, int> CachePolicy
{
get
{
//Use a FullDataSet cache policy - this will cache the entire GetAll result in a single collection
return _cachePolicyFactory ?? (_cachePolicyFactory = new FullDataSetRepositoryCachePolicyFactory<IMemberType, int>(
RuntimeCache, GetEntityId, () => PerformGetAll(),
//allow this cache to expire
expires: true));
if (_cachePolicy != null) return _cachePolicy;
_cachePolicy = new FullDataSetRepositoryCachePolicy<IMemberType, int>(RuntimeCache, GetEntityId, /*expires:*/ true);
return _cachePolicy;
}
}
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Data.SqlServerCe;
using NPoco;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
@@ -107,7 +106,7 @@ namespace Umbraco.Core.Persistence.Repositories
protected virtual new TId GetEntityId(TEntity entity)
{
return (TId)(object)entity.Id;
return (TId)(object) entity.Id;
}
}
}
@@ -16,19 +16,22 @@ namespace Umbraco.Core.Persistence.Repositories
{
internal class PublicAccessRepository : NPocoRepositoryBase<Guid, PublicAccessEntry>, IPublicAccessRepository
{
private IRepositoryCachePolicy<PublicAccessEntry, Guid> _cachePolicy;
public PublicAccessRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, IMappingResolver mappingResolver)
: base(work, cache, logger, mappingResolver)
{
}
private FullDataSetRepositoryCachePolicyFactory<PublicAccessEntry, Guid> _cachePolicyFactory;
protected override IRepositoryCachePolicyFactory<PublicAccessEntry, Guid> CachePolicyFactory
protected override IRepositoryCachePolicy<PublicAccessEntry, Guid> CachePolicy
{
get
{
//Use a FullDataSet cache policy - this will cache the entire GetAll result in a single collection
return _cachePolicyFactory ?? (_cachePolicyFactory = new FullDataSetRepositoryCachePolicyFactory<PublicAccessEntry, Guid>(
RuntimeCache, GetEntityId, () => PerformGetAll(), false));
if (_cachePolicy != null) return _cachePolicy;
_cachePolicy = new FullDataSetRepositoryCachePolicy<PublicAccessEntry, Guid>(RuntimeCache, GetEntityId, /*expires:*/ false);
return _cachePolicy;
}
}
@@ -81,25 +81,24 @@ namespace Umbraco.Core.Persistence.Repositories
/// </summary>
protected override IRuntimeCacheProvider RuntimeCache => RepositoryCache.IsolatedRuntimeCache.GetOrCreateCache<TEntity>();
private IRepositoryCachePolicyFactory<TEntity, TId> _cachePolicyFactory;
/// <summary>
/// Returns the Cache Policy for the repository
/// </summary>
/// <remarks>
/// The Cache Policy determines how each entity or entity collection is cached
/// </remarks>
protected virtual IRepositoryCachePolicyFactory<TEntity, TId> CachePolicyFactory
private IRepositoryCachePolicy<TEntity, TId> _cachePolicy;
protected virtual IRepositoryCachePolicy<TEntity, TId> CachePolicy
{
get
{
return _cachePolicyFactory ?? (_cachePolicyFactory = new DefaultRepositoryCachePolicyFactory<TEntity, TId>(
RuntimeCache,
new RepositoryCachePolicyOptions(() =>
{
//Get count of all entities of current type (TEntity) to ensure cached result is correct
var query = Query.Where(x => x.Id != 0);
return PerformCount(query);
})));
if (_cachePolicy != null) return _cachePolicy;
var options = new RepositoryCachePolicyOptions(() =>
{
//Get count of all entities of current type (TEntity) to ensure cached result is correct
var query = Query.Where(x => x.Id != 0);
return PerformCount(query);
});
_cachePolicy = new DefaultRepositoryCachePolicy<TEntity, TId>(RuntimeCache, options);
return _cachePolicy;
}
}
@@ -137,10 +136,7 @@ namespace Umbraco.Core.Persistence.Repositories
/// <returns></returns>
public TEntity Get(TId id)
{
using (var p = CachePolicyFactory.CreatePolicy())
{
return p.Get(id, PerformGet);
}
return CachePolicy.Get(id, PerformGet, PerformGetAll);
}
protected abstract IEnumerable<TEntity> PerformGetAll(params TId[] ids);
@@ -163,11 +159,7 @@ namespace Umbraco.Core.Persistence.Repositories
throw new InvalidOperationException("Cannot perform a query with more than 2000 parameters");
}
using (var p = CachePolicyFactory.CreatePolicy())
{
var result = p.GetAll(ids, PerformGetAll);
return result;
}
return CachePolicy.GetAll(ids, PerformGetAll);
}
protected abstract IEnumerable<TEntity> PerformGetByQuery(IQuery<TEntity> query);
@@ -191,10 +183,7 @@ namespace Umbraco.Core.Persistence.Repositories
/// <returns></returns>
public bool Exists(TId id)
{
using (var p = CachePolicyFactory.CreatePolicy())
{
return p.Exists(id, PerformExists);
}
return CachePolicy.Exists(id, PerformExists, PerformGetAll);
}
protected abstract int PerformCount(IQuery<TEntity> query);
@@ -214,12 +203,7 @@ namespace Umbraco.Core.Persistence.Repositories
/// <param name="entity"></param>
public virtual void PersistNewItem(IEntity entity)
{
var casted = (TEntity)entity;
using (var p = CachePolicyFactory.CreatePolicy())
{
p.CreateOrUpdate(casted, PersistNewItem);
}
CachePolicy.Create((TEntity) entity, PersistNewItem);
}
/// <summary>
@@ -228,12 +212,7 @@ namespace Umbraco.Core.Persistence.Repositories
/// <param name="entity"></param>
public virtual void PersistUpdatedItem(IEntity entity)
{
var casted = (TEntity)entity;
using (var p = CachePolicyFactory.CreatePolicy())
{
p.CreateOrUpdate(casted, PersistUpdatedItem);
}
CachePolicy.Update((TEntity) entity, PersistUpdatedItem);
}
/// <summary>
@@ -242,12 +221,7 @@ namespace Umbraco.Core.Persistence.Repositories
/// <param name="entity"></param>
public virtual void PersistDeletedItem(IEntity entity)
{
var casted = (TEntity)entity;
using (var p = CachePolicyFactory.CreatePolicy())
{
p.Remove(casted, PersistDeletedItem);
}
CachePolicy.Delete((TEntity) entity, PersistDeletedItem);
}
@@ -35,6 +35,7 @@ namespace Umbraco.Core.Persistence.Repositories
private readonly ITemplatesSection _templateConfig;
private readonly ViewHelper _viewHelper;
private readonly MasterPageHelper _masterPageHelper;
private IRepositoryCachePolicy<ITemplate, int> _cachePolicy;
public TemplateRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, IFileSystem masterpageFileSystem, IFileSystem viewFileSystem, ITemplatesSection templateConfig, IMappingResolver mappingResolver)
: base(work, cache, logger, mappingResolver)
@@ -46,15 +47,15 @@ namespace Umbraco.Core.Persistence.Repositories
_masterPageHelper = new MasterPageHelper(_masterpagesFileSystem);
}
private FullDataSetRepositoryCachePolicyFactory<ITemplate, int> _cachePolicyFactory;
protected override IRepositoryCachePolicyFactory<ITemplate, int> CachePolicyFactory
protected override IRepositoryCachePolicy<ITemplate, int> CachePolicy
{
get
{
//Use a FullDataSet cache policy - this will cache the entire GetAll result in a single collection
return _cachePolicyFactory ?? (_cachePolicyFactory = new FullDataSetRepositoryCachePolicyFactory<ITemplate, int>(
RuntimeCache, GetEntityId, () => PerformGetAll(), false));
if (_cachePolicy != null) return _cachePolicy;
_cachePolicy = new FullDataSetRepositoryCachePolicy<ITemplate, int>(RuntimeCache, GetEntityId, /*expires:*/ false);
return _cachePolicy;
}
}
+1 -4
View File
@@ -74,9 +74,7 @@
<Compile Include="Cache\CacheKeys.cs" />
<Compile Include="Cache\CacheProviderExtensions.cs" />
<Compile Include="Cache\DefaultRepositoryCachePolicy.cs" />
<Compile Include="Cache\DefaultRepositoryCachePolicyFactory.cs" />
<Compile Include="Cache\FullDataSetRepositoryCachePolicy.cs" />
<Compile Include="Cache\FullDataSetRepositoryCachePolicyFactory.cs" />
<Compile Include="Cache\ICacheProvider.cs" />
<Compile Include="Cache\CacheRefresherBase.cs" />
<Compile Include="Cache\CacheRefresherEventArgs.cs" />
@@ -84,8 +82,8 @@
<Compile Include="Cache\HttpRequestCacheProvider.cs" />
<Compile Include="Cache\IRepositoryCachePolicy.cs" />
<Compile Include="Cache\IPayloadCacheRefresher.cs" />
<Compile Include="Cache\IRepositoryCachePolicyFactory.cs" />
<Compile Include="Cache\IsolatedRuntimeCache.cs" />
<Compile Include="Cache\NoCacheRepositoryCachePolicy.cs" />
<Compile Include="Cache\ObjectCacheRuntimeCacheProvider.cs" />
<Compile Include="Cache\IRuntimeCacheProvider.cs" />
<Compile Include="Cache\HttpRuntimeCacheProvider.cs" />
@@ -94,7 +92,6 @@
<Compile Include="Cache\NullCacheProvider.cs" />
<Compile Include="Cache\RepositoryCachePolicyBase.cs" />
<Compile Include="Cache\SingleItemsOnlyRepositoryCachePolicy.cs" />
<Compile Include="Cache\OnlySingleItemsRepositoryCachePolicyFactory.cs" />
<Compile Include="Cache\PayloadCacheRefresherBase.cs" />
<Compile Include="Cache\RepositoryCachePolicyOptions.cs" />
<Compile Include="Cache\StaticCacheProvider.cs" />
@@ -24,10 +24,8 @@ namespace Umbraco.Tests.Cache
});
var defaultPolicy = new DefaultRepositoryCachePolicy<AuditItem, object>(cache.Object, new RepositoryCachePolicyOptions());
using (defaultPolicy)
{
var found = defaultPolicy.Get(1, o => new AuditItem(1, "blah", AuditType.Copy, 123));
}
var found = defaultPolicy.Get(1, id => new AuditItem(1, "blah", AuditType.Copy, 123), o => null);
Assert.IsTrue(isCached);
}
@@ -38,11 +36,9 @@ namespace Umbraco.Tests.Cache
cache.Setup(x => x.GetCacheItem(It.IsAny<string>())).Returns(new AuditItem(1, "blah", AuditType.Copy, 123));
var defaultPolicy = new DefaultRepositoryCachePolicy<AuditItem, object>(cache.Object, new RepositoryCachePolicyOptions());
using (defaultPolicy)
{
var found = defaultPolicy.Get(1, o => (AuditItem) null);
Assert.IsNotNull(found);
}
var found = defaultPolicy.Get(1, id => null, ids => null);
Assert.IsNotNull(found);
}
[Test]
@@ -59,14 +55,12 @@ namespace Umbraco.Tests.Cache
cache.Setup(x => x.GetCacheItemsByKeySearch(It.IsAny<string>())).Returns(new AuditItem[] {});
var defaultPolicy = new DefaultRepositoryCachePolicy<AuditItem, object>(cache.Object, new RepositoryCachePolicyOptions());
using (defaultPolicy)
{
var found = defaultPolicy.GetAll(new object[] {}, o => new[]
{
new AuditItem(1, "blah", AuditType.Copy, 123),
new AuditItem(2, "blah2", AuditType.Copy, 123)
});
}
var found = defaultPolicy.GetAll(new object[] {}, ids => new[]
{
new AuditItem(1, "blah", AuditType.Copy, 123),
new AuditItem(2, "blah2", AuditType.Copy, 123)
});
Assert.AreEqual(2, cached.Count);
}
@@ -82,11 +76,9 @@ namespace Umbraco.Tests.Cache
});
var defaultPolicy = new DefaultRepositoryCachePolicy<AuditItem, object>(cache.Object, new RepositoryCachePolicyOptions());
using (defaultPolicy)
{
var found = defaultPolicy.GetAll(new object[] {}, o => new[] {(AuditItem) null});
Assert.AreEqual(2, found.Length);
}
var found = defaultPolicy.GetAll(new object[] {}, ids => new[] { (AuditItem)null });
Assert.AreEqual(2, found.Length);
}
[Test]
@@ -103,13 +95,7 @@ namespace Umbraco.Tests.Cache
var defaultPolicy = new DefaultRepositoryCachePolicy<AuditItem, object>(cache.Object, new RepositoryCachePolicyOptions());
try
{
using (defaultPolicy)
{
defaultPolicy.CreateOrUpdate(new AuditItem(1, "blah", AuditType.Copy, 123), item =>
{
throw new Exception("blah!");
});
}
defaultPolicy.Update(new AuditItem(1, "blah", AuditType.Copy, 123), item => { throw new Exception("blah!"); });
}
catch
{
@@ -135,13 +121,7 @@ namespace Umbraco.Tests.Cache
var defaultPolicy = new DefaultRepositoryCachePolicy<AuditItem, object>(cache.Object, new RepositoryCachePolicyOptions());
try
{
using (defaultPolicy)
{
defaultPolicy.Remove(new AuditItem(1, "blah", AuditType.Copy, 123), item =>
{
throw new Exception("blah!");
});
}
defaultPolicy.Delete(new AuditItem(1, "blah", AuditType.Copy, 123), item => { throw new Exception("blah!"); });
}
catch
{
@@ -32,11 +32,9 @@ namespace Umbraco.Tests.Cache
isCached = true;
});
var defaultPolicy = new FullDataSetRepositoryCachePolicy<AuditItem, object>(cache.Object, item => item.Id, () => getAll, false);
using (defaultPolicy)
{
var found = defaultPolicy.Get(1, o => new AuditItem(1, "blah", AuditType.Copy, 123));
}
var policy = new FullDataSetRepositoryCachePolicy<AuditItem, object>(cache.Object, item => item.Id, false);
var found = policy.Get(1, id => new AuditItem(1, "blah", AuditType.Copy, 123), ids => getAll);
Assert.IsTrue(isCached);
}
@@ -52,12 +50,10 @@ namespace Umbraco.Tests.Cache
var cache = new Mock<IRuntimeCacheProvider>();
cache.Setup(x => x.GetCacheItem(It.IsAny<string>())).Returns(new AuditItem(1, "blah", AuditType.Copy, 123));
var defaultPolicy = new FullDataSetRepositoryCachePolicy<AuditItem, object>(cache.Object, item => item.Id, () => getAll, false);
using (defaultPolicy)
{
var found = defaultPolicy.Get(1, o => (AuditItem)null);
Assert.IsNotNull(found);
}
var defaultPolicy = new FullDataSetRepositoryCachePolicy<AuditItem, object>(cache.Object, item => item.Id, false);
var found = defaultPolicy.Get(1, id => null, ids => getAll);
Assert.IsNotNull(found);
}
[Test]
@@ -84,21 +80,17 @@ namespace Umbraco.Tests.Cache
return cached.Any() ? new DeepCloneableList<AuditItem>(ListCloneBehavior.CloneOnce) : null;
});
var defaultPolicy = new FullDataSetRepositoryCachePolicy<AuditItem, object>(cache.Object, item => item.Id, () => getAll, false);
using (defaultPolicy)
{
var found = defaultPolicy.GetAll(new object[] {}, o => getAll);
}
var policy = new FullDataSetRepositoryCachePolicy<AuditItem, object>(cache.Object, item => item.Id, false);
var found = policy.GetAll(new object[] {}, ids => getAll);
Assert.AreEqual(1, cached.Count);
Assert.IsNotNull(list);
//Do it again, ensure that its coming from the cache!
defaultPolicy = new FullDataSetRepositoryCachePolicy<AuditItem, object>(cache.Object, item => item.Id, () => getAll, false);
using (defaultPolicy)
{
var found = defaultPolicy.GetAll(new object[] { }, o => getAll);
}
policy = new FullDataSetRepositoryCachePolicy<AuditItem, object>(cache.Object, item => item.Id, false);
found = policy.GetAll(new object[] { }, ids => getAll);
Assert.AreEqual(1, cached.Count);
Assert.IsNotNull(list);
@@ -127,11 +119,9 @@ namespace Umbraco.Tests.Cache
});
cache.Setup(x => x.GetCacheItem(It.IsAny<string>())).Returns(new AuditItem[] { });
var defaultPolicy = new FullDataSetRepositoryCachePolicy<AuditItem, object>(cache.Object, item => item.Id, () => getAll, false);
using (defaultPolicy)
{
var found = defaultPolicy.GetAll(new object[] { }, o => getAll);
}
var defaultPolicy = new FullDataSetRepositoryCachePolicy<AuditItem, object>(cache.Object, item => item.Id, false);
var found = defaultPolicy.GetAll(new object[] { }, ids => getAll);
Assert.AreEqual(1, cached.Count);
Assert.IsNotNull(list);
@@ -150,12 +140,10 @@ namespace Umbraco.Tests.Cache
new AuditItem(2, "blah2", AuditType.Copy, 123)
});
var defaultPolicy = new FullDataSetRepositoryCachePolicy<AuditItem, object>(cache.Object, item => item.Id, () => getAll, false);
using (defaultPolicy)
{
var found = defaultPolicy.GetAll(new object[] { }, o => getAll);
Assert.AreEqual(2, found.Length);
}
var defaultPolicy = new FullDataSetRepositoryCachePolicy<AuditItem, object>(cache.Object,item => item.Id, false);
var found = defaultPolicy.GetAll(new object[] { }, ids => getAll);
Assert.AreEqual(2, found.Length);
}
[Test]
@@ -175,16 +163,10 @@ namespace Umbraco.Tests.Cache
cacheCleared = true;
});
var defaultPolicy = new FullDataSetRepositoryCachePolicy<AuditItem, object>(cache.Object, item => item.Id, () => getAll, false);
var defaultPolicy = new FullDataSetRepositoryCachePolicy<AuditItem, object>(cache.Object, item => item.Id, false);
try
{
using (defaultPolicy)
{
defaultPolicy.CreateOrUpdate(new AuditItem(1, "blah", AuditType.Copy, 123), item =>
{
throw new Exception("blah!");
});
}
defaultPolicy.Update(new AuditItem(1, "blah", AuditType.Copy, 123), item => { throw new Exception("blah!"); });
}
catch
{
@@ -213,16 +195,10 @@ namespace Umbraco.Tests.Cache
cacheCleared = true;
});
var defaultPolicy = new FullDataSetRepositoryCachePolicy<AuditItem, object>(cache.Object, item => item.Id, () => getAll, false);
var defaultPolicy = new FullDataSetRepositoryCachePolicy<AuditItem, object>(cache.Object, item => item.Id, false);
try
{
using (defaultPolicy)
{
defaultPolicy.Remove(new AuditItem(1, "blah", AuditType.Copy, 123), item =>
{
throw new Exception("blah!");
});
}
defaultPolicy.Delete(new AuditItem(1, "blah", AuditType.Copy, 123), item => { throw new Exception("blah!"); });
}
catch
{
@@ -25,14 +25,12 @@ namespace Umbraco.Tests.Cache
cache.Setup(x => x.GetCacheItemsByKeySearch(It.IsAny<string>())).Returns(new AuditItem[] { });
var defaultPolicy = new SingleItemsOnlyRepositoryCachePolicy<AuditItem, object>(cache.Object, new RepositoryCachePolicyOptions());
using (defaultPolicy)
{
var found = defaultPolicy.GetAll(new object[] { }, o => new[]
{
new AuditItem(1, "blah", AuditType.Copy, 123),
new AuditItem(2, "blah2", AuditType.Copy, 123)
});
}
var found = defaultPolicy.GetAll(new object[] { }, ids => new[]
{
new AuditItem(1, "blah", AuditType.Copy, 123),
new AuditItem(2, "blah2", AuditType.Copy, 123)
});
Assert.AreEqual(0, cached.Count);
}
@@ -50,10 +48,8 @@ namespace Umbraco.Tests.Cache
});
var defaultPolicy = new SingleItemsOnlyRepositoryCachePolicy<AuditItem, object>(cache.Object, new RepositoryCachePolicyOptions());
using (defaultPolicy)
{
var found = defaultPolicy.Get(1, o => new AuditItem(1, "blah", AuditType.Copy, 123));
}
var found = defaultPolicy.Get(1, id => new AuditItem(1, "blah", AuditType.Copy, 123), ids => null);
Assert.IsTrue(isCached);
}
}