private BaseCacheManager(string name, ICacheManagerConfiguration configuration) { NotNullOrWhiteSpace(name, nameof(name)); NotNull(configuration, nameof(configuration)); Name = name; Configuration = configuration; var loggerFactory = CacheReflectionHelper.CreateLoggerFactory(configuration); var serializer = CacheReflectionHelper.CreateSerializer(configuration, loggerFactory); Logger = loggerFactory.CreateLogger(this); _logTrace = Logger.IsEnabled(LogLevel.Trace); Logger.LogInfo("Cache manager: adding cache handles..."); try { _cacheHandles = CacheReflectionHelper.CreateCacheHandles(this, loggerFactory, serializer).ToArray(); var index = 0; foreach (var handle in _cacheHandles) { var handleIndex = index; handle.OnCacheSpecificRemove += (sender, args) => { // base cache handle does logging for this TriggerOnRemoveByHandle(args.Key, args.Region, args.Reason, handleIndex + 1, args.Value); if (Configuration.UpdateMode == CacheUpdateMode.Up) { if (_logTrace) { Logger.LogTrace("Cleaning handles above '{0}' because of remove event.", handleIndex); } EvictFromHandlesAbove(args.Key, args.Region, handleIndex); } }; index++; } _cacheBackplane = CacheReflectionHelper.CreateBackplane(configuration, loggerFactory); if (_cacheBackplane != null) { RegisterCacheBackplane(_cacheBackplane); } } catch (Exception ex) { Logger.LogError(ex, "Error occurred while creating the cache manager."); throw ex.InnerException ?? ex; } }
private void RegisterCacheBackplane(CacheBackplane backplane) { NotNull(backplane, nameof(backplane)); // this should have been checked during activation already, just to be totally sure... if (_cacheHandles.Any(p => p.Configuration.IsBackplaneSource)) { // added includeSource param to get the handles which need to be synced. // in case the backplane source is non-distributed (in-memory), only remotly triggered remove and clear should also // trigger a sync locally. For distribtued caches, we expect that the distributed cache is already the source and in sync // as that's the layer which triggered the event. In this case, only other in-memory handles above the distribtued, would be synced. var handles = new Func <bool, BaseCacheHandle <TCacheValue>[]>((includSource) => { var handleList = new List <BaseCacheHandle <TCacheValue> >(); foreach (var handle in _cacheHandles) { if (!handle.Configuration.IsBackplaneSource || (includSource && handle.Configuration.IsBackplaneSource && !handle.IsDistributedCache)) { handleList.Add(handle); } } return(handleList.ToArray()); }); backplane.Changed += (sender, args) => { if (Logger.IsEnabled(LogLevel.Debug)) { Logger.LogDebug("Backplane event: [Changed] for '{1}:{0}'.", args.Key, args.Region); } EvictFromHandles(args.Key, args.Region, handles(false)); switch (args.Action) { case CacheItemChangedEventAction.Add: TriggerOnAdd(args.Key, args.Region, CacheActionEventArgOrigin.Remote); break; case CacheItemChangedEventAction.Put: TriggerOnPut(args.Key, args.Region, CacheActionEventArgOrigin.Remote); break; case CacheItemChangedEventAction.Update: TriggerOnUpdate(args.Key, args.Region, CacheActionEventArgOrigin.Remote); break; } }; backplane.Removed += (sender, args) => { if (_logTrace) { Logger.LogTrace("Backplane event: [Remove] of {0} {1}.", args.Key, args.Region); } EvictFromHandles(args.Key, args.Region, handles(true)); TriggerOnRemove(args.Key, args.Region, CacheActionEventArgOrigin.Remote); }; backplane.Cleared += (sender, args) => { if (_logTrace) { Logger.LogTrace("Backplane event: [Clear]."); } ClearHandles(handles(true)); TriggerOnClear(CacheActionEventArgOrigin.Remote); }; backplane.ClearedRegion += (sender, args) => { if (_logTrace) { Logger.LogTrace("Backplane event: [Clear Region] region: {0}.", args.Region); } ClearRegionHandles(args.Region, handles(true)); TriggerOnClearRegion(args.Region, CacheActionEventArgOrigin.Remote); }; } }
private BaseCacheManager(string name, ICacheManagerConfiguration configuration) { NotNullOrWhiteSpace(name, nameof(name)); NotNull(configuration, nameof(configuration)); Name = name; Configuration = configuration; var loggerFactory = CacheReflectionHelper.CreateLoggerFactory(configuration); var serializer = CacheReflectionHelper.CreateSerializer(configuration, loggerFactory); Logger = loggerFactory.CreateLogger(this); _logTrace = Logger.IsEnabled(LogLevel.Trace); Logger.LogInfo("Cache manager: adding cache handles..."); try { _cacheHandles = CacheReflectionHelper.CreateCacheHandles(this, loggerFactory, serializer).ToArray(); var index = 0; foreach (var handle in _cacheHandles) { var handleIndex = index; handle.OnCacheSpecificRemove += (sender, args) => { // added sync for using backplane with in-memory caches on cache specific removal // but commented for now, this is not really needed if all instances use the same expiration etc, would just cause dublicated events ////if (_cacheBackplane != null && handle.Configuration.IsBackplaneSource && !handle.IsDistributedCache) ////{ //// if (string.IsNullOrEmpty(args.Region)) //// { //// _cacheBackplane.NotifyRemove(args.Key); //// } //// else //// { //// _cacheBackplane.NotifyRemove(args.Key, args.Region); //// } ////} // base cache handle does logging for this if (Configuration.UpdateMode == CacheUpdateMode.Up) { if (_logTrace) { Logger.LogTrace("Cleaning handles above '{0}' because of remove event.", handleIndex); } EvictFromHandlesAbove(args.Key, args.Region, handleIndex); } // moving down below cleanup, optherwise the item could still be in memory TriggerOnRemoveByHandle(args.Key, args.Region, args.Reason, handleIndex + 1, args.Value); }; index++; } _cacheBackplane = CacheReflectionHelper.CreateBackplane(configuration, loggerFactory); if (_cacheBackplane != null) { RegisterCacheBackplane(_cacheBackplane); } } catch (Exception ex) { Logger.LogError(ex, "Error occurred while creating the cache manager."); throw ex.InnerException ?? ex; } }
private void RegisterCacheBackplane(CacheBackplane backplane) { NotNull(backplane, nameof(backplane)); // this should have been checked during activation already, just to be totally sure... if (_cacheHandles.Any(p => p.Configuration.IsBackplaneSource)) { var handles = new Func <BaseCacheHandle <TCacheValue>[]>(() => { var handleList = new List <BaseCacheHandle <TCacheValue> >(); foreach (var handle in _cacheHandles) { if (!handle.Configuration.IsBackplaneSource) { handleList.Add(handle); } } return(handleList.ToArray()); }); backplane.Changed += (sender, args) => { if (_logTrace) { Logger.LogTrace("Backplane event: [Changed] of {0} {1}.", args.Key, args.Region); } EvictFromHandles(args.Key, args.Region, handles()); switch (args.Action) { case CacheItemChangedEventAction.Add: TriggerOnAdd(args.Key, args.Region, CacheActionEventArgOrigin.Remote); break; case CacheItemChangedEventAction.Put: TriggerOnPut(args.Key, args.Region, CacheActionEventArgOrigin.Remote); break; case CacheItemChangedEventAction.Update: TriggerOnUpdate(args.Key, args.Region, CacheActionEventArgOrigin.Remote); break; } }; backplane.Removed += (sender, args) => { if (_logTrace) { Logger.LogTrace("Backplane event: [Remove] of {0} {1}.", args.Key, args.Region); } EvictFromHandles(args.Key, args.Region, handles()); TriggerOnRemove(args.Key, args.Region, CacheActionEventArgOrigin.Remote); }; backplane.Cleared += (sender, args) => { if (_logTrace) { Logger.LogTrace("Backplane event: [Clear]."); } ClearHandles(handles()); TriggerOnClear(CacheActionEventArgOrigin.Remote); }; backplane.ClearedRegion += (sender, args) => { if (_logTrace) { Logger.LogTrace("Backplane event: [Clear Region] region: {0}.", args.Region); } ClearRegionHandles(args.Region, handles()); TriggerOnClearRegion(args.Region, CacheActionEventArgOrigin.Remote); }; } }