using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Cms.Core.Sync;
namespace Umbraco.Cms.Core.Cache
{
///
/// Represents the entry point into Umbraco's distributed cache infrastructure.
///
///
///
/// The distributed cache infrastructure ensures that distributed caches are
/// invalidated properly in load balancing environments.
///
///
/// Distribute caches include static (in-memory) cache, runtime cache, front-end content cache, Examine/Lucene indexes
///
///
public sealed class DistributedCache
{
private readonly IServerMessenger _serverMessenger;
private readonly CacheRefresherCollection _cacheRefreshers;
public DistributedCache(IServerMessenger serverMessenger, CacheRefresherCollection cacheRefreshers)
{
_serverMessenger = serverMessenger;
_cacheRefreshers = cacheRefreshers;
}
#region Core notification methods
///
/// Notifies the distributed cache of specified item invalidation, for a specified .
///
/// The type of the invalidated items.
/// The unique identifier of the ICacheRefresher.
/// A function returning the unique identifier of items.
/// The invalidated items.
///
/// This method is much better for performance because it does not need to re-lookup object instances.
///
public void Refresh(Guid refresherGuid, Func getNumericId, params T[] instances)
{
if (refresherGuid == Guid.Empty || instances.Length == 0 || getNumericId == null) return;
_serverMessenger.QueueRefresh(
GetRefresherById(refresherGuid),
getNumericId,
instances);
}
///
/// Notifies the distributed cache of a specified item invalidation, for a specified .
///
/// The unique identifier of the ICacheRefresher.
/// The unique identifier of the invalidated item.
public void Refresh(Guid refresherGuid, int id)
{
if (refresherGuid == Guid.Empty || id == default(int)) return;
_serverMessenger.QueueRefresh(
GetRefresherById(refresherGuid),
id);
}
///
/// Notifies the distributed cache of a specified item invalidation, for a specified .
///
/// The unique identifier of the ICacheRefresher.
/// The unique identifier of the invalidated item.
public void Refresh(Guid refresherGuid, Guid id)
{
if (refresherGuid == Guid.Empty || id == Guid.Empty) return;
_serverMessenger.QueueRefresh(
GetRefresherById(refresherGuid),
id);
}
// payload should be an object, or array of objects, NOT a
// Linq enumerable of some sort (IEnumerable, query...)
public void RefreshByPayload(Guid refresherGuid, TPayload[] payload)
{
if (refresherGuid == Guid.Empty || payload == null) return;
_serverMessenger.QueueRefresh(
GetRefresherById(refresherGuid),
payload);
}
// so deal with IEnumerable
public void RefreshByPayload(Guid refresherGuid, IEnumerable payloads)
where TPayload : class
{
if (refresherGuid == Guid.Empty || payloads == null) return;
_serverMessenger.QueueRefresh(
GetRefresherById(refresherGuid),
payloads.ToArray());
}
/////
///// Notifies the distributed cache, for a specified .
/////
///// The unique identifier of the ICacheRefresher.
///// The notification content.
//internal void Notify(Guid refresherId, object payload)
//{
// if (refresherId == Guid.Empty || payload == null) return;
// _serverMessenger.Notify(
// Current.ServerRegistrar.Registrations,
// GetRefresherById(refresherId),
// json);
//}
///
/// Notifies the distributed cache of a global invalidation for a specified .
///
/// The unique identifier of the ICacheRefresher.
public void RefreshAll(Guid refresherGuid)
{
if (refresherGuid == Guid.Empty) return;
_serverMessenger.QueueRefreshAll(
GetRefresherById(refresherGuid));
}
///
/// Notifies the distributed cache of a specified item removal, for a specified .
///
/// The unique identifier of the ICacheRefresher.
/// The unique identifier of the removed item.
public void Remove(Guid refresherGuid, int id)
{
if (refresherGuid == Guid.Empty || id == default(int)) return;
_serverMessenger.QueueRemove(
GetRefresherById(refresherGuid),
id);
}
///
/// Notifies the distributed cache of specified item removal, for a specified .
///
/// The type of the removed items.
/// The unique identifier of the ICacheRefresher.
/// A function returning the unique identifier of items.
/// The removed items.
///
/// This method is much better for performance because it does not need to re-lookup object instances.
///
public void Remove(Guid refresherGuid, Func getNumericId, params T[] instances)
{
_serverMessenger.QueueRemove(
GetRefresherById(refresherGuid),
getNumericId,
instances);
}
#endregion
// helper method to get an ICacheRefresher by its unique identifier
private ICacheRefresher GetRefresherById(Guid refresherGuid)
{
ICacheRefresher? refresher = _cacheRefreshers[refresherGuid];
if (refresher == null)
{
throw new InvalidOperationException($"No cache refresher found with id {refresherGuid}");
}
return refresher;
}
}
}