From 4904b9ec03ab00a80978100f3c74f6b8595d97ec Mon Sep 17 00:00:00 2001 From: Halil ibrahim Kalkan Date: Fri, 16 Nov 2018 15:13:03 +0300 Subject: [PATCH] Implemented creating distributed events on aggregate roots. --- .../Volo/Abp/Domain/Entities/AggregateRoot.cs | 60 ++++++++++++++----- .../Events/EntityChangeEventHelper.cs | 17 ++++-- .../Entities/Events/EntityChangeReport.cs | 9 ++- .../Domain/Entities/IGeneratesDomainEvents.cs | 8 ++- .../Abp/EntityFrameworkCore/AbpDbContext.cs | 19 +++--- .../Repositories/MongoDB/MongoDbRepository.cs | 27 ++++++--- .../Volo/Abp/TestApp/Domain/Person.cs | 19 +++++- .../TestApp/Domain/PersonNameChangedEto.cs | 15 +++++ .../Abp/TestApp/Testing/DomainEvents_Tests.cs | 20 +++++-- 9 files changed, 153 insertions(+), 41 deletions(-) create mode 100644 framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/PersonNameChangedEto.cs diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/AggregateRoot.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/AggregateRoot.cs index 8a4a8e0549..2916b7de3b 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/AggregateRoot.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/AggregateRoot.cs @@ -7,28 +7,45 @@ namespace Volo.Abp.Domain.Entities [Serializable] public abstract class AggregateRoot : Entity, IAggregateRoot, IGeneratesDomainEvents { - private readonly ICollection _domainEvents = new Collection(); + private readonly ICollection _localEvents = new Collection(); + private readonly ICollection _distributedEvents = new Collection(); - protected virtual void AddDomainEvent(object eventData) + protected virtual void AddLocalEvent(object eventData) { - _domainEvents.Add(eventData); + _localEvents.Add(eventData); } - public virtual IEnumerable GetDomainEvents() + protected virtual void AddDistributedEvent(object eventData) { - return _domainEvents; + _distributedEvents.Add(eventData); } - public virtual void ClearDomainEvents() + public virtual IEnumerable GetLocalEvents() { - _domainEvents.Clear(); + return _localEvents; + } + + public IEnumerable GetDistributedEvents() + { + return _distributedEvents; + } + + public virtual void ClearLocalEvents() + { + _localEvents.Clear(); + } + + public void ClearDistributedEvents() + { + _distributedEvents.Clear(); } } [Serializable] public abstract class AggregateRoot : Entity, IAggregateRoot, IGeneratesDomainEvents { - private readonly ICollection _domainEvents = new Collection(); + private readonly ICollection _localEvents = new Collection(); + private readonly ICollection _distributedEvents = new Collection(); protected AggregateRoot() { @@ -41,19 +58,34 @@ namespace Volo.Abp.Domain.Entities } - protected virtual void AddDomainEvent(object eventData) + protected virtual void AddLocalEvent(object eventData) + { + _localEvents.Add(eventData); + } + + protected virtual void AddDistributedEvent(object eventData) + { + _distributedEvents.Add(eventData); + } + + public virtual IEnumerable GetLocalEvents() + { + return _localEvents; + } + + public IEnumerable GetDistributedEvents() { - _domainEvents.Add(eventData); + return _distributedEvents; } - public virtual IEnumerable GetDomainEvents() + public virtual void ClearLocalEvents() { - return _domainEvents; + _localEvents.Clear(); } - public virtual void ClearDomainEvents() + public void ClearDistributedEvents() { - _domainEvents.Clear(); + _distributedEvents.Clear(); } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/EntityChangeEventHelper.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/EntityChangeEventHelper.cs index 6d5c03d4e1..b236e6f7e4 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/EntityChangeEventHelper.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/EntityChangeEventHelper.cs @@ -82,7 +82,8 @@ namespace Volo.Abp.Domain.Entities.Events protected virtual async Task TriggerEventsInternalAsync(EntityChangeReport changeReport) { await TriggerEntityChangeEvents(changeReport.ChangedEntities); - await TriggerDomainEvents(changeReport.DomainEvents); + await TriggerLocalEvents(changeReport.DomainEvents); + await TriggerDistributedEvents(changeReport.DistributedEvents); } protected virtual async Task TriggerEntityChangeEvents(List changedEntities) @@ -109,11 +110,19 @@ namespace Volo.Abp.Domain.Entities.Events } } - protected virtual async Task TriggerDomainEvents(List domainEvents) + protected virtual async Task TriggerLocalEvents(List localEvents) { - foreach (var domainEvent in domainEvents) + foreach (var localEvent in localEvents) { - await LocalEventBus.PublishAsync(domainEvent.EventData.GetType(), domainEvent.EventData); + await LocalEventBus.PublishAsync(localEvent.EventData.GetType(), localEvent.EventData); + } + } + + protected virtual async Task TriggerDistributedEvents(List distributedEvents) + { + foreach (var distributedEvent in distributedEvents) + { + await DistributedEventBus.PublishAsync(distributedEvent.EventData.GetType(), distributedEvent.EventData); } } diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/EntityChangeReport.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/EntityChangeReport.cs index 1a89eb193e..921de844c7 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/EntityChangeReport.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/EntityChangeReport.cs @@ -8,20 +8,25 @@ namespace Volo.Abp.Domain.Entities.Events public List DomainEvents { get; } + public List DistributedEvents { get; } + public EntityChangeReport() { ChangedEntities = new List(); DomainEvents = new List(); + DistributedEvents = new List(); } public bool IsEmpty() { - return ChangedEntities.Count <= 0 && DomainEvents.Count <= 0; + return ChangedEntities.Count <= 0 && + DomainEvents.Count <= 0 && + DistributedEvents.Count <= 0; } public override string ToString() { - return $"[EntityChangeReport] ChangedEntities: {ChangedEntities.Count}, DomainEvents: {DomainEvents.Count}"; + return $"[EntityChangeReport] ChangedEntities: {ChangedEntities.Count}, DomainEvents: {DomainEvents.Count}, DistributedEvents: {DistributedEvents.Count}"; } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/IGeneratesDomainEvents.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/IGeneratesDomainEvents.cs index d266206b90..5d0d5c7959 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/IGeneratesDomainEvents.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/IGeneratesDomainEvents.cs @@ -6,8 +6,12 @@ namespace Volo.Abp.Domain.Entities public interface IGeneratesDomainEvents { - IEnumerable GetDomainEvents(); + IEnumerable GetLocalEvents(); - void ClearDomainEvents(); + IEnumerable GetDistributedEvents(); + + void ClearLocalEvents(); + + void ClearDistributedEvents(); } } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs index 42afbb5183..87c9ec6153 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs @@ -203,7 +203,7 @@ namespace Volo.Abp.EntityFrameworkCore break; } - AddDomainEvents(changeReport.DomainEvents, entry.Entity); + AddDomainEvents(changeReport, entry.Entity); } protected virtual void ApplyAbpConceptsForAddedEntity(EntityEntry entry, EntityChangeReport changeReport) @@ -237,7 +237,7 @@ namespace Volo.Abp.EntityFrameworkCore changeReport.ChangedEntities.Add(new EntityChangeEntry(entry.Entity, EntityChangeType.Deleted)); } - protected virtual void AddDomainEvents(List domainEvents, object entityAsObj) + protected virtual void AddDomainEvents(EntityChangeReport changeReport, object entityAsObj) { var generatesDomainEventsEntity = entityAsObj as IGeneratesDomainEvents; if (generatesDomainEventsEntity == null) @@ -245,14 +245,19 @@ namespace Volo.Abp.EntityFrameworkCore return; } - var entityEvents = generatesDomainEventsEntity.GetDomainEvents().ToArray(); - if (entityEvents.IsNullOrEmpty()) + var localEvents = generatesDomainEventsEntity.GetLocalEvents().ToArray(); + if (localEvents.Any()) { - return; + changeReport.DomainEvents.AddRange(localEvents.Select(eventData => new DomainEventEntry(entityAsObj, eventData))); + generatesDomainEventsEntity.ClearLocalEvents(); } - domainEvents.AddRange(entityEvents.Select(eventData => new DomainEventEntry(entityAsObj, eventData))); - generatesDomainEventsEntity.ClearDomainEvents(); + var distributedEvents = generatesDomainEventsEntity.GetDistributedEvents().ToArray(); + if (distributedEvents.Any()) + { + changeReport.DistributedEvents.AddRange(distributedEvents.Select(eventData => new DomainEventEntry(entityAsObj, eventData))); + generatesDomainEventsEntity.ClearDistributedEvents(); + } } protected virtual void HandleConcurrencyStamp(EntityEntry entry) diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs index 17bc43ad14..f5170210bd 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs @@ -10,6 +10,7 @@ using Volo.Abp.Auditing; using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Entities.Events; using Volo.Abp.EventBus; +using Volo.Abp.EventBus.Distributed; using Volo.Abp.EventBus.Local; using Volo.Abp.Guids; using Volo.Abp.MongoDB; @@ -34,6 +35,8 @@ namespace Volo.Abp.Domain.Repositories.MongoDB public ILocalEventBus LocalEventBus { get; set; } + public IDistributedEventBus DistributedEventBus { get; set; } + public IEntityChangeEventHelper EntityChangeEventHelper { get; set; } public IGuidGenerator GuidGenerator { get; set; } @@ -45,6 +48,7 @@ namespace Volo.Abp.Domain.Repositories.MongoDB DbContextProvider = dbContextProvider; LocalEventBus = NullLocalEventBus.Instance; + DistributedEventBus = NullDistributedEventBus.Instance; EntityChangeEventHelper = NullEntityChangeEventHelper.Instance; } @@ -306,18 +310,27 @@ namespace Volo.Abp.Domain.Repositories.MongoDB return; } - var entityEvents = generatesDomainEventsEntity.GetDomainEvents().ToArray(); - if (entityEvents.IsNullOrEmpty()) + var localEvents = generatesDomainEventsEntity.GetLocalEvents().ToArray(); + if (localEvents.Any()) { - return; + foreach (var localEvent in localEvents) + { + await LocalEventBus.PublishAsync(localEvent.GetType(), localEvent); + } + + generatesDomainEventsEntity.ClearLocalEvents(); } - foreach (var entityEvent in entityEvents) + var distributedEvents = generatesDomainEventsEntity.GetDistributedEvents().ToArray(); + if (distributedEvents.Any()) { - await LocalEventBus.PublishAsync(entityEvent.GetType(), entityEvent); - } + foreach (var distributedEvent in distributedEvents) + { + await DistributedEventBus.PublishAsync(distributedEvent.GetType(), distributedEvent); + } - generatesDomainEventsEntity.ClearDomainEvents(); + generatesDomainEventsEntity.ClearDistributedEvents(); + } } } diff --git a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/Person.cs b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/Person.cs index 3600ceaeeb..8235225def 100644 --- a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/Person.cs +++ b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/Person.cs @@ -41,7 +41,24 @@ namespace Volo.Abp.TestApp.Domain var oldName = Name; Name = name; - AddDomainEvent(new PersonNameChangedEvent{Person = this, OldName = oldName}); + + AddLocalEvent( + new PersonNameChangedEvent + { + Person = this, + OldName = oldName + } + ); + + AddDistributedEvent( + new PersonNameChangedEto + { + Id = Id, + OldName = oldName, + NewName = Name, + TenantId = TenantId + } + ); } } } \ No newline at end of file diff --git a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/PersonNameChangedEto.cs b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/PersonNameChangedEto.cs new file mode 100644 index 0000000000..638d657142 --- /dev/null +++ b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/PersonNameChangedEto.cs @@ -0,0 +1,15 @@ +using System; + +namespace Volo.Abp.TestApp.Domain +{ + public class PersonNameChangedEto + { + public virtual Guid Id { get; set; } + + public virtual Guid? TenantId { get; set; } + + public string OldName { get; set; } + + public string NewName { get; set; } + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/DomainEvents_Tests.cs b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/DomainEvents_Tests.cs index ed62e14ecd..3ca7eaf8e4 100644 --- a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/DomainEvents_Tests.cs +++ b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/DomainEvents_Tests.cs @@ -3,7 +3,7 @@ using System.Linq; using System.Threading.Tasks; using Shouldly; using Volo.Abp.Domain.Repositories; -using Volo.Abp.EventBus; +using Volo.Abp.EventBus.Distributed; using Volo.Abp.EventBus.Local; using Volo.Abp.Modularity; using Volo.Abp.TestApp.Domain; @@ -16,11 +16,13 @@ namespace Volo.Abp.TestApp.Testing { protected readonly IRepository PersonRepository; protected readonly ILocalEventBus LocalEventBus; + protected readonly IDistributedEventBus DistributedEventBus; protected DomainEvents_Tests() { PersonRepository = GetRequiredService>(); LocalEventBus = GetRequiredService(); + DistributedEventBus = GetRequiredService(); } [Fact] @@ -28,13 +30,22 @@ namespace Volo.Abp.TestApp.Testing { //Arrange - var isTriggered = false; + var isLocalEventTriggered = false; + var isDistributedEventTriggered = false; LocalEventBus.Subscribe(data => { data.OldName.ShouldBe("Douglas"); data.Person.Name.ShouldBe("Douglas-Changed"); - isTriggered = true; + isLocalEventTriggered = true; + return Task.CompletedTask; + }); + + DistributedEventBus.Subscribe(data => + { + data.OldName.ShouldBe("Douglas"); + data.NewName.ShouldBe("Douglas-Changed"); + isDistributedEventTriggered = true; return Task.CompletedTask; }); @@ -49,7 +60,8 @@ namespace Volo.Abp.TestApp.Testing //Assert - isTriggered.ShouldBeTrue(); + isLocalEventTriggered.ShouldBeTrue(); + isDistributedEventTriggered.ShouldBeTrue(); } } } \ No newline at end of file