From c8471b096cc288b5d8d42dbc489b2b520230f128 Mon Sep 17 00:00:00 2001 From: Mole Date: Thu, 25 Mar 2021 14:51:00 +0100 Subject: [PATCH] Switch to INotificationHandler --- .../Cache/DistributedCacheBinder_Handlers.cs | 50 +++++++------- .../Compose/NotificationsComposer.cs | 8 +++ .../Services/Implement/LocalizationService.cs | 67 +++---------------- .../Compose/NotificationsComposer.cs | 17 +++++ .../PublishedSnapshotServiceEventHandler.cs | 12 ++-- .../Scoping/ScopedRepositoryTests.cs | 22 ++++-- 6 files changed, 82 insertions(+), 94 deletions(-) create mode 100644 src/Umbraco.PublishedCache.NuCache/Compose/NotificationsComposer.cs diff --git a/src/Umbraco.Infrastructure/Cache/DistributedCacheBinder_Handlers.cs b/src/Umbraco.Infrastructure/Cache/DistributedCacheBinder_Handlers.cs index 1aa4906029..de75ac0905 100644 --- a/src/Umbraco.Infrastructure/Cache/DistributedCacheBinder_Handlers.cs +++ b/src/Umbraco.Infrastructure/Cache/DistributedCacheBinder_Handlers.cs @@ -11,6 +11,7 @@ using Umbraco.Cms.Core.Models.Membership; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Services.Changes; using Umbraco.Cms.Core.Services.Implement; +using Umbraco.Cms.Infrastructure.Services.Notifications; using Umbraco.Extensions; namespace Umbraco.Cms.Core.Cache @@ -18,7 +19,11 @@ namespace Umbraco.Cms.Core.Cache /// /// Default implementation. /// - public partial class DistributedCacheBinder + public partial class DistributedCacheBinder : + INotificationHandler, + INotificationHandler, + INotificationHandler, + INotificationHandler { private List _unbinders; @@ -61,12 +66,6 @@ namespace Umbraco.Cms.Core.Cache Bind(() => UserService.UserGroupPermissionsAssigned += UserService_UserGroupPermissionsAssigned, () => UserService.UserGroupPermissionsAssigned -= UserService_UserGroupPermissionsAssigned); - // bind to dictionary events - Bind(() => LocalizationService.DeletedDictionaryItem += LocalizationService_DeletedDictionaryItem, - () => LocalizationService.DeletedDictionaryItem -= LocalizationService_DeletedDictionaryItem); - Bind(() => LocalizationService.SavedDictionaryItem += LocalizationService_SavedDictionaryItem, - () => LocalizationService.SavedDictionaryItem -= LocalizationService_SavedDictionaryItem); - // bind to data type events Bind(() => DataTypeService.Deleted += DataTypeService_Deleted, () => DataTypeService.Deleted -= DataTypeService_Deleted); @@ -85,12 +84,6 @@ namespace Umbraco.Cms.Core.Cache Bind(() => DomainService.Deleted += DomainService_Deleted, () => DomainService.Deleted -= DomainService_Deleted); - // bind to language events - Bind(() => LocalizationService.SavedLanguage += LocalizationService_SavedLanguage, - () => LocalizationService.SavedLanguage -= LocalizationService_SavedLanguage); - Bind(() => LocalizationService.DeletedLanguage += LocalizationService_DeletedLanguage, - () => LocalizationService.DeletedLanguage -= LocalizationService_DeletedLanguage); - // bind to content type events Bind(() => ContentTypeService.Changed += ContentTypeService_Changed, () => ContentTypeService.Changed -= ContentTypeService_Changed); @@ -196,17 +189,20 @@ namespace Umbraco.Cms.Core.Cache #endregion #region LocalizationService / Dictionary - - private void LocalizationService_SavedDictionaryItem(ILocalizationService sender, SaveEventArgs e) + public void Handle(DictionaryItemSavedNotification notification) { - foreach (var entity in e.SavedEntities) + foreach (IDictionaryItem entity in notification.SavedEntities) + { _distributedCache.RefreshDictionaryCache(entity.Id); + } } - private void LocalizationService_DeletedDictionaryItem(ILocalizationService sender, DeleteEventArgs e) + public void Handle(DictionaryItemDeletedNotification notification) { - foreach (var entity in e.DeletedEntities) + foreach (IDictionaryItem entity in notification.DeletedEntities) + { _distributedCache.RemoveDictionaryCache(entity.Id); + } } #endregion @@ -248,23 +244,25 @@ namespace Umbraco.Cms.Core.Cache /// /// Fires when a language is deleted /// - /// - /// - private void LocalizationService_DeletedLanguage(ILocalizationService sender, DeleteEventArgs e) + /// + public void Handle(LanguageDeletedNotification notification) { - foreach (var entity in e.DeletedEntities) + foreach (ILanguage entity in notification.DeletedEntities) + { _distributedCache.RemoveLanguageCache(entity); + } } /// /// Fires when a language is saved /// - /// - /// - private void LocalizationService_SavedLanguage(ILocalizationService sender, SaveEventArgs e) + /// + public void Handle(LanguageSavedNotification notification) { - foreach (var entity in e.SavedEntities) + foreach (ILanguage entity in notification.SavedEntities) + { _distributedCache.RefreshLanguageCache(entity); + } } #endregion diff --git a/src/Umbraco.Infrastructure/Compose/NotificationsComposer.cs b/src/Umbraco.Infrastructure/Compose/NotificationsComposer.cs index c760c33b71..2e3403e3dd 100644 --- a/src/Umbraco.Infrastructure/Compose/NotificationsComposer.cs +++ b/src/Umbraco.Infrastructure/Compose/NotificationsComposer.cs @@ -1,6 +1,7 @@ // Copyright (c) Umbraco. // See LICENSE for more details. +using Umbraco.Cms.Core.Cache; using Umbraco.Cms.Core.Composing; using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Events; @@ -62,6 +63,13 @@ namespace Umbraco.Cms.Core.Compose .AddNotificationHandler() .AddNotificationHandler() .AddNotificationHandler(); + + // Add notification handlers for DistributedCache + builder + .AddNotificationHandler() + .AddNotificationHandler() + .AddNotificationHandler() + .AddNotificationHandler(); } } } diff --git a/src/Umbraco.Infrastructure/Services/Implement/LocalizationService.cs b/src/Umbraco.Infrastructure/Services/Implement/LocalizationService.cs index f4072ccfb7..b8c36f1ed9 100644 --- a/src/Umbraco.Infrastructure/Services/Implement/LocalizationService.cs +++ b/src/Umbraco.Infrastructure/Services/Implement/LocalizationService.cs @@ -18,7 +18,6 @@ namespace Umbraco.Cms.Core.Services.Implement { private readonly IDictionaryRepository _dictionaryRepository; private readonly ILanguageRepository _languageRepository; - private readonly IEventAggregator _eventAggregator; private readonly IAuditRepository _auditRepository; public LocalizationService( @@ -27,14 +26,12 @@ namespace Umbraco.Cms.Core.Services.Implement IEventMessagesFactory eventMessagesFactory, IDictionaryRepository dictionaryRepository, IAuditRepository auditRepository, - ILanguageRepository languageRepository, - IEventAggregator eventAggregator) + ILanguageRepository languageRepository) : base(provider, loggerFactory, eventMessagesFactory) { _dictionaryRepository = dictionaryRepository; _auditRepository = auditRepository; _languageRepository = languageRepository; - _eventAggregator = eventAggregator; } /// @@ -101,7 +98,7 @@ namespace Umbraco.Cms.Core.Services.Implement EventMessages eventMessages = EventMessagesFactory.Get(); var savingNotification = new DictionaryItemSavingNotification(item, eventMessages); - if (_eventAggregator.PublishCancelable(savingNotification)) + if (scope.Notifications.PublishCancelable(savingNotification)) { scope.Complete(); return item; @@ -111,7 +108,7 @@ namespace Umbraco.Cms.Core.Services.Implement // ensure the lazy Language callback is assigned EnsureDictionaryItemLanguageCallback(item); - _eventAggregator.Publish(new DictionaryItemSavedNotification(item, eventMessages).WithStateFrom(savingNotification)); + scope.Notifications.Publish(new DictionaryItemSavedNotification(item, eventMessages).WithStateFrom(savingNotification)); scope.Complete(); @@ -244,7 +241,7 @@ namespace Umbraco.Cms.Core.Services.Implement { EventMessages eventMessages = EventMessagesFactory.Get(); var savingNotification = new DictionaryItemSavingNotification(dictionaryItem, eventMessages); - if (_eventAggregator.PublishCancelable(savingNotification)) + if (scope.Notifications.PublishCancelable(savingNotification)) { scope.Complete(); return; @@ -256,7 +253,7 @@ namespace Umbraco.Cms.Core.Services.Implement // ensure the lazy Language callback is assigned EnsureDictionaryItemLanguageCallback(dictionaryItem); - _eventAggregator.Publish(new DictionaryItemSavedNotification(dictionaryItem, eventMessages).WithStateFrom(savingNotification)); + scope.Notifications.Publish(new DictionaryItemSavedNotification(dictionaryItem, eventMessages).WithStateFrom(savingNotification)); Audit(AuditType.Save, "Save DictionaryItem", userId, dictionaryItem.Id, "DictionaryItem"); scope.Complete(); @@ -275,14 +272,14 @@ namespace Umbraco.Cms.Core.Services.Implement { EventMessages eventMessages = EventMessagesFactory.Get(); var deletingNotification = new DictionaryItemDeletingNotification(dictionaryItem, eventMessages); - if (_eventAggregator.PublishCancelable(deletingNotification)) + if (scope.Notifications.PublishCancelable(deletingNotification)) { scope.Complete(); return; } _dictionaryRepository.Delete(dictionaryItem); - _eventAggregator.Publish(new DictionaryItemDeletedNotification(dictionaryItem, eventMessages).WithStateFrom(deletingNotification)); + scope.Notifications.Publish(new DictionaryItemDeletedNotification(dictionaryItem, eventMessages).WithStateFrom(deletingNotification)); Audit(AuditType.Delete, "Delete DictionaryItem", userId, dictionaryItem.Id, "DictionaryItem"); @@ -388,14 +385,14 @@ namespace Umbraco.Cms.Core.Services.Implement EventMessages eventMessages = EventMessagesFactory.Get(); var savingNotification = new LanguageSavingNotification(language, eventMessages); - if (_eventAggregator.PublishCancelable(savingNotification)) + if (scope.Notifications.PublishCancelable(savingNotification)) { scope.Complete(); return; } _languageRepository.Save(language); - _eventAggregator.Publish(new LanguageSavedNotification(language, eventMessages).WithStateFrom(savingNotification)); + scope.Notifications.Publish(new LanguageSavedNotification(language, eventMessages).WithStateFrom(savingNotification)); Audit(AuditType.Save, "Save Language", userId, language.Id, ObjectTypes.GetName(UmbracoObjectTypes.Language)); @@ -431,7 +428,7 @@ namespace Umbraco.Cms.Core.Services.Implement EventMessages eventMessages = EventMessagesFactory.Get(); var deletingLanguageNotification = new LanguageDeletingNotification(language, eventMessages); - if (_eventAggregator.PublishCancelable(deletingLanguageNotification)) + if (scope.Notifications.PublishCancelable(deletingLanguageNotification)) { scope.Complete(); return; @@ -440,7 +437,7 @@ namespace Umbraco.Cms.Core.Services.Implement // NOTE: Other than the fall-back language, there aren't any other constraints in the db, so possible references aren't deleted _languageRepository.Delete(language); - _eventAggregator.Publish(new LanguageDeletedNotification(language, eventMessages).WithStateFrom(deletingLanguageNotification)); + scope.Notifications.Publish(new LanguageDeletedNotification(language, eventMessages).WithStateFrom(deletingLanguageNotification)); Audit(AuditType.Delete, "Delete Language", userId, language.Id, ObjectTypes.GetName(UmbracoObjectTypes.Language)); scope.Complete(); @@ -475,47 +472,5 @@ namespace Umbraco.Cms.Core.Services.Implement return _dictionaryRepository.GetDictionaryItemKeyMap(); } } - - #region Events - /// - /// Occurs before Delete - /// - public static event TypedEventHandler> DeletingLanguage; - - /// - /// Occurs after Delete - /// - public static event TypedEventHandler> DeletedLanguage; - - /// - /// Occurs before Delete - /// - public static event TypedEventHandler> DeletingDictionaryItem; - - /// - /// Occurs after Delete - /// - public static event TypedEventHandler> DeletedDictionaryItem; - - /// - /// Occurs before Save - /// - public static event TypedEventHandler> SavingDictionaryItem; - - /// - /// Occurs after Save - /// - public static event TypedEventHandler> SavedDictionaryItem; - - /// - /// Occurs before Save - /// - public static event TypedEventHandler> SavingLanguage; - - /// - /// Occurs after Save - /// - public static event TypedEventHandler> SavedLanguage; - #endregion } } diff --git a/src/Umbraco.PublishedCache.NuCache/Compose/NotificationsComposer.cs b/src/Umbraco.PublishedCache.NuCache/Compose/NotificationsComposer.cs new file mode 100644 index 0000000000..df84759793 --- /dev/null +++ b/src/Umbraco.PublishedCache.NuCache/Compose/NotificationsComposer.cs @@ -0,0 +1,17 @@ +using Umbraco.Cms.Core.Compose; +using Umbraco.Cms.Core.Composing; +using Umbraco.Cms.Core.DependencyInjection; +using Umbraco.Cms.Infrastructure.Services.Notifications; + +namespace Umbraco.Cms.Infrastructure.PublishedCache.Compose +{ + public sealed class NotificationsComposer : ComponentComposer, ICoreComposer + { + public override void Compose(IUmbracoBuilder builder) + { + base.Compose(builder); + + builder.AddNotificationHandler(); + } + } +} diff --git a/src/Umbraco.PublishedCache.NuCache/PublishedSnapshotServiceEventHandler.cs b/src/Umbraco.PublishedCache.NuCache/PublishedSnapshotServiceEventHandler.cs index 25ceb9fb6a..df02320d87 100644 --- a/src/Umbraco.PublishedCache.NuCache/PublishedSnapshotServiceEventHandler.cs +++ b/src/Umbraco.PublishedCache.NuCache/PublishedSnapshotServiceEventHandler.cs @@ -9,6 +9,7 @@ using Umbraco.Cms.Core.Services.Changes; using Umbraco.Cms.Core.Services.Implement; using Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement; using Umbraco.Cms.Infrastructure.PublishedCache.Persistence; +using Umbraco.Cms.Infrastructure.Services.Notifications; using Umbraco.Extensions; namespace Umbraco.Cms.Infrastructure.PublishedCache @@ -16,7 +17,7 @@ namespace Umbraco.Cms.Infrastructure.PublishedCache /// /// Subscribes to Umbraco events to ensure nucache remains consistent with the source data /// - public class PublishedSnapshotServiceEventHandler : IDisposable + public class PublishedSnapshotServiceEventHandler : IDisposable, INotificationHandler { private readonly IRuntimeState _runtime; private bool _disposedValue; @@ -79,9 +80,6 @@ namespace Umbraco.Cms.Infrastructure.PublishedCache ContentTypeService.ScopedRefreshedEntity += OnContentTypeRefreshedEntity; MediaTypeService.ScopedRefreshedEntity += OnMediaTypeRefreshedEntity; MemberTypeService.ScopedRefreshedEntity += OnMemberTypeRefreshedEntity; - - // TODO: This should be a cache refresher call! - LocalizationService.SavedLanguage += OnLanguageSaved; } private void TearDownRepositoryEvents() @@ -95,7 +93,6 @@ namespace Umbraco.Cms.Infrastructure.PublishedCache ContentTypeService.ScopedRefreshedEntity -= OnContentTypeRefreshedEntity; MediaTypeService.ScopedRefreshedEntity -= OnMediaTypeRefreshedEntity; MemberTypeService.ScopedRefreshedEntity -= OnMemberTypeRefreshedEntity; - LocalizationService.SavedLanguage -= OnLanguageSaved; // TODO: Shouldn't this be a cache refresher event? } // note: if the service is not ready, ie _isReady is false, then we still handle repository events, @@ -156,13 +153,14 @@ namespace Umbraco.Cms.Infrastructure.PublishedCache } } + // TODO: This should be a cache refresher call! /// /// If a is ever saved with a different culture, we need to rebuild all of the content nucache database table /// - private void OnLanguageSaved(ILocalizationService sender, SaveEventArgs e) + public void Handle(LanguageSavedNotification notification) { // culture changed on an existing language - var cultureChanged = e.SavedEntities.Any(x => !x.WasPropertyDirty(nameof(ILanguage.Id)) && x.WasPropertyDirty(nameof(ILanguage.IsoCode))); + var cultureChanged = notification.SavedEntities.Any(x => !x.WasPropertyDirty(nameof(ILanguage.Id)) && x.WasPropertyDirty(nameof(ILanguage.IsoCode))); if (cultureChanged) { // Rebuild all content for all content types diff --git a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Scoping/ScopedRepositoryTests.cs b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Scoping/ScopedRepositoryTests.cs index 96ba30905b..fcfd81a39d 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Scoping/ScopedRepositoryTests.cs +++ b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Scoping/ScopedRepositoryTests.cs @@ -6,6 +6,7 @@ using System.Linq; using Microsoft.Extensions.Logging; using NUnit.Framework; using Umbraco.Cms.Core.Cache; +using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.Membership; @@ -14,9 +15,12 @@ using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Services.Implement; using Umbraco.Cms.Core.Sync; using Umbraco.Cms.Core.Web; +using Umbraco.Cms.Infrastructure.PublishedCache; +using Umbraco.Cms.Infrastructure.Services.Notifications; using Umbraco.Cms.Infrastructure.Sync; using Umbraco.Cms.Tests.Common.Testing; using Umbraco.Cms.Tests.Integration.Testing; +using Umbraco.Extensions; namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Scoping { @@ -44,6 +48,17 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Scoping return result; } + protected override void CustomTestSetup(IUmbracoBuilder builder) + { + builder.Services.AddUnique(); + builder + .AddNotificationHandler() + .AddNotificationHandler() + .AddNotificationHandler() + .AddNotificationHandler(); + builder.AddNotificationHandler(); + } + [TearDown] public void Teardown() { @@ -154,9 +169,6 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Scoping Assert.AreEqual(lang.Id, globalCached.Id); Assert.AreEqual("fr-FR", globalCached.IsoCode); - _distributedCacheBinder = new DistributedCacheBinder(new DistributedCache(ServerMessenger, CacheRefresherCollection), GetRequiredService(), GetRequiredService>()); - _distributedCacheBinder.BindEvents(true); - Assert.IsNull(scopeProvider.AmbientScope); using (IScope scope = scopeProvider.CreateScope(repositoryCacheMode: RepositoryCacheMode.Scoped)) { @@ -250,8 +262,8 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Scoping Assert.AreEqual(item.Id, globalCached.Id); Assert.AreEqual("item-key", globalCached.ItemKey); - _distributedCacheBinder = new DistributedCacheBinder(new DistributedCache(ServerMessenger, CacheRefresherCollection), GetRequiredService(), GetRequiredService>()); - _distributedCacheBinder.BindEvents(true); + // _distributedCacheBinder = new DistributedCacheBinder(new DistributedCache(ServerMessenger, CacheRefresherCollection), GetRequiredService(), GetRequiredService>()); + // _distributedCacheBinder.BindEvents(true); Assert.IsNull(scopeProvider.AmbientScope); using (IScope scope = scopeProvider.CreateScope(repositoryCacheMode: RepositoryCacheMode.Scoped))