From 616258197e95019ed76a2b37050b430bcf6e7e53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Tue, 7 Sep 2021 17:05:50 +0300 Subject: [PATCH 01/36] Added outbox parameter and dbcontext abstraction --- .../Abp/EntityFrameworkCore/AbpDbContext.cs | 2 +- ...ntOutboxDbContextModelBuilderExtensions.cs | 21 ++++++ .../DistributedEvents/IHasEventOutbox.cs | 9 +++ .../DistributedEvents/OutgoingEventRecord.cs | 29 ++++++++ .../Kafka/KafkaDistributedEventBus.cs | 25 ++++--- .../RabbitMq/RabbitMqDistributedEventBus.cs | 7 +- .../Rebus/RebusDistributedEventBus.cs | 7 +- .../Distributed/DistributedEventBusBase.cs | 69 +++++++++++++++++++ .../Distributed/IDistributedEventBus.cs | 13 ++++ .../Distributed/LocalDistributedEventBus.cs | 10 +++ .../Distributed/NullDistributedEventBus.cs | 10 +++ .../Volo/Abp/EventBus/EventBusBase.cs | 8 ++- .../Abp/EventBus/UnitOfWorkEventPublisher.cs | 13 +++- .../MemoryDb/MemoryDbRepository.cs | 3 +- .../Repositories/MongoDB/MongoDbRepository.cs | 3 +- .../Volo/Abp/Uow/UnitOfWorkEventRecord.cs | 6 +- 16 files changed, 207 insertions(+), 28 deletions(-) create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/EventOutboxDbContextModelBuilderExtensions.cs create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IHasEventOutbox.cs create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/OutgoingEventRecord.cs create mode 100644 framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs 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 b86f9b83b1..1fd8273e67 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs @@ -201,7 +201,7 @@ namespace Volo.Abp.EntityFrameworkCore foreach (var distributedEvent in changeReport.DistributedEvents) { UnitOfWorkManager.Current?.AddOrReplaceDistributedEvent( - new UnitOfWorkEventRecord(distributedEvent.EventData.GetType(), distributedEvent.EventData, distributedEvent.EventOrder) + new UnitOfWorkEventRecord(distributedEvent.EventData.GetType(), distributedEvent.EventData, distributedEvent.EventOrder, useOutbox: true) ); } } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/EventOutboxDbContextModelBuilderExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/EventOutboxDbContextModelBuilderExtensions.cs new file mode 100644 index 0000000000..5443968343 --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/EventOutboxDbContextModelBuilderExtensions.cs @@ -0,0 +1,21 @@ +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore; +using Volo.Abp.Data; +using Volo.Abp.EntityFrameworkCore.Modeling; + +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public static class EventOutboxDbContextModelBuilderExtensions + { + public static void ConfigureEventOutbox([NotNull] this ModelBuilder builder) + { + builder.Entity(b => + { + b.ToTable(AbpCommonDbProperties.DbTablePrefix + "EventOutbox", AbpCommonDbProperties.DbSchema); + b.ConfigureByConvention(); + b.Property(x => x.EventName).IsRequired().HasMaxLength(OutgoingEventRecord.MaxEventNameLength); + b.Property(x => x.EventData).IsRequired(); + }); + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IHasEventOutbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IHasEventOutbox.cs new file mode 100644 index 0000000000..34c712c1a1 --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IHasEventOutbox.cs @@ -0,0 +1,9 @@ +using Microsoft.EntityFrameworkCore; + +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public interface IHasEventOutbox + { + DbSet OutgoingEventRecords { get; set; } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/OutgoingEventRecord.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/OutgoingEventRecord.cs new file mode 100644 index 0000000000..9ebee6894a --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/OutgoingEventRecord.cs @@ -0,0 +1,29 @@ +using System; +using Volo.Abp.Data; +using Volo.Abp.Domain.Entities; + +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public class OutgoingEventRecord : BasicAggregateRoot, IHasExtraProperties + { + public static int MaxEventNameLength { get; set; } = 256; + + public ExtraPropertyDictionary ExtraProperties { get; protected set; } + + public string EventName { get; set; } + public byte[] EventData { get; set; } + + protected OutgoingEventRecord() + { + ExtraProperties = new ExtraPropertyDictionary(); + this.SetDefaultsForExtraProperties(); + } + + public OutgoingEventRecord(Guid id) + : base(id) + { + ExtraProperties = new ExtraPropertyDictionary(); + this.SetDefaultsForExtraProperties(); + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs b/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs index 0be3a326b6..c3050adb3b 100644 --- a/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs +++ b/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs @@ -18,7 +18,7 @@ namespace Volo.Abp.EventBus.Kafka { [Dependency(ReplaceServices = true)] [ExposeServices(typeof(IDistributedEventBus), typeof(KafkaDistributedEventBus))] - public class KafkaDistributedEventBus : EventBusBase, IDistributedEventBus, ISingletonDependency + public class KafkaDistributedEventBus : DistributedEventBusBase, ISingletonDependency { protected AbpEventBusOptions AbpEventBusOptions { get; } protected AbpKafkaEventBusOptions AbpKafkaEventBusOptions { get; } @@ -94,11 +94,6 @@ namespace Volo.Abp.EventBus.Kafka }); } - public IDisposable Subscribe(IDistributedEventHandler handler) where TEvent : class - { - return Subscribe(typeof(TEvent), handler); - } - public override IDisposable Subscribe(Type eventType, IEventHandlerFactory factory) { var handlerFactories = GetOrCreateHandlerFactories(eventType); @@ -169,7 +164,15 @@ namespace Volo.Abp.EventBus.Kafka protected override async Task PublishToEventBusAsync(Type eventType, object eventData) { - await PublishAsync(eventType, eventData, new Headers {{"messageId", Serializer.Serialize(Guid.NewGuid())}}, null); + await PublishAsync( + eventType, + eventData, + new Headers + { + { "messageId", Serializer.Serialize(Guid.NewGuid()) } + }, + null + ); } protected override void AddToUnitOfWork(IUnitOfWork unitOfWork, UnitOfWorkEventRecord eventRecord) @@ -179,7 +182,13 @@ namespace Volo.Abp.EventBus.Kafka public virtual async Task PublishAsync(Type eventType, object eventData, Headers headers, Dictionary headersArguments) { - await PublishAsync(AbpKafkaEventBusOptions.TopicName, eventType, eventData, headers, headersArguments); + await PublishAsync( + AbpKafkaEventBusOptions.TopicName, + eventType, + eventData, + headers, + headersArguments + ); } public virtual async Task PublishToDeadLetterAsync(Type eventType, object eventData, Headers headers, Dictionary headersArguments) diff --git a/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs b/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs index f5e3682a7a..9891b5cf12 100644 --- a/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs +++ b/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs @@ -23,7 +23,7 @@ namespace Volo.Abp.EventBus.RabbitMq */ [Dependency(ReplaceServices = true)] [ExposeServices(typeof(IDistributedEventBus), typeof(RabbitMqDistributedEventBus))] - public class RabbitMqDistributedEventBus : EventBusBase, IDistributedEventBus, ISingletonDependency + public class RabbitMqDistributedEventBus : DistributedEventBusBase, ISingletonDependency { protected AbpRabbitMqEventBusOptions AbpRabbitMqEventBusOptions { get; } protected AbpDistributedEventBusOptions AbpDistributedEventBusOptions { get; } @@ -113,11 +113,6 @@ namespace Volo.Abp.EventBus.RabbitMq }); } - public IDisposable Subscribe(IDistributedEventHandler handler) where TEvent : class - { - return Subscribe(typeof(TEvent), handler); - } - public override IDisposable Subscribe(Type eventType, IEventHandlerFactory factory) { var handlerFactories = GetOrCreateHandlerFactories(eventType); diff --git a/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventBus.cs b/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventBus.cs index 0206b5fefc..3f07cf7150 100644 --- a/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventBus.cs +++ b/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventBus.cs @@ -16,7 +16,7 @@ namespace Volo.Abp.EventBus.Rebus { [Dependency(ReplaceServices = true)] [ExposeServices(typeof(IDistributedEventBus), typeof(RebusDistributedEventBus))] - public class RebusDistributedEventBus : EventBusBase, IDistributedEventBus, ISingletonDependency + public class RebusDistributedEventBus : DistributedEventBusBase, ISingletonDependency { protected IBus Rebus { get; } @@ -122,11 +122,6 @@ namespace Volo.Abp.EventBus.Rebus Rebus.Unsubscribe(eventType); } - public IDisposable Subscribe(IDistributedEventHandler handler) where TEvent : class - { - return Subscribe(typeof(TEvent), handler); - } - protected override async Task PublishToEventBusAsync(Type eventType, object eventData) { await AbpRebusEventBusOptions.Publish(Rebus, eventType, eventData); diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs new file mode 100644 index 0000000000..94176d9f50 --- /dev/null +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs @@ -0,0 +1,69 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.MultiTenancy; +using Volo.Abp.Uow; + +namespace Volo.Abp.EventBus.Distributed +{ + public abstract class DistributedEventBusBase : EventBusBase, IDistributedEventBus + { + protected DistributedEventBusBase( + IServiceScopeFactory serviceScopeFactory, + ICurrentTenant currentTenant, + IUnitOfWorkManager unitOfWorkManager, + IEventErrorHandler errorHandler + ) : base( + serviceScopeFactory, + currentTenant, + unitOfWorkManager, + errorHandler) + { + } + + public IDisposable Subscribe(IDistributedEventHandler handler) where TEvent : class + { + return Subscribe(typeof(TEvent), handler); + } + + public Task PublishAsync( + TEvent eventData, + bool onUnitOfWorkComplete = true, + bool useOutbox = true) + where TEvent : class + { + return PublishAsync(typeof(TEvent), eventData, onUnitOfWorkComplete, useOutbox); + } + + public async Task PublishAsync( + Type eventType, + object eventData, + bool onUnitOfWorkComplete = true, + bool useOutbox = true) + { + if (onUnitOfWorkComplete && UnitOfWorkManager.Current != null) + { + AddToUnitOfWork( + UnitOfWorkManager.Current, + new UnitOfWorkEventRecord(eventType, eventData, EventOrderGenerator.GetNext(), useOutbox) + ); + return; + } + + if (useOutbox) + { + if (await AddToOutboxAsync(eventType, eventData)) + { + return; + } + } + + await PublishToEventBusAsync(eventType, eventData); + } + + private async Task AddToOutboxAsync(Type eventType, object eventData) + { + return false; + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IDistributedEventBus.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IDistributedEventBus.cs index e406f7069b..80af122242 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IDistributedEventBus.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IDistributedEventBus.cs @@ -1,4 +1,5 @@ using System; +using System.Threading.Tasks; namespace Volo.Abp.EventBus.Distributed { @@ -12,5 +13,17 @@ namespace Volo.Abp.EventBus.Distributed /// Object to handle the event IDisposable Subscribe(IDistributedEventHandler handler) where TEvent : class; + + Task PublishAsync( + TEvent eventData, + bool onUnitOfWorkComplete = true, + bool useOutbox = true) + where TEvent : class; + + Task PublishAsync( + Type eventType, + object eventData, + bool onUnitOfWorkComplete = true, + bool useOutbox = true); } } diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/LocalDistributedEventBus.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/LocalDistributedEventBus.cs index 3ee3700a0d..d5dd961802 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/LocalDistributedEventBus.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/LocalDistributedEventBus.cs @@ -132,5 +132,15 @@ namespace Volo.Abp.EventBus.Distributed { return _localEventBus.PublishAsync(eventType, eventData, onUnitOfWorkComplete); } + + public Task PublishAsync(TEvent eventData, bool onUnitOfWorkComplete = true, bool useOutbox = true) where TEvent : class + { + return _localEventBus.PublishAsync(eventData, onUnitOfWorkComplete); + } + + public Task PublishAsync(Type eventType, object eventData, bool onUnitOfWorkComplete = true, bool useOutbox = true) + { + return _localEventBus.PublishAsync(eventType, eventData, onUnitOfWorkComplete); + } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/NullDistributedEventBus.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/NullDistributedEventBus.cs index 60be7a147c..97004fbeac 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/NullDistributedEventBus.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/NullDistributedEventBus.cs @@ -86,5 +86,15 @@ namespace Volo.Abp.EventBus.Distributed { return Task.CompletedTask; } + + public Task PublishAsync(TEvent eventData, bool onUnitOfWorkComplete = true, bool useOutbox = true) where TEvent : class + { + return Task.CompletedTask; + } + + public Task PublishAsync(Type eventType, object eventData, bool onUnitOfWorkComplete = true, bool useOutbox = true) + { + return Task.CompletedTask; + } } } diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventBusBase.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventBusBase.cs index f29a169cb5..a739bf814d 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventBusBase.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventBusBase.cs @@ -92,13 +92,17 @@ namespace Volo.Abp.EventBus public abstract void UnsubscribeAll(Type eventType); /// - public Task PublishAsync(TEvent eventData, bool onUnitOfWorkComplete = true) where TEvent : class + public Task PublishAsync(TEvent eventData, bool onUnitOfWorkComplete = true) + where TEvent : class { return PublishAsync(typeof(TEvent), eventData, onUnitOfWorkComplete); } /// - public async Task PublishAsync(Type eventType, object eventData, bool onUnitOfWorkComplete = true) + public async Task PublishAsync( + Type eventType, + object eventData, + bool onUnitOfWorkComplete = true) { if (onUnitOfWorkComplete && UnitOfWorkManager.Current != null) { diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/UnitOfWorkEventPublisher.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/UnitOfWorkEventPublisher.cs index 65e271afa8..ea6a66a699 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/UnitOfWorkEventPublisher.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/UnitOfWorkEventPublisher.cs @@ -25,7 +25,11 @@ namespace Volo.Abp.EventBus { foreach (var localEvent in localEvents) { - await _localEventBus.PublishAsync(localEvent.EventType, localEvent.EventData, onUnitOfWorkComplete: false); + await _localEventBus.PublishAsync( + localEvent.EventType, + localEvent.EventData, + onUnitOfWorkComplete: false + ); } } @@ -33,7 +37,12 @@ namespace Volo.Abp.EventBus { foreach (var distributedEvent in distributedEvents) { - await _distributedEventBus.PublishAsync(distributedEvent.EventType, distributedEvent.EventData, onUnitOfWorkComplete: false); + await _distributedEventBus.PublishAsync( + distributedEvent.EventType, + distributedEvent.EventData, + onUnitOfWorkComplete: false, + useOutbox: distributedEvent.UseOutbox + ); } } } diff --git a/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDbRepository.cs b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDbRepository.cs index cf3479de67..3193e15ad1 100644 --- a/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDbRepository.cs +++ b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDbRepository.cs @@ -100,7 +100,8 @@ namespace Volo.Abp.Domain.Repositories.MemoryDb new UnitOfWorkEventRecord( distributedEvent.EventData.GetType(), distributedEvent.EventData, - distributedEvent.EventOrder + distributedEvent.EventOrder, + useOutbox: true ) ); } 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 a40117e0ff..db8448db23 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 @@ -674,7 +674,8 @@ namespace Volo.Abp.Domain.Repositories.MongoDB new UnitOfWorkEventRecord( distributedEvent.EventData.GetType(), distributedEvent.EventData, - distributedEvent.EventOrder + distributedEvent.EventOrder, + useOutbox: true ) ); } diff --git a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkEventRecord.cs b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkEventRecord.cs index 11ae4920cd..dd917d6fe2 100644 --- a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkEventRecord.cs +++ b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkEventRecord.cs @@ -11,6 +11,8 @@ namespace Volo.Abp.Uow public long EventOrder { get; } + public bool UseOutbox { get; } + /// /// Extra properties can be used if needed. /// @@ -19,11 +21,13 @@ namespace Volo.Abp.Uow public UnitOfWorkEventRecord( Type eventType, object eventData, - long eventOrder) + long eventOrder, + bool useOutbox = false) { EventType = eventType; EventData = eventData; EventOrder = eventOrder; + UseOutbox = useOutbox; } } } \ No newline at end of file From 5f50d3323ab99e8a048f274e3a4ab91ae08135fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Tue, 7 Sep 2021 17:11:42 +0300 Subject: [PATCH 02/36] Add AbpDistributedEventBusOptions to DistributedEventBusBase --- .../Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs | 9 ++++++--- .../Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs | 9 ++++++--- .../Volo/Abp/EventBus/Rebus/RebusDistributedEventBus.cs | 9 ++++++--- .../Distributed/AbpDistributedEventBusOptions.cs | 8 ++++++++ .../Abp/EventBus/Distributed/DistributedEventBusBase.cs | 7 ++++++- 5 files changed, 32 insertions(+), 10 deletions(-) diff --git a/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs b/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs index c3050adb3b..b2d099286a 100644 --- a/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs +++ b/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs @@ -22,7 +22,6 @@ namespace Volo.Abp.EventBus.Kafka { protected AbpEventBusOptions AbpEventBusOptions { get; } protected AbpKafkaEventBusOptions AbpKafkaEventBusOptions { get; } - protected AbpDistributedEventBusOptions AbpDistributedEventBusOptions { get; } protected IKafkaMessageConsumerFactory MessageConsumerFactory { get; } protected IKafkaSerializer Serializer { get; } protected IProducerPool ProducerPool { get; } @@ -42,10 +41,14 @@ namespace Volo.Abp.EventBus.Kafka IProducerPool producerPool, IEventErrorHandler errorHandler, IOptions abpEventBusOptions) - : base(serviceScopeFactory, currentTenant, unitOfWorkManager, errorHandler) + : base( + serviceScopeFactory, + currentTenant, + unitOfWorkManager, + errorHandler, + abpDistributedEventBusOptions) { AbpKafkaEventBusOptions = abpKafkaEventBusOptions.Value; - AbpDistributedEventBusOptions = abpDistributedEventBusOptions.Value; AbpEventBusOptions = abpEventBusOptions.Value; MessageConsumerFactory = messageConsumerFactory; Serializer = serializer; diff --git a/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs b/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs index 9891b5cf12..471bcacad6 100644 --- a/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs +++ b/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs @@ -26,7 +26,6 @@ namespace Volo.Abp.EventBus.RabbitMq public class RabbitMqDistributedEventBus : DistributedEventBusBase, ISingletonDependency { protected AbpRabbitMqEventBusOptions AbpRabbitMqEventBusOptions { get; } - protected AbpDistributedEventBusOptions AbpDistributedEventBusOptions { get; } protected AbpEventBusOptions AbpEventBusOptions { get; } protected IConnectionPool ConnectionPool { get; } protected IRabbitMqSerializer Serializer { get; } @@ -48,13 +47,17 @@ namespace Volo.Abp.EventBus.RabbitMq IUnitOfWorkManager unitOfWorkManager, IEventErrorHandler errorHandler, IOptions abpEventBusOptions) - : base(serviceScopeFactory, currentTenant, unitOfWorkManager, errorHandler) + : base( + serviceScopeFactory, + currentTenant, + unitOfWorkManager, + errorHandler, + distributedEventBusOptions) { ConnectionPool = connectionPool; Serializer = serializer; MessageConsumerFactory = messageConsumerFactory; AbpEventBusOptions = abpEventBusOptions.Value; - AbpDistributedEventBusOptions = distributedEventBusOptions.Value; AbpRabbitMqEventBusOptions = options.Value; HandlerFactories = new ConcurrentDictionary>(); diff --git a/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventBus.cs b/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventBus.cs index 3f07cf7150..760af619f5 100644 --- a/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventBus.cs +++ b/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventBus.cs @@ -23,7 +23,6 @@ namespace Volo.Abp.EventBus.Rebus //TODO: Accessing to the List may not be thread-safe! protected ConcurrentDictionary> HandlerFactories { get; } protected ConcurrentDictionary EventTypes { get; } - protected AbpDistributedEventBusOptions AbpDistributedEventBusOptions { get; } protected AbpRebusEventBusOptions AbpRebusEventBusOptions { get; } public RebusDistributedEventBus( @@ -34,11 +33,15 @@ namespace Volo.Abp.EventBus.Rebus IOptions abpDistributedEventBusOptions, IOptions abpEventBusRebusOptions, IEventErrorHandler errorHandler) : - base(serviceScopeFactory, currentTenant, unitOfWorkManager, errorHandler) + base( + serviceScopeFactory, + currentTenant, + unitOfWorkManager, + errorHandler, + abpDistributedEventBusOptions) { Rebus = rebus; AbpRebusEventBusOptions = abpEventBusRebusOptions.Value; - AbpDistributedEventBusOptions = abpDistributedEventBusOptions.Value; HandlerFactories = new ConcurrentDictionary>(); EventTypes = new ConcurrentDictionary(); diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/AbpDistributedEventBusOptions.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/AbpDistributedEventBusOptions.cs index 342e7b77bb..2d3861da73 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/AbpDistributedEventBusOptions.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/AbpDistributedEventBusOptions.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using Volo.Abp.Collections; namespace Volo.Abp.EventBus.Distributed @@ -5,10 +6,17 @@ namespace Volo.Abp.EventBus.Distributed public class AbpDistributedEventBusOptions { public ITypeList Handlers { get; } + + public List Outboxes { get; } public AbpDistributedEventBusOptions() { Handlers = new TypeList(); } } + + public class OutboxConfig + { + + } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs index 94176d9f50..541373cd13 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs @@ -1,6 +1,7 @@ using System; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using Volo.Abp.MultiTenancy; using Volo.Abp.Uow; @@ -8,17 +9,21 @@ namespace Volo.Abp.EventBus.Distributed { public abstract class DistributedEventBusBase : EventBusBase, IDistributedEventBus { + protected AbpDistributedEventBusOptions AbpDistributedEventBusOptions { get; } + protected DistributedEventBusBase( IServiceScopeFactory serviceScopeFactory, ICurrentTenant currentTenant, IUnitOfWorkManager unitOfWorkManager, - IEventErrorHandler errorHandler + IEventErrorHandler errorHandler, + IOptions abpDistributedEventBusOptions ) : base( serviceScopeFactory, currentTenant, unitOfWorkManager, errorHandler) { + AbpDistributedEventBusOptions = abpDistributedEventBusOptions.Value; } public IDisposable Subscribe(IDistributedEventHandler handler) where TEvent : class From d1ea4736b7aa1ab93e8f001b01cf42061f70a2c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 8 Sep 2021 10:37:15 +0300 Subject: [PATCH 03/36] save to outbox --- .../Abp/EntityFrameworkCore/AbpDbContext.cs | 2 +- .../AbpEntityFrameworkCoreModule.cs | 2 + .../DistributedEvents/DbContextEventOutbox.cs | 29 +++++ .../DistributedEvents/IHasEventOutbox.cs | 2 +- .../DistributedEvents/OutgoingEventRecord.cs | 5 +- .../Kafka/KafkaDistributedEventBus.cs | 5 + .../RabbitMq/RabbitMqDistributedEventBus.cs | 5 + .../Abp/EventBus/Rebus/IRabbitMqSerializer.cs | 13 ++ .../Rebus/RebusDistributedEventBus.cs | 10 +- .../Rebus/Utf8JsonRabbitMqSerializer.cs | 32 +++++ .../AbpDistributedEventBusOptions.cs | 9 +- .../Distributed/DistributedEventBusBase.cs | 28 +++++ .../Abp/EventBus/Distributed/IEventOutbox.cs | 9 ++ .../Abp/EventBus/Distributed/OutboxConfig.cs | 18 +++ .../EventBus/Distributed/OutboxConfigList.cs | 8 ++ .../Volo/Abp/EventBus/EventBusBase.cs | 2 +- .../Repositories/MongoDB/MongoDbRepository.cs | 3 +- .../Volo/Abp/Uow/UnitOfWorkEventRecord.cs | 2 +- .../DistEvents/DistDemoApp/DistDemoApp.csproj | 1 + .../DistDemoApp/DistDemoAppModule.cs | 13 +- .../20210908063422_Added_Outbox.Designer.cs | 118 ++++++++++++++++++ .../Migrations/20210908063422_Added_Outbox.cs | 31 +++++ .../Migrations/TodoDbContextModelSnapshot.cs | 23 ++++ test/DistEvents/DistDemoApp/TodoDbContext.cs | 6 +- .../DistDemoApp/TodoEventHandler.cs | 2 +- test/DistEvents/DistDemoApp/appsettings.json | 11 ++ 26 files changed, 371 insertions(+), 18 deletions(-) create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventOutbox.cs create mode 100644 framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/IRabbitMqSerializer.cs create mode 100644 framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/Utf8JsonRabbitMqSerializer.cs create mode 100644 framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IEventOutbox.cs create mode 100644 framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/OutboxConfig.cs create mode 100644 framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/OutboxConfigList.cs create mode 100644 test/DistEvents/DistDemoApp/Migrations/20210908063422_Added_Outbox.Designer.cs create mode 100644 test/DistEvents/DistDemoApp/Migrations/20210908063422_Added_Outbox.cs 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 1fd8273e67..b86f9b83b1 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs @@ -201,7 +201,7 @@ namespace Volo.Abp.EntityFrameworkCore foreach (var distributedEvent in changeReport.DistributedEvents) { UnitOfWorkManager.Current?.AddOrReplaceDistributedEvent( - new UnitOfWorkEventRecord(distributedEvent.EventData.GetType(), distributedEvent.EventData, distributedEvent.EventOrder, useOutbox: true) + new UnitOfWorkEventRecord(distributedEvent.EventData.GetType(), distributedEvent.EventData, distributedEvent.EventOrder) ); } } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreModule.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreModule.cs index b5d9eb8436..1378f955e4 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreModule.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreModule.cs @@ -3,6 +3,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Volo.Abp.Domain; using Volo.Abp.EntityFrameworkCore.DependencyInjection; +using Volo.Abp.EntityFrameworkCore.DistributedEvents; using Volo.Abp.Modularity; using Volo.Abp.Uow.EntityFrameworkCore; @@ -26,6 +27,7 @@ namespace Volo.Abp.EntityFrameworkCore }); context.Services.TryAddTransient(typeof(IDbContextProvider<>), typeof(UnitOfWorkDbContextProvider<>)); + context.Services.AddTransient(typeof(DbContextEventOutbox<>)); } } } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventOutbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventOutbox.cs new file mode 100644 index 0000000000..1831b67ccb --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventOutbox.cs @@ -0,0 +1,29 @@ +using System.Threading.Tasks; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.Guids; + +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public class DbContextEventOutbox : IEventOutbox + where TDbContext : IHasEventOutbox + { + protected IDbContextProvider DbContextProvider { get; } + protected IGuidGenerator GuidGenerator { get; } + + public DbContextEventOutbox( + IDbContextProvider dbContextProvider, + IGuidGenerator guidGenerator) + { + DbContextProvider = dbContextProvider; + GuidGenerator = guidGenerator; + } + + public async Task EnqueueAsync(string eventName, byte[] eventData) + { + var dbContext = (IHasEventOutbox) await DbContextProvider.GetDbContextAsync(); + dbContext.OutgoingEventRecords.Add( + new OutgoingEventRecord(GuidGenerator.Create(), eventName, eventData) + ); + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IHasEventOutbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IHasEventOutbox.cs index 34c712c1a1..e7e60e3800 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IHasEventOutbox.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IHasEventOutbox.cs @@ -2,7 +2,7 @@ using Microsoft.EntityFrameworkCore; namespace Volo.Abp.EntityFrameworkCore.DistributedEvents { - public interface IHasEventOutbox + public interface IHasEventOutbox : IEfCoreDbContext { DbSet OutgoingEventRecords { get; set; } } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/OutgoingEventRecord.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/OutgoingEventRecord.cs index 9ebee6894a..395970c4a9 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/OutgoingEventRecord.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/OutgoingEventRecord.cs @@ -19,9 +19,12 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents this.SetDefaultsForExtraProperties(); } - public OutgoingEventRecord(Guid id) + public OutgoingEventRecord(Guid id, string eventName, byte[] eventData) : base(id) { + EventName = eventName; + EventData = eventData; + ExtraProperties = new ExtraPropertyDictionary(); this.SetDefaultsForExtraProperties(); } diff --git a/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs b/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs index b2d099286a..18f68923e1 100644 --- a/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs +++ b/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs @@ -182,6 +182,11 @@ namespace Volo.Abp.EventBus.Kafka { unitOfWork.AddOrReplaceDistributedEvent(eventRecord); } + + protected override byte[] Serialize(object eventData) + { + return Serializer.Serialize(eventData); + } public virtual async Task PublishAsync(Type eventType, object eventData, Headers headers, Dictionary headersArguments) { diff --git a/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs b/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs index 471bcacad6..d2766eb247 100644 --- a/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs +++ b/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs @@ -198,6 +198,11 @@ namespace Volo.Abp.EventBus.RabbitMq { unitOfWork.AddOrReplaceDistributedEvent(eventRecord); } + + protected override byte[] Serialize(object eventData) + { + return Serializer.Serialize(eventData); + } public Task PublishAsync(Type eventType, object eventData, IBasicProperties properties, Dictionary headersArguments = null) { diff --git a/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/IRabbitMqSerializer.cs b/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/IRabbitMqSerializer.cs new file mode 100644 index 0000000000..68700b4da5 --- /dev/null +++ b/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/IRabbitMqSerializer.cs @@ -0,0 +1,13 @@ +using System; + +namespace Volo.Abp.EventBus.Rebus +{ + public interface IRebusSerializer + { + byte[] Serialize(object obj); + + object Deserialize(byte[] value, Type type); + + T Deserialize(byte[] value); + } +} diff --git a/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventBus.cs b/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventBus.cs index 760af619f5..43017d9c4a 100644 --- a/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventBus.cs +++ b/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventBus.cs @@ -19,6 +19,7 @@ namespace Volo.Abp.EventBus.Rebus public class RebusDistributedEventBus : DistributedEventBusBase, ISingletonDependency { protected IBus Rebus { get; } + protected IRebusSerializer Serializer { get; } //TODO: Accessing to the List may not be thread-safe! protected ConcurrentDictionary> HandlerFactories { get; } @@ -32,7 +33,8 @@ namespace Volo.Abp.EventBus.Rebus IBus rebus, IOptions abpDistributedEventBusOptions, IOptions abpEventBusRebusOptions, - IEventErrorHandler errorHandler) : + IEventErrorHandler errorHandler, + IRebusSerializer serializer) : base( serviceScopeFactory, currentTenant, @@ -41,6 +43,7 @@ namespace Volo.Abp.EventBus.Rebus abpDistributedEventBusOptions) { Rebus = rebus; + Serializer = serializer; AbpRebusEventBusOptions = abpEventBusRebusOptions.Value; HandlerFactories = new ConcurrentDictionary>(); @@ -178,5 +181,10 @@ namespace Volo.Abp.EventBus.Rebus return false; } + + protected override byte[] Serialize(object eventData) + { + return Serializer.Serialize(eventData); + } } } diff --git a/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/Utf8JsonRabbitMqSerializer.cs b/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/Utf8JsonRabbitMqSerializer.cs new file mode 100644 index 0000000000..515e616aab --- /dev/null +++ b/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/Utf8JsonRabbitMqSerializer.cs @@ -0,0 +1,32 @@ +using System; +using System.Text; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Json; + +namespace Volo.Abp.EventBus.Rebus +{ + public class Utf8JsonRebusSerializer : IRebusSerializer, ITransientDependency + { + private readonly IJsonSerializer _jsonSerializer; + + public Utf8JsonRebusSerializer(IJsonSerializer jsonSerializer) + { + _jsonSerializer = jsonSerializer; + } + + public byte[] Serialize(object obj) + { + return Encoding.UTF8.GetBytes(_jsonSerializer.Serialize(obj)); + } + + public object Deserialize(byte[] value, Type type) + { + return _jsonSerializer.Deserialize(type, Encoding.UTF8.GetString(value)); + } + + public T Deserialize(byte[] value) + { + return _jsonSerializer.Deserialize(Encoding.UTF8.GetString(value)); + } + } +} diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/AbpDistributedEventBusOptions.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/AbpDistributedEventBusOptions.cs index 2d3861da73..052e421511 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/AbpDistributedEventBusOptions.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/AbpDistributedEventBusOptions.cs @@ -1,4 +1,3 @@ -using System.Collections.Generic; using Volo.Abp.Collections; namespace Volo.Abp.EventBus.Distributed @@ -7,16 +6,12 @@ namespace Volo.Abp.EventBus.Distributed { public ITypeList Handlers { get; } - public List Outboxes { get; } + public OutboxConfigList Outboxes { get; } public AbpDistributedEventBusOptions() { Handlers = new TypeList(); + Outboxes = new OutboxConfigList(); } } - - public class OutboxConfig - { - - } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs index 541373cd13..bea6b93a36 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; @@ -31,6 +32,11 @@ namespace Volo.Abp.EventBus.Distributed return Subscribe(typeof(TEvent), handler); } + public override Task PublishAsync(Type eventType, object eventData, bool onUnitOfWorkComplete = true) + { + return PublishAsync(eventType, eventData, onUnitOfWorkComplete, useOutbox: true); + } + public Task PublishAsync( TEvent eventData, bool onUnitOfWorkComplete = true, @@ -68,7 +74,29 @@ namespace Volo.Abp.EventBus.Distributed private async Task AddToOutboxAsync(Type eventType, object eventData) { + var unitOfWork = UnitOfWorkManager.Current; + if (unitOfWork == null) + { + return false; + } + + foreach (var outboxConfig in AbpDistributedEventBusOptions.Outboxes) + { + if (outboxConfig.Selector == null || outboxConfig.Selector(eventType)) + { + var eventOutbox = (IEventOutbox)unitOfWork.ServiceProvider.GetRequiredService(outboxConfig.ImplementationType); + var eventName = EventNameAttribute.GetNameOrDefault(eventType); + await eventOutbox.EnqueueAsync( + eventName, + Serialize(eventData) + ); + return true; + } + } + return false; } + + protected abstract byte[] Serialize(object eventData); } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IEventOutbox.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IEventOutbox.cs new file mode 100644 index 0000000000..ec6d010307 --- /dev/null +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IEventOutbox.cs @@ -0,0 +1,9 @@ +using System.Threading.Tasks; + +namespace Volo.Abp.EventBus.Distributed +{ + public interface IEventOutbox + { + Task EnqueueAsync(string eventName, byte[] eventData); + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/OutboxConfig.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/OutboxConfig.cs new file mode 100644 index 0000000000..97712ec85e --- /dev/null +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/OutboxConfig.cs @@ -0,0 +1,18 @@ +using System; + +namespace Volo.Abp.EventBus.Distributed +{ + public class OutboxConfig + { + public string Name { get; } + + public Type ImplementationType { get; set; } + public Func Selector { get; set; } + + public OutboxConfig(string name, Type implementationType, Func selector = null) + { + Name = name; + ImplementationType = implementationType; + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/OutboxConfigList.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/OutboxConfigList.cs new file mode 100644 index 0000000000..47c91377da --- /dev/null +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/OutboxConfigList.cs @@ -0,0 +1,8 @@ +using System.Collections.Generic; + +namespace Volo.Abp.EventBus.Distributed +{ + public class OutboxConfigList : List + { + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventBusBase.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventBusBase.cs index a739bf814d..c8b7eb6790 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventBusBase.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventBusBase.cs @@ -99,7 +99,7 @@ namespace Volo.Abp.EventBus } /// - public async Task PublishAsync( + public virtual async Task PublishAsync( Type eventType, object eventData, bool onUnitOfWorkComplete = true) 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 db8448db23..a40117e0ff 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 @@ -674,8 +674,7 @@ namespace Volo.Abp.Domain.Repositories.MongoDB new UnitOfWorkEventRecord( distributedEvent.EventData.GetType(), distributedEvent.EventData, - distributedEvent.EventOrder, - useOutbox: true + distributedEvent.EventOrder ) ); } diff --git a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkEventRecord.cs b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkEventRecord.cs index dd917d6fe2..cba5646f7a 100644 --- a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkEventRecord.cs +++ b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkEventRecord.cs @@ -22,7 +22,7 @@ namespace Volo.Abp.Uow Type eventType, object eventData, long eventOrder, - bool useOutbox = false) + bool useOutbox = true) { EventType = eventType; EventData = eventData; diff --git a/test/DistEvents/DistDemoApp/DistDemoApp.csproj b/test/DistEvents/DistDemoApp/DistDemoApp.csproj index 9695a92f04..0513a520d1 100644 --- a/test/DistEvents/DistDemoApp/DistDemoApp.csproj +++ b/test/DistEvents/DistDemoApp/DistDemoApp.csproj @@ -16,6 +16,7 @@ + diff --git a/test/DistEvents/DistDemoApp/DistDemoAppModule.cs b/test/DistEvents/DistDemoApp/DistDemoAppModule.cs index f69f9c2380..3cb92b2307 100644 --- a/test/DistEvents/DistDemoApp/DistDemoAppModule.cs +++ b/test/DistEvents/DistDemoApp/DistDemoAppModule.cs @@ -2,14 +2,18 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Autofac; using Volo.Abp.Domain.Entities.Events.Distributed; using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore.DistributedEvents; using Volo.Abp.EntityFrameworkCore.SqlServer; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.EventBus.RabbitMq; using Volo.Abp.Modularity; namespace DistDemoApp { [DependsOn( typeof(AbpEntityFrameworkCoreSqlServerModule), - typeof(AbpAutofacModule) + typeof(AbpAutofacModule), + typeof(AbpEventBusRabbitMqModule) )] public class DistDemoAppModule : AbpModule { @@ -32,6 +36,13 @@ namespace DistDemoApp options.EtoMappings.Add(); options.AutoEventSelectors.Add(); }); + + Configure(options => + { + options.Outboxes.Add( + new OutboxConfig("Default", typeof(DbContextEventOutbox)) + ); + }); } } } \ No newline at end of file diff --git a/test/DistEvents/DistDemoApp/Migrations/20210908063422_Added_Outbox.Designer.cs b/test/DistEvents/DistDemoApp/Migrations/20210908063422_Added_Outbox.Designer.cs new file mode 100644 index 0000000000..9c350598bf --- /dev/null +++ b/test/DistEvents/DistDemoApp/Migrations/20210908063422_Added_Outbox.Designer.cs @@ -0,0 +1,118 @@ +// +using System; +using DistDemoApp; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Volo.Abp.EntityFrameworkCore; + +namespace DistDemoApp.Migrations +{ + [DbContext(typeof(TodoDbContext))] + [Migration("20210908063422_Added_Outbox")] + partial class Added_Outbox + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) + .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("ProductVersion", "5.0.9") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("DistDemoApp.TodoItem", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Text") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.ToTable("TodoItems"); + }); + + modelBuilder.Entity("DistDemoApp.TodoSummary", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Day") + .HasColumnType("tinyint"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Month") + .HasColumnType("tinyint"); + + b.Property("TotalCount") + .HasColumnType("int"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("TodoSummaries"); + }); + + modelBuilder.Entity("Volo.Abp.EntityFrameworkCore.DistributedEvents.OutgoingEventRecord", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("EventData") + .IsRequired() + .HasColumnType("varbinary(max)"); + + b.Property("EventName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.HasKey("Id"); + + b.ToTable("AbpEventOutbox"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/test/DistEvents/DistDemoApp/Migrations/20210908063422_Added_Outbox.cs b/test/DistEvents/DistDemoApp/Migrations/20210908063422_Added_Outbox.cs new file mode 100644 index 0000000000..2954acdac7 --- /dev/null +++ b/test/DistEvents/DistDemoApp/Migrations/20210908063422_Added_Outbox.cs @@ -0,0 +1,31 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace DistDemoApp.Migrations +{ + public partial class Added_Outbox : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "AbpEventOutbox", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true), + EventName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + EventData = table.Column(type: "varbinary(max)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpEventOutbox", x => x.Id); + }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AbpEventOutbox"); + } + } +} diff --git a/test/DistEvents/DistDemoApp/Migrations/TodoDbContextModelSnapshot.cs b/test/DistEvents/DistDemoApp/Migrations/TodoDbContextModelSnapshot.cs index 99f0f92ab7..91d7bc0cc7 100644 --- a/test/DistEvents/DistDemoApp/Migrations/TodoDbContextModelSnapshot.cs +++ b/test/DistEvents/DistDemoApp/Migrations/TodoDbContextModelSnapshot.cs @@ -87,6 +87,29 @@ namespace DistDemoApp.Migrations b.ToTable("TodoSummaries"); }); + + modelBuilder.Entity("Volo.Abp.EntityFrameworkCore.DistributedEvents.OutgoingEventRecord", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("EventData") + .IsRequired() + .HasColumnType("varbinary(max)"); + + b.Property("EventName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.HasKey("Id"); + + b.ToTable("AbpEventOutbox"); + }); #pragma warning restore 612, 618 } } diff --git a/test/DistEvents/DistDemoApp/TodoDbContext.cs b/test/DistEvents/DistDemoApp/TodoDbContext.cs index 000f18c802..3db006535a 100644 --- a/test/DistEvents/DistDemoApp/TodoDbContext.cs +++ b/test/DistEvents/DistDemoApp/TodoDbContext.cs @@ -1,13 +1,15 @@ using Microsoft.EntityFrameworkCore; using Volo.Abp.Domain.Entities; using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore.DistributedEvents; namespace DistDemoApp { - public class TodoDbContext : AbpDbContext + public class TodoDbContext : AbpDbContext, IHasEventOutbox { public DbSet TodoItems { get; set; } public DbSet TodoSummaries { get; set; } + public DbSet OutgoingEventRecords { get; set; } public TodoDbContext(DbContextOptions options) : base(options) @@ -18,6 +20,8 @@ namespace DistDemoApp protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); + + modelBuilder.ConfigureEventOutbox(); modelBuilder.Entity(b => { diff --git a/test/DistEvents/DistDemoApp/TodoEventHandler.cs b/test/DistEvents/DistDemoApp/TodoEventHandler.cs index 73c7040732..c7fd43aea3 100644 --- a/test/DistEvents/DistDemoApp/TodoEventHandler.cs +++ b/test/DistEvents/DistDemoApp/TodoEventHandler.cs @@ -42,7 +42,7 @@ namespace DistDemoApp Console.WriteLine("Increased total count: " + todoSummary); - throw new ApplicationException("Thrown to rollback the UOW!"); + //throw new ApplicationException("Thrown to rollback the UOW!"); } public async Task HandleEventAsync(EntityDeletedEto eventData) diff --git a/test/DistEvents/DistDemoApp/appsettings.json b/test/DistEvents/DistDemoApp/appsettings.json index 6bb7ba54ca..8f4773ae6a 100644 --- a/test/DistEvents/DistDemoApp/appsettings.json +++ b/test/DistEvents/DistDemoApp/appsettings.json @@ -1,5 +1,16 @@ { "ConnectionStrings": { "Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=DistEventsDemo;Trusted_Connection=True" + }, + "RabbitMQ": { + "Connections": { + "Default": { + "HostName": "localhost" + } + }, + "EventBus": { + "ClientName": "DistDemoApp", + "ExchangeName": "DistDemo" + } } } \ No newline at end of file From eb7765ca538c853c609b355e299739ee28837f1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 8 Sep 2021 10:54:17 +0300 Subject: [PATCH 04/36] Refactored configuration, added CreationTime --- .../EfCoreOutboxConfigExtensions.cs | 13 ++ .../DistributedEvents/OutgoingEventRecord.cs | 6 +- .../Distributed/DistributedEventBusBase.cs | 2 +- .../Abp/EventBus/Distributed/OutboxConfig.cs | 14 +- .../EventBus/Distributed/OutboxConfigList.cs | 8 +- .../DistDemoApp/DistDemoAppModule.cs | 7 +- ...5344_Added_Outbox_CreationTime.Designer.cs | 122 ++++++++++++++++++ ...0210908075344_Added_Outbox_CreationTime.cs | 25 ++++ .../Migrations/TodoDbContextModelSnapshot.cs | 4 + 9 files changed, 192 insertions(+), 9 deletions(-) create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/EfCoreOutboxConfigExtensions.cs create mode 100644 test/DistEvents/DistDemoApp/Migrations/20210908075344_Added_Outbox_CreationTime.Designer.cs create mode 100644 test/DistEvents/DistDemoApp/Migrations/20210908075344_Added_Outbox_CreationTime.cs diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/EfCoreOutboxConfigExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/EfCoreOutboxConfigExtensions.cs new file mode 100644 index 0000000000..8199ff0739 --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/EfCoreOutboxConfigExtensions.cs @@ -0,0 +1,13 @@ +using Volo.Abp.EventBus.Distributed; + +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public static class EfCoreOutboxConfigExtensions + { + public static void UseDbContext(this OutboxConfig outboxConfig) + where TDbContext : IHasEventOutbox + { + outboxConfig.ImplementationType = typeof(DbContextEventOutbox); + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/OutgoingEventRecord.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/OutgoingEventRecord.cs index 395970c4a9..d33e6a0097 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/OutgoingEventRecord.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/OutgoingEventRecord.cs @@ -1,17 +1,21 @@ using System; +using Volo.Abp.Auditing; using Volo.Abp.Data; using Volo.Abp.Domain.Entities; namespace Volo.Abp.EntityFrameworkCore.DistributedEvents { - public class OutgoingEventRecord : BasicAggregateRoot, IHasExtraProperties + public class OutgoingEventRecord : BasicAggregateRoot, IHasExtraProperties, IHasCreationTime { public static int MaxEventNameLength { get; set; } = 256; public ExtraPropertyDictionary ExtraProperties { get; protected set; } public string EventName { get; set; } + public byte[] EventData { get; set; } + + public DateTime CreationTime { get; set; } protected OutgoingEventRecord() { diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs index bea6b93a36..3d68490ae2 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs @@ -80,7 +80,7 @@ namespace Volo.Abp.EventBus.Distributed return false; } - foreach (var outboxConfig in AbpDistributedEventBusOptions.Outboxes) + foreach (var outboxConfig in AbpDistributedEventBusOptions.Outboxes.Values) { if (outboxConfig.Selector == null || outboxConfig.Selector(eventType)) { diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/OutboxConfig.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/OutboxConfig.cs index 97712ec85e..be7630ddee 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/OutboxConfig.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/OutboxConfig.cs @@ -1,18 +1,26 @@ using System; +using JetBrains.Annotations; namespace Volo.Abp.EventBus.Distributed { public class OutboxConfig { + [NotNull] public string Name { get; } public Type ImplementationType { get; set; } + public Func Selector { get; set; } - public OutboxConfig(string name, Type implementationType, Func selector = null) + /// + /// Used to enable/disable sending events from outbox to the message broker. + /// Default: true. + /// + public bool IsSendingEnabled { get; set; } = true; + + public OutboxConfig([NotNull] string name) { - Name = name; - ImplementationType = implementationType; + Name = Check.NotNullOrWhiteSpace(name, nameof(name)); } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/OutboxConfigList.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/OutboxConfigList.cs index 47c91377da..162ceef6ff 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/OutboxConfigList.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/OutboxConfigList.cs @@ -1,8 +1,14 @@ +using System; using System.Collections.Generic; namespace Volo.Abp.EventBus.Distributed { - public class OutboxConfigList : List + public class OutboxConfigList : Dictionary { + public void Configure(string outboxName, Action configAction) + { + var outboxConfig = this.GetOrAdd(outboxName, () => new OutboxConfig(outboxName)); + configAction(outboxConfig); + } } } \ No newline at end of file diff --git a/test/DistEvents/DistDemoApp/DistDemoAppModule.cs b/test/DistEvents/DistDemoApp/DistDemoAppModule.cs index 3cb92b2307..93880032d9 100644 --- a/test/DistEvents/DistDemoApp/DistDemoAppModule.cs +++ b/test/DistEvents/DistDemoApp/DistDemoAppModule.cs @@ -39,9 +39,10 @@ namespace DistDemoApp Configure(options => { - options.Outboxes.Add( - new OutboxConfig("Default", typeof(DbContextEventOutbox)) - ); + options.Outboxes.Configure("Default", config => + { + config.UseDbContext(); + }); }); } } diff --git a/test/DistEvents/DistDemoApp/Migrations/20210908075344_Added_Outbox_CreationTime.Designer.cs b/test/DistEvents/DistDemoApp/Migrations/20210908075344_Added_Outbox_CreationTime.Designer.cs new file mode 100644 index 0000000000..def5ebc7d7 --- /dev/null +++ b/test/DistEvents/DistDemoApp/Migrations/20210908075344_Added_Outbox_CreationTime.Designer.cs @@ -0,0 +1,122 @@ +// +using System; +using DistDemoApp; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Volo.Abp.EntityFrameworkCore; + +namespace DistDemoApp.Migrations +{ + [DbContext(typeof(TodoDbContext))] + [Migration("20210908075344_Added_Outbox_CreationTime")] + partial class Added_Outbox_CreationTime + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) + .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("ProductVersion", "5.0.9") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("DistDemoApp.TodoItem", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Text") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.ToTable("TodoItems"); + }); + + modelBuilder.Entity("DistDemoApp.TodoSummary", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Day") + .HasColumnType("tinyint"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Month") + .HasColumnType("tinyint"); + + b.Property("TotalCount") + .HasColumnType("int"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("TodoSummaries"); + }); + + modelBuilder.Entity("Volo.Abp.EntityFrameworkCore.DistributedEvents.OutgoingEventRecord", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("EventData") + .IsRequired() + .HasColumnType("varbinary(max)"); + + b.Property("EventName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.HasKey("Id"); + + b.ToTable("AbpEventOutbox"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/test/DistEvents/DistDemoApp/Migrations/20210908075344_Added_Outbox_CreationTime.cs b/test/DistEvents/DistDemoApp/Migrations/20210908075344_Added_Outbox_CreationTime.cs new file mode 100644 index 0000000000..2899933b8f --- /dev/null +++ b/test/DistEvents/DistDemoApp/Migrations/20210908075344_Added_Outbox_CreationTime.cs @@ -0,0 +1,25 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace DistDemoApp.Migrations +{ + public partial class Added_Outbox_CreationTime : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "CreationTime", + table: "AbpEventOutbox", + type: "datetime2", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "CreationTime", + table: "AbpEventOutbox"); + } + } +} diff --git a/test/DistEvents/DistDemoApp/Migrations/TodoDbContextModelSnapshot.cs b/test/DistEvents/DistDemoApp/Migrations/TodoDbContextModelSnapshot.cs index 91d7bc0cc7..f1b3330485 100644 --- a/test/DistEvents/DistDemoApp/Migrations/TodoDbContextModelSnapshot.cs +++ b/test/DistEvents/DistDemoApp/Migrations/TodoDbContextModelSnapshot.cs @@ -93,6 +93,10 @@ namespace DistDemoApp.Migrations b.Property("Id") .HasColumnType("uniqueidentifier"); + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + b.Property("EventData") .IsRequired() .HasColumnType("varbinary(max)"); From 3a89cb41b85352e9f8512dda239d95fae737437d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 8 Sep 2021 11:16:53 +0300 Subject: [PATCH 05/36] Added Volo.Abp.EventBus.Boxes.csproj --- framework/Volo.Abp.sln | 7 +++++ .../BackgroundJobs/AbpBackgroundJobsModule.cs | 7 +---- .../Volo.Abp.EventBus.Boxes/FodyWeavers.xml | 3 ++ .../Volo.Abp.EventBus.Boxes/FodyWeavers.xsd | 30 +++++++++++++++++++ .../Volo.Abp.EventBus.Boxes.csproj | 21 +++++++++++++ .../EventBus/Boxes/AbpEventBusBoxesModule.cs | 12 ++++++++ .../Volo/Abp/EventBus/Boxes/OutboxSender.cs | 7 +++++ .../Volo/Abp/Threading/AbpTimer.cs | 2 +- nupkg/common.ps1 | 1 + 9 files changed, 83 insertions(+), 7 deletions(-) create mode 100644 framework/src/Volo.Abp.EventBus.Boxes/FodyWeavers.xml create mode 100644 framework/src/Volo.Abp.EventBus.Boxes/FodyWeavers.xsd create mode 100644 framework/src/Volo.Abp.EventBus.Boxes/Volo.Abp.EventBus.Boxes.csproj create mode 100644 framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/AbpEventBusBoxesModule.cs create mode 100644 framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs diff --git a/framework/Volo.Abp.sln b/framework/Volo.Abp.sln index 8d5432f4c6..60011440f9 100644 --- a/framework/Volo.Abp.sln +++ b/framework/Volo.Abp.sln @@ -385,6 +385,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.MongoDB.Tests.Seco EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Threading.Tests", "test\Volo.Abp.Threading.Tests\Volo.Abp.Threading.Tests.csproj", "{7B2FCAD6-86E6-49C8-ADBE-A61B4F4B101B}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.EventBus.Boxes", "src\Volo.Abp.EventBus.Boxes\Volo.Abp.EventBus.Boxes.csproj", "{6E289F31-7924-418B-9DAC-62A7CFADF916}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1147,6 +1149,10 @@ Global {7B2FCAD6-86E6-49C8-ADBE-A61B4F4B101B}.Debug|Any CPU.Build.0 = Debug|Any CPU {7B2FCAD6-86E6-49C8-ADBE-A61B4F4B101B}.Release|Any CPU.ActiveCfg = Release|Any CPU {7B2FCAD6-86E6-49C8-ADBE-A61B4F4B101B}.Release|Any CPU.Build.0 = Release|Any CPU + {6E289F31-7924-418B-9DAC-62A7CFADF916}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6E289F31-7924-418B-9DAC-62A7CFADF916}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6E289F31-7924-418B-9DAC-62A7CFADF916}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6E289F31-7924-418B-9DAC-62A7CFADF916}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1341,6 +1347,7 @@ Global {75D8DADB-3FA9-4C1D-B23A-DBFD08133B7C} = {447C8A77-E5F0-4538-8687-7383196D04EA} {90B1866A-EF99-40B9-970E-B898E5AA523F} = {447C8A77-E5F0-4538-8687-7383196D04EA} {7B2FCAD6-86E6-49C8-ADBE-A61B4F4B101B} = {447C8A77-E5F0-4538-8687-7383196D04EA} + {6E289F31-7924-418B-9DAC-62A7CFADF916} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5} diff --git a/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/AbpBackgroundJobsModule.cs b/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/AbpBackgroundJobsModule.cs index cea8a1eee6..dccf2006dc 100644 --- a/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/AbpBackgroundJobsModule.cs +++ b/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/AbpBackgroundJobsModule.cs @@ -20,12 +20,7 @@ namespace Volo.Abp.BackgroundJobs var options = context.ServiceProvider.GetRequiredService>().Value; if (options.IsJobExecutionEnabled) { - context.ServiceProvider - .GetRequiredService() - .Add( - context.ServiceProvider - .GetRequiredService() - ); + context.AddBackgroundWorker(); } } } diff --git a/framework/src/Volo.Abp.EventBus.Boxes/FodyWeavers.xml b/framework/src/Volo.Abp.EventBus.Boxes/FodyWeavers.xml new file mode 100644 index 0000000000..be0de3a908 --- /dev/null +++ b/framework/src/Volo.Abp.EventBus.Boxes/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus.Boxes/FodyWeavers.xsd b/framework/src/Volo.Abp.EventBus.Boxes/FodyWeavers.xsd new file mode 100644 index 0000000000..3f3946e282 --- /dev/null +++ b/framework/src/Volo.Abp.EventBus.Boxes/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus.Boxes/Volo.Abp.EventBus.Boxes.csproj b/framework/src/Volo.Abp.EventBus.Boxes/Volo.Abp.EventBus.Boxes.csproj new file mode 100644 index 0000000000..3cae05a96a --- /dev/null +++ b/framework/src/Volo.Abp.EventBus.Boxes/Volo.Abp.EventBus.Boxes.csproj @@ -0,0 +1,21 @@ + + + + + + + netstandard2.0 + Volo.Abp.EventBus.Boxes + Volo.Abp.EventBus.Boxes + $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; + false + false + false + + + + + + + + diff --git a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/AbpEventBusBoxesModule.cs b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/AbpEventBusBoxesModule.cs new file mode 100644 index 0000000000..904bab747a --- /dev/null +++ b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/AbpEventBusBoxesModule.cs @@ -0,0 +1,12 @@ +using Volo.Abp.Modularity; + +namespace Volo.Abp.EventBus.Boxes +{ + [DependsOn( + typeof(AbpEventBusModule) + )] + public class AbpEventBusBoxesModule : AbpModule + { + + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs new file mode 100644 index 0000000000..48bad9a6cf --- /dev/null +++ b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs @@ -0,0 +1,7 @@ +namespace Volo.Abp.EventBus.Boxes +{ + public class OutboxSender + { + //Background worker & distributed lock + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/AbpTimer.cs b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/AbpTimer.cs index e7e6efd5de..d95fc7012b 100644 --- a/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/AbpTimer.cs +++ b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/AbpTimer.cs @@ -96,7 +96,7 @@ namespace Volo.Abp.Threading try { - Elapsed.InvokeSafely(this, new EventArgs()); + Elapsed.InvokeSafely(this, EventArgs.Empty); } catch(Exception ex) { diff --git a/nupkg/common.ps1 b/nupkg/common.ps1 index b71ebccfd0..c4fcfc4df3 100644 --- a/nupkg/common.ps1 +++ b/nupkg/common.ps1 @@ -100,6 +100,7 @@ $projects = ( "framework/src/Volo.Abp.EntityFrameworkCore.SqlServer", "framework/src/Volo.Abp.EventBus.Abstractions", "framework/src/Volo.Abp.EventBus", + "framework/src/Volo.Abp.EventBus.Boxes", "framework/src/Volo.Abp.EventBus.RabbitMQ", "framework/src/Volo.Abp.EventBus.Kafka", "framework/src/Volo.Abp.EventBus.Rebus", From afcd640e40adfe8bb0233d9686607f04ab8ccb05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 8 Sep 2021 14:02:05 +0300 Subject: [PATCH 06/36] Basic implementation is done for the event outbox. --- .../AbpEntityFrameworkCoreModule.cs | 2 +- .../DistributedEvents/DbContextEventOutbox.cs | 48 +++++++++--- .../EfCoreOutboxConfigExtensions.cs | 2 +- .../IDbContextEventOutbox.cs | 10 +++ .../DistributedEvents/OutgoingEventRecord.cs | 36 ++++++--- .../Volo.Abp.EventBus.Boxes.csproj | 1 + .../Boxes/AbpDistributedEventBusExtensions.cs | 18 +++++ .../EventBus/Boxes/AbpEventBusBoxesModule.cs | 11 ++- .../Volo/Abp/EventBus/Boxes/IOutboxSender.cs | 11 +++ .../Volo/Abp/EventBus/Boxes/OutboxSender.cs | 77 ++++++++++++++++++- .../Abp/EventBus/Boxes/OutboxSenderManager.cs | 48 ++++++++++++ .../Kafka/KafkaDistributedEventBus.cs | 36 ++++++++- .../RabbitMq/RabbitMqDistributedEventBus.cs | 29 ++++++- .../Rebus/RebusDistributedEventBus.cs | 16 +++- .../Volo.Abp.EventBus.csproj | 1 + .../Volo/Abp/EventBus/AbpEventBusModule.cs | 5 +- .../Distributed/DistributedEventBusBase.cs | 25 ++++-- .../Abp/EventBus/Distributed/IEventOutbox.cs | 8 +- .../Distributed/IRawEventPublisher.cs | 13 ++++ .../EventBus/Distributed/OutgoingEventInfo.cs | 39 ++++++++++ .../DistEvents/DistDemoApp/DistDemoApp.csproj | 1 + .../DistDemoApp/DistDemoAppModule.cs | 4 +- 22 files changed, 395 insertions(+), 46 deletions(-) create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IDbContextEventOutbox.cs create mode 100644 framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/AbpDistributedEventBusExtensions.cs create mode 100644 framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/IOutboxSender.cs create mode 100644 framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSenderManager.cs create mode 100644 framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IRawEventPublisher.cs create mode 100644 framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/OutgoingEventInfo.cs diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreModule.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreModule.cs index 1378f955e4..79db928711 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreModule.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreModule.cs @@ -27,7 +27,7 @@ namespace Volo.Abp.EntityFrameworkCore }); context.Services.TryAddTransient(typeof(IDbContextProvider<>), typeof(UnitOfWorkDbContextProvider<>)); - context.Services.AddTransient(typeof(DbContextEventOutbox<>)); + context.Services.AddTransient(typeof(IDbContextEventOutbox<>), typeof(DbContextEventOutbox<>)); } } } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventOutbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventOutbox.cs index 1831b67ccb..b8d26fa357 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventOutbox.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventOutbox.cs @@ -1,29 +1,59 @@ -using System.Threading.Tasks; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; using Volo.Abp.EventBus.Distributed; -using Volo.Abp.Guids; +using Volo.Abp.Uow; namespace Volo.Abp.EntityFrameworkCore.DistributedEvents { - public class DbContextEventOutbox : IEventOutbox + public class DbContextEventOutbox : IDbContextEventOutbox where TDbContext : IHasEventOutbox { protected IDbContextProvider DbContextProvider { get; } - protected IGuidGenerator GuidGenerator { get; } public DbContextEventOutbox( - IDbContextProvider dbContextProvider, - IGuidGenerator guidGenerator) + IDbContextProvider dbContextProvider) { DbContextProvider = dbContextProvider; - GuidGenerator = guidGenerator; } - public async Task EnqueueAsync(string eventName, byte[] eventData) + [UnitOfWork] + public virtual async Task EnqueueAsync(OutgoingEventInfo outgoingEvent) { var dbContext = (IHasEventOutbox) await DbContextProvider.GetDbContextAsync(); dbContext.OutgoingEventRecords.Add( - new OutgoingEventRecord(GuidGenerator.Create(), eventName, eventData) + new OutgoingEventRecord(outgoingEvent) ); } + + [UnitOfWork] + public virtual async Task> GetWaitingEventsAsync(int maxCount) + { + var dbContext = (IHasEventOutbox) await DbContextProvider.GetDbContextAsync(); + + var outgoingEventRecords = await dbContext + .OutgoingEventRecords + .AsNoTracking() + .OrderBy(x => x.CreationTime) + .Take(maxCount) + .ToListAsync(); + + return outgoingEventRecords + .Select(x => x.ToOutgoingEventInfo()) + .ToList(); + } + + [UnitOfWork] + public virtual async Task DeleteAsync(Guid id) + { + var dbContext = (IHasEventOutbox) await DbContextProvider.GetDbContextAsync(); + var outgoingEvent = await dbContext.OutgoingEventRecords.FindAsync(id); + if (outgoingEvent != null) + { + dbContext.Remove(outgoingEvent); + } + } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/EfCoreOutboxConfigExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/EfCoreOutboxConfigExtensions.cs index 8199ff0739..53745477c7 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/EfCoreOutboxConfigExtensions.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/EfCoreOutboxConfigExtensions.cs @@ -7,7 +7,7 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents public static void UseDbContext(this OutboxConfig outboxConfig) where TDbContext : IHasEventOutbox { - outboxConfig.ImplementationType = typeof(DbContextEventOutbox); + outboxConfig.ImplementationType = typeof(IDbContextEventOutbox); } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IDbContextEventOutbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IDbContextEventOutbox.cs new file mode 100644 index 0000000000..71d65c7f23 --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IDbContextEventOutbox.cs @@ -0,0 +1,10 @@ +using Volo.Abp.EventBus.Distributed; + +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public interface IDbContextEventOutbox : IEventOutbox + where TDbContext : IHasEventOutbox + { + + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/OutgoingEventRecord.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/OutgoingEventRecord.cs index d33e6a0097..727216de48 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/OutgoingEventRecord.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/OutgoingEventRecord.cs @@ -2,20 +2,24 @@ using Volo.Abp.Auditing; using Volo.Abp.Data; using Volo.Abp.Domain.Entities; +using Volo.Abp.EventBus.Distributed; namespace Volo.Abp.EntityFrameworkCore.DistributedEvents { - public class OutgoingEventRecord : BasicAggregateRoot, IHasExtraProperties, IHasCreationTime + public class OutgoingEventRecord : + BasicAggregateRoot, + IHasExtraProperties, + IHasCreationTime { public static int MaxEventNameLength { get; set; } = 256; - public ExtraPropertyDictionary ExtraProperties { get; protected set; } + public ExtraPropertyDictionary ExtraProperties { get; private set; } - public string EventName { get; set; } + public string EventName { get; private set; } - public byte[] EventData { get; set; } + public byte[] EventData { get; private set; } - public DateTime CreationTime { get; set; } + public DateTime CreationTime { get; private set; } protected OutgoingEventRecord() { @@ -23,14 +27,26 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents this.SetDefaultsForExtraProperties(); } - public OutgoingEventRecord(Guid id, string eventName, byte[] eventData) - : base(id) + public OutgoingEventRecord( + OutgoingEventInfo eventInfo) + : base(eventInfo.Id) { - EventName = eventName; - EventData = eventData; - + EventName = eventInfo.EventName; + EventData = eventInfo.EventData; + CreationTime = eventInfo.CreationTime; + ExtraProperties = new ExtraPropertyDictionary(); this.SetDefaultsForExtraProperties(); } + + public OutgoingEventInfo ToOutgoingEventInfo() + { + return new OutgoingEventInfo( + Id, + EventName, + EventData, + CreationTime + ); + } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus.Boxes/Volo.Abp.EventBus.Boxes.csproj b/framework/src/Volo.Abp.EventBus.Boxes/Volo.Abp.EventBus.Boxes.csproj index 3cae05a96a..19b7f7032e 100644 --- a/framework/src/Volo.Abp.EventBus.Boxes/Volo.Abp.EventBus.Boxes.csproj +++ b/framework/src/Volo.Abp.EventBus.Boxes/Volo.Abp.EventBus.Boxes.csproj @@ -15,6 +15,7 @@ + diff --git a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/AbpDistributedEventBusExtensions.cs b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/AbpDistributedEventBusExtensions.cs new file mode 100644 index 0000000000..dda6f71245 --- /dev/null +++ b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/AbpDistributedEventBusExtensions.cs @@ -0,0 +1,18 @@ +using Volo.Abp.EventBus.Distributed; + +namespace Volo.Abp.EventBus.Boxes +{ + public static class AbpDistributedEventBusExtensions + { + public static IRawEventPublisher AsRawEventPublisher(this IDistributedEventBus eventBus) + { + var rawPublisher = eventBus as IRawEventPublisher; + if (rawPublisher == null) + { + throw new AbpException($"Given type ({eventBus.GetType().AssemblyQualifiedName}) should implement {nameof(IRawEventPublisher)}!"); + } + + return rawPublisher; + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/AbpEventBusBoxesModule.cs b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/AbpEventBusBoxesModule.cs index 904bab747a..9445f1de08 100644 --- a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/AbpEventBusBoxesModule.cs +++ b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/AbpEventBusBoxesModule.cs @@ -1,12 +1,17 @@ -using Volo.Abp.Modularity; +using Volo.Abp.BackgroundWorkers; +using Volo.Abp.Modularity; namespace Volo.Abp.EventBus.Boxes { [DependsOn( - typeof(AbpEventBusModule) + typeof(AbpEventBusModule), + typeof(AbpBackgroundWorkersModule) )] public class AbpEventBusBoxesModule : AbpModule { - + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + context.AddBackgroundWorker(); + } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/IOutboxSender.cs b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/IOutboxSender.cs new file mode 100644 index 0000000000..efc278844a --- /dev/null +++ b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/IOutboxSender.cs @@ -0,0 +1,11 @@ +using System.Threading.Tasks; +using Volo.Abp.EventBus.Distributed; + +namespace Volo.Abp.EventBus.Boxes +{ + public interface IOutboxSender + { + Task StartAsync(OutboxConfig outboxConfig); + Task StopAsync(); + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs index 48bad9a6cf..8c7669e447 100644 --- a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs +++ b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs @@ -1,7 +1,78 @@ -namespace Volo.Abp.EventBus.Boxes +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Volo.Abp.DependencyInjection; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.Threading; +using Volo.Abp.Uow; + +namespace Volo.Abp.EventBus.Boxes { - public class OutboxSender + //TODO: use distributed lock! + public class OutboxSender : IOutboxSender, ITransientDependency { - //Background worker & distributed lock + protected IServiceProvider ServiceProvider { get; } + protected AbpTimer Timer { get; } + protected IDistributedEventBus DistributedEventBus { get; } + protected IEventOutbox Outbox { get; private set; } + public ILogger Logger { get; set; } + + public OutboxSender( + IServiceProvider serviceProvider, + AbpTimer timer, + IDistributedEventBus distributedEventBus) + { + ServiceProvider = serviceProvider; + Timer = timer; + DistributedEventBus = distributedEventBus; + Timer.Period = 2000; //TODO: Config? + Timer.Elapsed += TimerOnElapsed; + Logger = NullLogger.Instance; + } + + public virtual Task StartAsync(OutboxConfig outboxConfig) + { + Outbox = (IEventOutbox)ServiceProvider.GetRequiredService(outboxConfig.ImplementationType); + Timer.Start(); + return Task.CompletedTask; + } + + public virtual Task StopAsync() + { + Timer.Stop(); + return Task.CompletedTask; + } + + private void TimerOnElapsed(object sender, EventArgs e) + { + AsyncHelper.RunSync(RunAsync); + } + + protected virtual async Task RunAsync() + { + while (true) + { + var waitingEvents = await Outbox.GetWaitingEventsAsync(100); + if (waitingEvents.Count <= 0) + { + break; + } + + Logger.LogInformation($"Found {waitingEvents.Count} events in the outbox."); + + foreach (var waitingEvent in waitingEvents) + { + await DistributedEventBus + .AsRawEventPublisher() + .PublishRawAsync(waitingEvent.Id, waitingEvent.EventName, waitingEvent.EventData); + + await Outbox.DeleteAsync(waitingEvent.Id); + + Logger.LogInformation($"Sent the event to the message broker with id = {waitingEvent.Id:N}"); + } + } + } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSenderManager.cs b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSenderManager.cs new file mode 100644 index 0000000000..617913e42f --- /dev/null +++ b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSenderManager.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Volo.Abp.BackgroundWorkers; +using Volo.Abp.EventBus.Distributed; + +namespace Volo.Abp.EventBus.Boxes +{ + public class OutboxSenderManager : IBackgroundWorker + { + protected AbpDistributedEventBusOptions Options { get; } + protected IServiceProvider ServiceProvider { get; } + protected List Senders { get; } + + public OutboxSenderManager( + IOptions options, + IServiceProvider serviceProvider) + { + ServiceProvider = serviceProvider; + Options = options.Value; + Senders = new List(); + } + + public async Task StartAsync(CancellationToken cancellationToken = default) + { + foreach (var outboxConfig in Options.Outboxes.Values) + { + if (outboxConfig.IsSendingEnabled) + { + var sender = ServiceProvider.GetRequiredService(); + await sender.StartAsync(outboxConfig); + Senders.Add(sender); + } + } + } + + public async Task StopAsync(CancellationToken cancellationToken = default) + { + foreach (var sender in Senders) + { + await sender.StopAsync(); + } + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs b/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs index 18f68923e1..9e62b47fed 100644 --- a/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs +++ b/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs @@ -9,9 +9,11 @@ using Microsoft.Extensions.Options; using Volo.Abp.Data; using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus.Distributed; +using Volo.Abp.Guids; using Volo.Abp.Kafka; using Volo.Abp.MultiTenancy; using Volo.Abp.Threading; +using Volo.Abp.Timing; using Volo.Abp.Uow; namespace Volo.Abp.EventBus.Kafka @@ -40,13 +42,17 @@ namespace Volo.Abp.EventBus.Kafka IKafkaSerializer serializer, IProducerPool producerPool, IEventErrorHandler errorHandler, - IOptions abpEventBusOptions) + IOptions abpEventBusOptions, + IGuidGenerator guidGenerator, + IClock clock) : base( serviceScopeFactory, currentTenant, unitOfWorkManager, errorHandler, - abpDistributedEventBusOptions) + abpDistributedEventBusOptions, + guidGenerator, + clock) { AbpKafkaEventBusOptions = abpKafkaEventBusOptions.Value; AbpEventBusOptions = abpEventBusOptions.Value; @@ -182,7 +188,24 @@ namespace Volo.Abp.EventBus.Kafka { unitOfWork.AddOrReplaceDistributedEvent(eventRecord); } - + + public override Task PublishRawAsync( + Guid eventId, + string eventName, + byte[] eventData) + { + return PublishAsync( + AbpKafkaEventBusOptions.TopicName, + eventName, + eventData, + new Headers + { + { "messageId", Serializer.Serialize(eventId) } + }, + null + ); + } + protected override byte[] Serialize(object eventData) { return Serializer.Serialize(eventData); @@ -204,11 +227,16 @@ namespace Volo.Abp.EventBus.Kafka await PublishAsync(DeadLetterTopicName, eventType, eventData, headers, headersArguments); } - private async Task PublishAsync(string topicName, Type eventType, object eventData, Headers headers, Dictionary headersArguments) + private Task PublishAsync(string topicName, Type eventType, object eventData, Headers headers, Dictionary headersArguments) { var eventName = EventNameAttribute.GetNameOrDefault(eventType); var body = Serializer.Serialize(eventData); + return PublishAsync(topicName, eventName, body, headers, headersArguments); + } + + private async Task PublishAsync(string topicName, string eventName, byte[] body, Headers headers, Dictionary headersArguments) + { var producer = ProducerPool.Get(AbpKafkaEventBusOptions.ConnectionName); SetEventMessageHeaders(headers, headersArguments); diff --git a/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs b/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs index d2766eb247..f51cd6821d 100644 --- a/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs +++ b/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs @@ -10,9 +10,11 @@ using RabbitMQ.Client.Events; using Volo.Abp.Data; using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus.Distributed; +using Volo.Abp.Guids; using Volo.Abp.MultiTenancy; using Volo.Abp.RabbitMQ; using Volo.Abp.Threading; +using Volo.Abp.Timing; using Volo.Abp.Uow; namespace Volo.Abp.EventBus.RabbitMq @@ -46,13 +48,17 @@ namespace Volo.Abp.EventBus.RabbitMq ICurrentTenant currentTenant, IUnitOfWorkManager unitOfWorkManager, IEventErrorHandler errorHandler, - IOptions abpEventBusOptions) + IOptions abpEventBusOptions, + IGuidGenerator guidGenerator, + IClock clock) : base( serviceScopeFactory, currentTenant, unitOfWorkManager, errorHandler, - distributedEventBusOptions) + distributedEventBusOptions, + guidGenerator, + clock) { ConnectionPool = connectionPool; Serializer = serializer; @@ -198,7 +204,12 @@ namespace Volo.Abp.EventBus.RabbitMq { unitOfWork.AddOrReplaceDistributedEvent(eventRecord); } - + + public override Task PublishRawAsync(Guid eventId, string eventName, byte[] eventData) + { + return PublishAsync(eventName, eventData, null, eventId: eventId); + } + protected override byte[] Serialize(object eventData) { return Serializer.Serialize(eventData); @@ -209,6 +220,16 @@ namespace Volo.Abp.EventBus.RabbitMq var eventName = EventNameAttribute.GetNameOrDefault(eventType); var body = Serializer.Serialize(eventData); + return PublishAsync(eventName, body, properties, headersArguments); + } + + protected Task PublishAsync( + string eventName, + byte[] body, + IBasicProperties properties, + Dictionary headersArguments = null, + Guid? eventId = null) + { using (var channel = ConnectionPool.Get(AbpRabbitMqEventBusOptions.ConnectionName).CreateModel()) { channel.ExchangeDeclare( @@ -221,7 +242,7 @@ namespace Volo.Abp.EventBus.RabbitMq { properties = channel.CreateBasicProperties(); properties.DeliveryMode = RabbitMqConsts.DeliveryModes.Persistent; - properties.MessageId = Guid.NewGuid().ToString("N"); + properties.MessageId = (eventId ?? GuidGenerator.Create()).ToString("N"); } SetEventMessageHeaders(properties, headersArguments); diff --git a/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventBus.cs b/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventBus.cs index 43017d9c4a..07995d67dd 100644 --- a/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventBus.cs +++ b/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventBus.cs @@ -8,8 +8,10 @@ using Microsoft.Extensions.Options; using Rebus.Bus; using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus.Distributed; +using Volo.Abp.Guids; using Volo.Abp.MultiTenancy; using Volo.Abp.Threading; +using Volo.Abp.Timing; using Volo.Abp.Uow; namespace Volo.Abp.EventBus.Rebus @@ -34,13 +36,17 @@ namespace Volo.Abp.EventBus.Rebus IOptions abpDistributedEventBusOptions, IOptions abpEventBusRebusOptions, IEventErrorHandler errorHandler, - IRebusSerializer serializer) : + IRebusSerializer serializer, + IGuidGenerator guidGenerator, + IClock clock) : base( serviceScopeFactory, currentTenant, unitOfWorkManager, errorHandler, - abpDistributedEventBusOptions) + abpDistributedEventBusOptions, + guidGenerator, + clock) { Rebus = rebus; Serializer = serializer; @@ -182,6 +188,12 @@ namespace Volo.Abp.EventBus.Rebus return false; } + public override Task PublishRawAsync(Guid eventId, string eventName, byte[] eventData) + { + /* TODO: IMPLEMENT! */ + throw new NotImplementedException(); + } + protected override byte[] Serialize(object eventData) { return Serializer.Serialize(eventData); diff --git a/framework/src/Volo.Abp.EventBus/Volo.Abp.EventBus.csproj b/framework/src/Volo.Abp.EventBus/Volo.Abp.EventBus.csproj index 261b10d8ae..5de5b0893f 100644 --- a/framework/src/Volo.Abp.EventBus/Volo.Abp.EventBus.csproj +++ b/framework/src/Volo.Abp.EventBus/Volo.Abp.EventBus.csproj @@ -16,6 +16,7 @@ + diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/AbpEventBusModule.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/AbpEventBusModule.cs index 329c26c93f..bd86f14703 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/AbpEventBusModule.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/AbpEventBusModule.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using Volo.Abp.EventBus.Abstractions; using Volo.Abp.EventBus.Distributed; using Volo.Abp.EventBus.Local; +using Volo.Abp.Guids; using Volo.Abp.Json; using Volo.Abp.Modularity; using Volo.Abp.MultiTenancy; @@ -14,7 +15,9 @@ namespace Volo.Abp.EventBus [DependsOn( typeof(AbpEventBusAbstractionsModule), typeof(AbpMultiTenancyModule), - typeof(AbpJsonModule))] + typeof(AbpJsonModule), + typeof(AbpGuidsModule) + )] public class AbpEventBusModule : AbpModule { public override void PreConfigureServices(ServiceConfigurationContext context) diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs index 3d68490ae2..786f58fe47 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs @@ -1,15 +1,18 @@ using System; -using System.Linq; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; +using Volo.Abp.Guids; using Volo.Abp.MultiTenancy; +using Volo.Abp.Timing; using Volo.Abp.Uow; namespace Volo.Abp.EventBus.Distributed { - public abstract class DistributedEventBusBase : EventBusBase, IDistributedEventBus + public abstract class DistributedEventBusBase : EventBusBase, IDistributedEventBus, IRawEventPublisher { + protected IGuidGenerator GuidGenerator { get; } + protected IClock Clock { get; } protected AbpDistributedEventBusOptions AbpDistributedEventBusOptions { get; } protected DistributedEventBusBase( @@ -17,13 +20,17 @@ namespace Volo.Abp.EventBus.Distributed ICurrentTenant currentTenant, IUnitOfWorkManager unitOfWorkManager, IEventErrorHandler errorHandler, - IOptions abpDistributedEventBusOptions + IOptions abpDistributedEventBusOptions, + IGuidGenerator guidGenerator, + IClock clock ) : base( serviceScopeFactory, currentTenant, unitOfWorkManager, errorHandler) { + GuidGenerator = guidGenerator; + Clock = clock; AbpDistributedEventBusOptions = abpDistributedEventBusOptions.Value; } @@ -71,7 +78,9 @@ namespace Volo.Abp.EventBus.Distributed await PublishToEventBusAsync(eventType, eventData); } - + + public abstract Task PublishRawAsync(Guid eventId, string eventName, byte[] eventData); + private async Task AddToOutboxAsync(Type eventType, object eventData) { var unitOfWork = UnitOfWorkManager.Current; @@ -87,8 +96,12 @@ namespace Volo.Abp.EventBus.Distributed var eventOutbox = (IEventOutbox)unitOfWork.ServiceProvider.GetRequiredService(outboxConfig.ImplementationType); var eventName = EventNameAttribute.GetNameOrDefault(eventType); await eventOutbox.EnqueueAsync( - eventName, - Serialize(eventData) + new OutgoingEventInfo( + GuidGenerator.Create(), + eventName, + Serialize(eventData), + Clock.Now + ) ); return true; } diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IEventOutbox.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IEventOutbox.cs index ec6d010307..0b50993e8e 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IEventOutbox.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IEventOutbox.cs @@ -1,9 +1,15 @@ +using System; +using System.Collections.Generic; using System.Threading.Tasks; namespace Volo.Abp.EventBus.Distributed { public interface IEventOutbox { - Task EnqueueAsync(string eventName, byte[] eventData); + Task EnqueueAsync(OutgoingEventInfo outgoingEvent); + + Task> GetWaitingEventsAsync(int maxCount); + + Task DeleteAsync(Guid id); } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IRawEventPublisher.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IRawEventPublisher.cs new file mode 100644 index 0000000000..f53eb2b78b --- /dev/null +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IRawEventPublisher.cs @@ -0,0 +1,13 @@ +using System; +using System.Threading.Tasks; + +namespace Volo.Abp.EventBus.Distributed +{ + public interface IRawEventPublisher + { + Task PublishRawAsync( + Guid eventId, + string eventName, + byte[] eventData); + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/OutgoingEventInfo.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/OutgoingEventInfo.cs new file mode 100644 index 0000000000..91cf806ba9 --- /dev/null +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/OutgoingEventInfo.cs @@ -0,0 +1,39 @@ +using System; +using Volo.Abp.Data; + +namespace Volo.Abp.EventBus.Distributed +{ + public class OutgoingEventInfo : IHasExtraProperties + { + public static int MaxEventNameLength { get; set; } = 256; + + public ExtraPropertyDictionary ExtraProperties { get; protected set; } + + public Guid Id { get; } + + public string EventName { get; } + + public byte[] EventData { get; } + + public DateTime CreationTime { get; } + + protected OutgoingEventInfo() + { + ExtraProperties = new ExtraPropertyDictionary(); + this.SetDefaultsForExtraProperties(); + } + + public OutgoingEventInfo( + Guid id, + string eventName, + byte[] eventData, + DateTime creationTime) + { + Id = id; + EventName = eventName; + EventData = eventData; + CreationTime = creationTime; + ExtraProperties = new ExtraPropertyDictionary(); + this.SetDefaultsForExtraProperties(); + } + }} \ No newline at end of file diff --git a/test/DistEvents/DistDemoApp/DistDemoApp.csproj b/test/DistEvents/DistDemoApp/DistDemoApp.csproj index 0513a520d1..adfe26ebea 100644 --- a/test/DistEvents/DistDemoApp/DistDemoApp.csproj +++ b/test/DistEvents/DistDemoApp/DistDemoApp.csproj @@ -17,6 +17,7 @@ + diff --git a/test/DistEvents/DistDemoApp/DistDemoAppModule.cs b/test/DistEvents/DistDemoApp/DistDemoAppModule.cs index 93880032d9..42e82f5e46 100644 --- a/test/DistEvents/DistDemoApp/DistDemoAppModule.cs +++ b/test/DistEvents/DistDemoApp/DistDemoAppModule.cs @@ -4,6 +4,7 @@ using Volo.Abp.Domain.Entities.Events.Distributed; using Volo.Abp.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore.DistributedEvents; using Volo.Abp.EntityFrameworkCore.SqlServer; +using Volo.Abp.EventBus.Boxes; using Volo.Abp.EventBus.Distributed; using Volo.Abp.EventBus.RabbitMq; using Volo.Abp.Modularity; @@ -13,7 +14,8 @@ namespace DistDemoApp [DependsOn( typeof(AbpEntityFrameworkCoreSqlServerModule), typeof(AbpAutofacModule), - typeof(AbpEventBusRabbitMqModule) + typeof(AbpEventBusRabbitMqModule), + typeof(AbpEventBusBoxesModule) )] public class DistDemoAppModule : AbpModule { From 6cb6b172226cf67da94291376d47b67e5576a506 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 8 Sep 2021 14:49:36 +0300 Subject: [PATCH 07/36] Update OutboxSender.cs --- .../Volo/Abp/EventBus/Boxes/OutboxSender.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs index 8c7669e447..43c51c0b73 100644 --- a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs +++ b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs @@ -6,7 +6,6 @@ using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus.Distributed; using Volo.Abp.Threading; -using Volo.Abp.Uow; namespace Volo.Abp.EventBus.Boxes { @@ -54,7 +53,7 @@ namespace Volo.Abp.EventBus.Boxes { while (true) { - var waitingEvents = await Outbox.GetWaitingEventsAsync(100); + var waitingEvents = await Outbox.GetWaitingEventsAsync(1000); //TODO: Config? if (waitingEvents.Count <= 0) { break; From ae95de6aa5324a8c4deb21fec66efc3f0ce26bdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 8 Sep 2021 14:57:35 +0300 Subject: [PATCH 08/36] Introduced Volo.Abp.DistributedLocking package --- framework/Volo.Abp.sln | 7 +++++ .../FodyWeavers.xml | 3 ++ .../FodyWeavers.xsd | 30 +++++++++++++++++++ .../Volo.Abp.DistributedLocking.csproj | 21 +++++++++++++ .../AbpDistributedLockingModule.cs | 9 ++++++ nupkg/common.ps1 | 1 + 6 files changed, 71 insertions(+) create mode 100644 framework/src/Volo.Abp.DistributedLocking/FodyWeavers.xml create mode 100644 framework/src/Volo.Abp.DistributedLocking/FodyWeavers.xsd create mode 100644 framework/src/Volo.Abp.DistributedLocking/Volo.Abp.DistributedLocking.csproj create mode 100644 framework/src/Volo.Abp.DistributedLocking/Volo/Abp/DistributedLocking/AbpDistributedLockingModule.cs diff --git a/framework/Volo.Abp.sln b/framework/Volo.Abp.sln index 60011440f9..c5065464ff 100644 --- a/framework/Volo.Abp.sln +++ b/framework/Volo.Abp.sln @@ -387,6 +387,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Threading.Tests", EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.EventBus.Boxes", "src\Volo.Abp.EventBus.Boxes\Volo.Abp.EventBus.Boxes.csproj", "{6E289F31-7924-418B-9DAC-62A7CFADF916}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.DistributedLocking", "src\Volo.Abp.DistributedLocking\Volo.Abp.DistributedLocking.csproj", "{9A7EEA08-15BE-476D-8168-53039867038E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1153,6 +1155,10 @@ Global {6E289F31-7924-418B-9DAC-62A7CFADF916}.Debug|Any CPU.Build.0 = Debug|Any CPU {6E289F31-7924-418B-9DAC-62A7CFADF916}.Release|Any CPU.ActiveCfg = Release|Any CPU {6E289F31-7924-418B-9DAC-62A7CFADF916}.Release|Any CPU.Build.0 = Release|Any CPU + {9A7EEA08-15BE-476D-8168-53039867038E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9A7EEA08-15BE-476D-8168-53039867038E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9A7EEA08-15BE-476D-8168-53039867038E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9A7EEA08-15BE-476D-8168-53039867038E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1348,6 +1354,7 @@ Global {90B1866A-EF99-40B9-970E-B898E5AA523F} = {447C8A77-E5F0-4538-8687-7383196D04EA} {7B2FCAD6-86E6-49C8-ADBE-A61B4F4B101B} = {447C8A77-E5F0-4538-8687-7383196D04EA} {6E289F31-7924-418B-9DAC-62A7CFADF916} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} + {9A7EEA08-15BE-476D-8168-53039867038E} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5} diff --git a/framework/src/Volo.Abp.DistributedLocking/FodyWeavers.xml b/framework/src/Volo.Abp.DistributedLocking/FodyWeavers.xml new file mode 100644 index 0000000000..be0de3a908 --- /dev/null +++ b/framework/src/Volo.Abp.DistributedLocking/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/framework/src/Volo.Abp.DistributedLocking/FodyWeavers.xsd b/framework/src/Volo.Abp.DistributedLocking/FodyWeavers.xsd new file mode 100644 index 0000000000..3f3946e282 --- /dev/null +++ b/framework/src/Volo.Abp.DistributedLocking/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/framework/src/Volo.Abp.DistributedLocking/Volo.Abp.DistributedLocking.csproj b/framework/src/Volo.Abp.DistributedLocking/Volo.Abp.DistributedLocking.csproj new file mode 100644 index 0000000000..6cecd5b0d8 --- /dev/null +++ b/framework/src/Volo.Abp.DistributedLocking/Volo.Abp.DistributedLocking.csproj @@ -0,0 +1,21 @@ + + + + + + + netstandard2.0 + Volo.Abp.DistributedLocking + Volo.Abp.DistributedLocking + $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; + false + false + false + + + + + + + + diff --git a/framework/src/Volo.Abp.DistributedLocking/Volo/Abp/DistributedLocking/AbpDistributedLockingModule.cs b/framework/src/Volo.Abp.DistributedLocking/Volo/Abp/DistributedLocking/AbpDistributedLockingModule.cs new file mode 100644 index 0000000000..877ac54244 --- /dev/null +++ b/framework/src/Volo.Abp.DistributedLocking/Volo/Abp/DistributedLocking/AbpDistributedLockingModule.cs @@ -0,0 +1,9 @@ +using Volo.Abp.Modularity; + +namespace Volo.Abp.DistributedLocking +{ + public class AbpDistributedLockingModule : AbpModule + { + + } +} \ No newline at end of file diff --git a/nupkg/common.ps1 b/nupkg/common.ps1 index c4fcfc4df3..bc9ccb63a0 100644 --- a/nupkg/common.ps1 +++ b/nupkg/common.ps1 @@ -90,6 +90,7 @@ $projects = ( "framework/src/Volo.Abp.Ddd.Application", "framework/src/Volo.Abp.Ddd.Application.Contracts", "framework/src/Volo.Abp.Ddd.Domain", + "framework/src/Volo.Abp.DistributedLocking", "framework/src/Volo.Abp.Emailing", "framework/src/Volo.Abp.EntityFrameworkCore", "framework/src/Volo.Abp.EntityFrameworkCore.MySQL", From 8271fc98a6248cd52cca7e06987253ee0b1a2380 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 8 Sep 2021 15:50:09 +0300 Subject: [PATCH 09/36] Implemented distributed locking for the event outbox --- .../Volo.Abp.DistributedLocking.csproj | 4 ++ .../Volo.Abp.EventBus.Boxes.csproj | 1 + .../Volo/Abp/EventBus/Boxes/OutboxSender.cs | 49 +++++++++++++------ .../DistEvents/DistDemoApp/DistDemoApp.csproj | 1 + .../DistDemoApp/DistDemoAppModule.cs | 11 +++++ test/DistEvents/DistDemoApp/appsettings.json | 3 ++ 6 files changed, 55 insertions(+), 14 deletions(-) diff --git a/framework/src/Volo.Abp.DistributedLocking/Volo.Abp.DistributedLocking.csproj b/framework/src/Volo.Abp.DistributedLocking/Volo.Abp.DistributedLocking.csproj index 6cecd5b0d8..c4b590412d 100644 --- a/framework/src/Volo.Abp.DistributedLocking/Volo.Abp.DistributedLocking.csproj +++ b/framework/src/Volo.Abp.DistributedLocking/Volo.Abp.DistributedLocking.csproj @@ -18,4 +18,8 @@ + + + + diff --git a/framework/src/Volo.Abp.EventBus.Boxes/Volo.Abp.EventBus.Boxes.csproj b/framework/src/Volo.Abp.EventBus.Boxes/Volo.Abp.EventBus.Boxes.csproj index 19b7f7032e..6cbaf62aed 100644 --- a/framework/src/Volo.Abp.EventBus.Boxes/Volo.Abp.EventBus.Boxes.csproj +++ b/framework/src/Volo.Abp.EventBus.Boxes/Volo.Abp.EventBus.Boxes.csproj @@ -16,6 +16,7 @@ + diff --git a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs index 43c51c0b73..176f281caa 100644 --- a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs +++ b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs @@ -1,5 +1,6 @@ using System; using System.Threading.Tasks; +using Medallion.Threading; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; @@ -15,17 +16,22 @@ namespace Volo.Abp.EventBus.Boxes protected IServiceProvider ServiceProvider { get; } protected AbpTimer Timer { get; } protected IDistributedEventBus DistributedEventBus { get; } + protected IDistributedLockProvider DistributedLockProvider { get; } protected IEventOutbox Outbox { get; private set; } + protected OutboxConfig OutboxConfig { get; private set; } + protected string DistributedLockName => "Outbox_" + OutboxConfig.Name; public ILogger Logger { get; set; } public OutboxSender( IServiceProvider serviceProvider, AbpTimer timer, - IDistributedEventBus distributedEventBus) + IDistributedEventBus distributedEventBus, + IDistributedLockProvider distributedLockProvider) { ServiceProvider = serviceProvider; Timer = timer; DistributedEventBus = distributedEventBus; + DistributedLockProvider = distributedLockProvider; Timer.Period = 2000; //TODO: Config? Timer.Elapsed += TimerOnElapsed; Logger = NullLogger.Instance; @@ -33,6 +39,7 @@ namespace Volo.Abp.EventBus.Boxes public virtual Task StartAsync(OutboxConfig outboxConfig) { + OutboxConfig = outboxConfig; Outbox = (IEventOutbox)ServiceProvider.GetRequiredService(outboxConfig.ImplementationType); Timer.Start(); return Task.CompletedTask; @@ -51,25 +58,39 @@ namespace Volo.Abp.EventBus.Boxes protected virtual async Task RunAsync() { - while (true) + await using (var handle = await DistributedLockProvider.TryAcquireLockAsync(DistributedLockName)) { - var waitingEvents = await Outbox.GetWaitingEventsAsync(1000); //TODO: Config? - if (waitingEvents.Count <= 0) + if (handle != null) { - break; - } + Logger.LogDebug("Obtained the distributed lock: " + DistributedLockName); + + while (true) + { + var waitingEvents = await Outbox.GetWaitingEventsAsync(1000); //TODO: Config? + if (waitingEvents.Count <= 0) + { + break; + } - Logger.LogInformation($"Found {waitingEvents.Count} events in the outbox."); + Logger.LogInformation($"Found {waitingEvents.Count} events in the outbox."); - foreach (var waitingEvent in waitingEvents) - { - await DistributedEventBus - .AsRawEventPublisher() - .PublishRawAsync(waitingEvent.Id, waitingEvent.EventName, waitingEvent.EventData); + foreach (var waitingEvent in waitingEvents) + { + await DistributedEventBus + .AsRawEventPublisher() + .PublishRawAsync(waitingEvent.Id, waitingEvent.EventName, waitingEvent.EventData); - await Outbox.DeleteAsync(waitingEvent.Id); + await Outbox.DeleteAsync(waitingEvent.Id); - Logger.LogInformation($"Sent the event to the message broker with id = {waitingEvent.Id:N}"); + Logger.LogInformation($"Sent the event to the message broker with id = {waitingEvent.Id:N}"); + } + } + + await Task.Delay(30000); + } + else + { + Logger.LogDebug("Could not obtain the distributed lock: " + DistributedLockName); } } } diff --git a/test/DistEvents/DistDemoApp/DistDemoApp.csproj b/test/DistEvents/DistDemoApp/DistDemoApp.csproj index adfe26ebea..66623bfde4 100644 --- a/test/DistEvents/DistDemoApp/DistDemoApp.csproj +++ b/test/DistEvents/DistDemoApp/DistDemoApp.csproj @@ -6,6 +6,7 @@ + diff --git a/test/DistEvents/DistDemoApp/DistDemoAppModule.cs b/test/DistEvents/DistDemoApp/DistDemoAppModule.cs index 42e82f5e46..c4eab2937f 100644 --- a/test/DistEvents/DistDemoApp/DistDemoAppModule.cs +++ b/test/DistEvents/DistDemoApp/DistDemoAppModule.cs @@ -1,4 +1,7 @@ +using Medallion.Threading; +using Medallion.Threading.Redis; using Microsoft.Extensions.DependencyInjection; +using StackExchange.Redis; using Volo.Abp.Autofac; using Volo.Abp.Domain.Entities.Events.Distributed; using Volo.Abp.EntityFrameworkCore; @@ -21,6 +24,8 @@ namespace DistDemoApp { public override void ConfigureServices(ServiceConfigurationContext context) { + var configuration = context.Services.GetConfiguration(); + context.Services.AddHostedService(); context.Services.AddAbpDbContext(options => @@ -46,6 +51,12 @@ namespace DistDemoApp config.UseDbContext(); }); }); + + context.Services.AddSingleton(sp => + { + var connection = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]); + return new RedisDistributedSynchronizationProvider(connection.GetDatabase()); + }); } } } \ No newline at end of file diff --git a/test/DistEvents/DistDemoApp/appsettings.json b/test/DistEvents/DistDemoApp/appsettings.json index 8f4773ae6a..1ed30c80a9 100644 --- a/test/DistEvents/DistDemoApp/appsettings.json +++ b/test/DistEvents/DistDemoApp/appsettings.json @@ -12,5 +12,8 @@ "ClientName": "DistDemoApp", "ExchangeName": "DistDemo" } + }, + "Redis": { + "Configuration": "127.0.0.1" } } \ No newline at end of file From 79015b0e4e9ad82ff5cac0c9124a10b6a7f1a2b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 8 Sep 2021 15:57:51 +0300 Subject: [PATCH 10/36] Added cancellation tokens --- .../Volo/Abp/EventBus/Boxes/IOutboxSender.cs | 5 +++-- .../Volo/Abp/EventBus/Boxes/OutboxSender.cs | 12 ++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/IOutboxSender.cs b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/IOutboxSender.cs index efc278844a..b9a78060df 100644 --- a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/IOutboxSender.cs +++ b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/IOutboxSender.cs @@ -1,3 +1,4 @@ +using System.Threading; using System.Threading.Tasks; using Volo.Abp.EventBus.Distributed; @@ -5,7 +6,7 @@ namespace Volo.Abp.EventBus.Boxes { public interface IOutboxSender { - Task StartAsync(OutboxConfig outboxConfig); - Task StopAsync(); + Task StartAsync(OutboxConfig outboxConfig, CancellationToken cancellationToken = default); + Task StopAsync(CancellationToken cancellationToken = default); } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs index 176f281caa..94d0175e10 100644 --- a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs +++ b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs @@ -1,4 +1,5 @@ using System; +using System.Threading; using System.Threading.Tasks; using Medallion.Threading; using Microsoft.Extensions.DependencyInjection; @@ -37,17 +38,17 @@ namespace Volo.Abp.EventBus.Boxes Logger = NullLogger.Instance; } - public virtual Task StartAsync(OutboxConfig outboxConfig) + public virtual Task StartAsync(OutboxConfig outboxConfig, CancellationToken cancellationToken = default) { OutboxConfig = outboxConfig; Outbox = (IEventOutbox)ServiceProvider.GetRequiredService(outboxConfig.ImplementationType); - Timer.Start(); + Timer.Start(cancellationToken); return Task.CompletedTask; } - public virtual Task StopAsync() + public virtual Task StopAsync(CancellationToken cancellationToken = default) { - Timer.Stop(); + Timer.Stop(cancellationToken); return Task.CompletedTask; } @@ -85,12 +86,11 @@ namespace Volo.Abp.EventBus.Boxes Logger.LogInformation($"Sent the event to the message broker with id = {waitingEvent.Id:N}"); } } - - await Task.Delay(30000); } else { Logger.LogDebug("Could not obtain the distributed lock: " + DistributedLockName); + await Task.Delay(7000); //TODO: Can we pass a cancellation token to cancel on shutdown? (Config?) } } } From 9593c877e10cce72821018e57137cda66520c724 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Thu, 9 Sep 2021 15:50:33 +0300 Subject: [PATCH 11/36] Save incoming events to inbox --- .../AbpEntityFrameworkCoreModule.cs | 1 + .../DistributedEvents/DbContextEventInbox.cs | 47 ++++++ .../DistributedEvents/DbContextEventOutbox.cs | 6 +- .../EfCoreInboxConfigExtensions.cs | 13 ++ ...entInboxDbContextModelBuilderExtensions.cs | 21 +++ .../DistributedEvents/IDbContextEventInbox.cs | 10 ++ .../DistributedEvents/IHasEventInbox.cs | 9 ++ .../DistributedEvents/IHasEventOutbox.cs | 2 +- .../DistributedEvents/IncomingEventRecord.cs | 52 ++++++ .../Kafka/KafkaDistributedEventBus.cs | 5 + .../RabbitMq/RabbitMqDistributedEventBus.cs | 9 +- .../AbpDistributedEventBusOptions.cs | 7 +- .../Distributed/DistributedEventBusBase.cs | 43 ++++- .../Abp/EventBus/Distributed/IEventInbox.cs | 12 ++ .../Abp/EventBus/Distributed/InboxConfig.cs | 28 ++++ .../Distributed/InboxConfigDictionary.cs | 19 +++ .../EventBus/Distributed/IncomingEventInfo.cs | 40 +++++ ...onfigList.cs => OutboxConfigDictionary.cs} | 7 +- .../EventBus/Distributed/OutgoingEventInfo.cs | 2 +- .../DistDemoApp/DistDemoAppModule.cs | 7 +- .../20210909113934_Added_Inbox.Designer.cs | 149 ++++++++++++++++++ .../Migrations/20210909113934_Added_Inbox.cs | 32 ++++ .../Migrations/TodoDbContextModelSnapshot.cs | 27 ++++ test/DistEvents/DistDemoApp/TodoDbContext.cs | 6 +- 24 files changed, 537 insertions(+), 17 deletions(-) create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventInbox.cs create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/EfCoreInboxConfigExtensions.cs create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/EventInboxDbContextModelBuilderExtensions.cs create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IDbContextEventInbox.cs create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IHasEventInbox.cs create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IncomingEventRecord.cs create mode 100644 framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IEventInbox.cs create mode 100644 framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/InboxConfig.cs create mode 100644 framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/InboxConfigDictionary.cs create mode 100644 framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IncomingEventInfo.cs rename framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/{OutboxConfigList.cs => OutboxConfigDictionary.cs} (61%) create mode 100644 test/DistEvents/DistDemoApp/Migrations/20210909113934_Added_Inbox.Designer.cs create mode 100644 test/DistEvents/DistDemoApp/Migrations/20210909113934_Added_Inbox.cs diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreModule.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreModule.cs index 79db928711..90b541bc73 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreModule.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreModule.cs @@ -28,6 +28,7 @@ namespace Volo.Abp.EntityFrameworkCore context.Services.TryAddTransient(typeof(IDbContextProvider<>), typeof(UnitOfWorkDbContextProvider<>)); context.Services.AddTransient(typeof(IDbContextEventOutbox<>), typeof(DbContextEventOutbox<>)); + context.Services.AddTransient(typeof(IDbContextEventInbox<>), typeof(DbContextEventInbox<>)); } } } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventInbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventInbox.cs new file mode 100644 index 0000000000..aeaeebe948 --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventInbox.cs @@ -0,0 +1,47 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.Uow; + +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public class DbContextEventInbox : IDbContextEventInbox + where TDbContext : IHasEventInbox + { + protected IDbContextProvider DbContextProvider { get; } + + public DbContextEventInbox( + IDbContextProvider dbContextProvider) + { + DbContextProvider = dbContextProvider; + } + + [UnitOfWork] + public virtual async Task EnqueueAsync(IncomingEventInfo incomingEvent) + { + var dbContext = (IHasEventInbox) await DbContextProvider.GetDbContextAsync(); + dbContext.IncomingEvents.Add( + new IncomingEventRecord(incomingEvent) + ); + } + + [UnitOfWork] + public virtual async Task> GetWaitingEventsAsync(int maxCount) + { + var dbContext = (IHasEventInbox) await DbContextProvider.GetDbContextAsync(); + + var outgoingEventRecords = await dbContext + .IncomingEvents + .AsNoTracking() + .OrderBy(x => x.CreationTime) + .Take(maxCount) + .ToListAsync(); + + return outgoingEventRecords + .Select(x => x.ToIncomingEventInfo()) + .ToList(); + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventOutbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventOutbox.cs index b8d26fa357..89e10bbd75 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventOutbox.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventOutbox.cs @@ -23,7 +23,7 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents public virtual async Task EnqueueAsync(OutgoingEventInfo outgoingEvent) { var dbContext = (IHasEventOutbox) await DbContextProvider.GetDbContextAsync(); - dbContext.OutgoingEventRecords.Add( + dbContext.OutgoingEvents.Add( new OutgoingEventRecord(outgoingEvent) ); } @@ -34,7 +34,7 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents var dbContext = (IHasEventOutbox) await DbContextProvider.GetDbContextAsync(); var outgoingEventRecords = await dbContext - .OutgoingEventRecords + .OutgoingEvents .AsNoTracking() .OrderBy(x => x.CreationTime) .Take(maxCount) @@ -49,7 +49,7 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents public virtual async Task DeleteAsync(Guid id) { var dbContext = (IHasEventOutbox) await DbContextProvider.GetDbContextAsync(); - var outgoingEvent = await dbContext.OutgoingEventRecords.FindAsync(id); + var outgoingEvent = await dbContext.OutgoingEvents.FindAsync(id); if (outgoingEvent != null) { dbContext.Remove(outgoingEvent); diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/EfCoreInboxConfigExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/EfCoreInboxConfigExtensions.cs new file mode 100644 index 0000000000..182c7b20ba --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/EfCoreInboxConfigExtensions.cs @@ -0,0 +1,13 @@ +using Volo.Abp.EventBus.Distributed; + +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public static class EfCoreInboxConfigExtensions + { + public static void UseDbContext(this InboxConfig outboxConfig) + where TDbContext : IHasEventInbox + { + outboxConfig.ImplementationType = typeof(IDbContextEventInbox); + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/EventInboxDbContextModelBuilderExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/EventInboxDbContextModelBuilderExtensions.cs new file mode 100644 index 0000000000..d3e3a6cc26 --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/EventInboxDbContextModelBuilderExtensions.cs @@ -0,0 +1,21 @@ +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore; +using Volo.Abp.Data; +using Volo.Abp.EntityFrameworkCore.Modeling; + +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public static class EventInboxDbContextModelBuilderExtensions + { + public static void ConfigureEventInbox([NotNull] this ModelBuilder builder) + { + builder.Entity(b => + { + b.ToTable(AbpCommonDbProperties.DbTablePrefix + "EventInbox", AbpCommonDbProperties.DbSchema); + b.ConfigureByConvention(); + b.Property(x => x.EventName).IsRequired().HasMaxLength(IncomingEventRecord.MaxEventNameLength); + b.Property(x => x.EventData).IsRequired(); + }); + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IDbContextEventInbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IDbContextEventInbox.cs new file mode 100644 index 0000000000..81b51bc11d --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IDbContextEventInbox.cs @@ -0,0 +1,10 @@ +using Volo.Abp.EventBus.Distributed; + +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public interface IDbContextEventInbox : IEventInbox + where TDbContext : IHasEventInbox + { + + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IHasEventInbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IHasEventInbox.cs new file mode 100644 index 0000000000..f6836a0c19 --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IHasEventInbox.cs @@ -0,0 +1,9 @@ +using Microsoft.EntityFrameworkCore; + +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public interface IHasEventInbox : IEfCoreDbContext + { + DbSet IncomingEvents { get; set; } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IHasEventOutbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IHasEventOutbox.cs index e7e60e3800..5e2934d591 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IHasEventOutbox.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IHasEventOutbox.cs @@ -4,6 +4,6 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents { public interface IHasEventOutbox : IEfCoreDbContext { - DbSet OutgoingEventRecords { get; set; } + DbSet OutgoingEvents { get; set; } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IncomingEventRecord.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IncomingEventRecord.cs new file mode 100644 index 0000000000..95bc5fa9d4 --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IncomingEventRecord.cs @@ -0,0 +1,52 @@ +using System; +using Volo.Abp.Auditing; +using Volo.Abp.Data; +using Volo.Abp.Domain.Entities; +using Volo.Abp.EventBus.Distributed; + +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public class IncomingEventRecord : + BasicAggregateRoot, + IHasExtraProperties, + IHasCreationTime + { + public static int MaxEventNameLength { get; set; } = 256; + + public ExtraPropertyDictionary ExtraProperties { get; private set; } + + public string EventName { get; private set; } + + public byte[] EventData { get; private set; } + + public DateTime CreationTime { get; private set; } + + protected IncomingEventRecord() + { + ExtraProperties = new ExtraPropertyDictionary(); + this.SetDefaultsForExtraProperties(); + } + + public IncomingEventRecord( + IncomingEventInfo eventInfo) + : base(eventInfo.Id) + { + EventName = eventInfo.EventName; + EventData = eventInfo.EventData; + CreationTime = eventInfo.CreationTime; + + ExtraProperties = new ExtraPropertyDictionary(); + this.SetDefaultsForExtraProperties(); + } + + public IncomingEventInfo ToIncomingEventInfo() + { + return new IncomingEventInfo( + Id, + EventName, + EventData, + CreationTime + ); + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs b/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs index 9e62b47fed..5977cf159d 100644 --- a/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs +++ b/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs @@ -86,6 +86,11 @@ namespace Volo.Abp.EventBus.Kafka { return; } + + if (await AddToInboxAsync(eventName, eventType, message.Value)) + { + return; + } var eventData = Serializer.Deserialize(message.Value, eventType); diff --git a/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs b/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs index f51cd6821d..59fe5e4b99 100644 --- a/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs +++ b/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs @@ -105,7 +105,14 @@ namespace Volo.Abp.EventBus.RabbitMq return; } - var eventData = Serializer.Deserialize(ea.Body.ToArray(), eventType); + var eventBytes = ea.Body.ToArray(); + + if (await AddToInboxAsync(eventName, eventType, eventBytes)) + { + return; + } + + var eventData = Serializer.Deserialize(eventBytes, eventType); await TriggerHandlersAsync(eventType, eventData, errorContext => { diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/AbpDistributedEventBusOptions.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/AbpDistributedEventBusOptions.cs index 052e421511..896dfd4f7d 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/AbpDistributedEventBusOptions.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/AbpDistributedEventBusOptions.cs @@ -6,12 +6,15 @@ namespace Volo.Abp.EventBus.Distributed { public ITypeList Handlers { get; } - public OutboxConfigList Outboxes { get; } + public OutboxConfigDictionary Outboxes { get; } + + public InboxConfigDictionary Inboxes { get; } public AbpDistributedEventBusOptions() { Handlers = new TypeList(); - Outboxes = new OutboxConfigList(); + Outboxes = new OutboxConfigDictionary(); + Inboxes = new InboxConfigDictionary(); } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs index 786f58fe47..dd4ca189ab 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; @@ -17,14 +18,14 @@ namespace Volo.Abp.EventBus.Distributed protected DistributedEventBusBase( IServiceScopeFactory serviceScopeFactory, - ICurrentTenant currentTenant, + ICurrentTenant currentTenant, IUnitOfWorkManager unitOfWorkManager, IEventErrorHandler errorHandler, IOptions abpDistributedEventBusOptions, IGuidGenerator guidGenerator, IClock clock - ) : base( - serviceScopeFactory, + ) : base( + serviceScopeFactory, currentTenant, unitOfWorkManager, errorHandler) @@ -67,7 +68,7 @@ namespace Volo.Abp.EventBus.Distributed ); return; } - + if (useOutbox) { if (await AddToOutboxAsync(eventType, eventData)) @@ -106,10 +107,42 @@ namespace Volo.Abp.EventBus.Distributed return true; } } - + return false; } + protected async Task AddToInboxAsync( + string eventName, + Type eventType, + byte[] eventBytes) + { + if (AbpDistributedEventBusOptions.Inboxes.Count <= 0) + { + return false; + } + + using (var scope = ServiceScopeFactory.CreateScope()) + { + foreach (var inboxConfig in AbpDistributedEventBusOptions.Inboxes.Values) + { + if (inboxConfig.EventSelector == null || inboxConfig.EventSelector(eventType)) + { + var eventInbox = (IEventInbox) scope.ServiceProvider.GetRequiredService(inboxConfig.ImplementationType); + await eventInbox.EnqueueAsync( + new IncomingEventInfo( + GuidGenerator.Create(), + eventName, + eventBytes, + Clock.Now + ) + ); + } + } + } + + return true; + } + protected abstract byte[] Serialize(object eventData); } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IEventInbox.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IEventInbox.cs new file mode 100644 index 0000000000..dddedab2c0 --- /dev/null +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IEventInbox.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Volo.Abp.EventBus.Distributed +{ + public interface IEventInbox + { + Task EnqueueAsync(IncomingEventInfo incomingEvent); + + Task> GetWaitingEventsAsync(int maxCount); + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/InboxConfig.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/InboxConfig.cs new file mode 100644 index 0000000000..5f708fdb6f --- /dev/null +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/InboxConfig.cs @@ -0,0 +1,28 @@ +using System; +using JetBrains.Annotations; + +namespace Volo.Abp.EventBus.Distributed +{ + public class InboxConfig + { + [NotNull] + public string Name { get; } + + public Type ImplementationType { get; set; } + + public Func EventSelector { get; set; } + + public Func HandlerSelector { get; set; } + + /// + /// Used to enable/disable processing incoming events. + /// Default: true. + /// + public bool IsProcessingEnabled { get; set; } = true; + + public InboxConfig([NotNull] string name) + { + Name = Check.NotNullOrWhiteSpace(name, nameof(name)); + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/InboxConfigDictionary.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/InboxConfigDictionary.cs new file mode 100644 index 0000000000..9909181138 --- /dev/null +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/InboxConfigDictionary.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; + +namespace Volo.Abp.EventBus.Distributed +{ + public class InboxConfigDictionary : Dictionary + { + public void Configure(Action configAction) + { + Configure("Default", configAction); + } + + public void Configure(string outboxName, Action configAction) + { + var outboxConfig = this.GetOrAdd(outboxName, () => new InboxConfig(outboxName)); + configAction(outboxConfig); + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IncomingEventInfo.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IncomingEventInfo.cs new file mode 100644 index 0000000000..7cd628cf91 --- /dev/null +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IncomingEventInfo.cs @@ -0,0 +1,40 @@ +using System; +using Volo.Abp.Data; + +namespace Volo.Abp.EventBus.Distributed +{ + public class IncomingEventInfo : IHasExtraProperties + { + public static int MaxEventNameLength { get; set; } = 256; + + public ExtraPropertyDictionary ExtraProperties { get; protected set; } + + public Guid Id { get; } + + public string EventName { get; } + + public byte[] EventData { get; } + + public DateTime CreationTime { get; } + + protected IncomingEventInfo() + { + ExtraProperties = new ExtraPropertyDictionary(); + this.SetDefaultsForExtraProperties(); + } + + public IncomingEventInfo( + Guid id, + string eventName, + byte[] eventData, + DateTime creationTime) + { + Id = id; + EventName = Check.NotNullOrWhiteSpace(eventName, nameof(eventName), MaxEventNameLength); + EventData = eventData; + CreationTime = creationTime; + ExtraProperties = new ExtraPropertyDictionary(); + this.SetDefaultsForExtraProperties(); + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/OutboxConfigList.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/OutboxConfigDictionary.cs similarity index 61% rename from framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/OutboxConfigList.cs rename to framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/OutboxConfigDictionary.cs index 162ceef6ff..be5b838363 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/OutboxConfigList.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/OutboxConfigDictionary.cs @@ -3,8 +3,13 @@ using System.Collections.Generic; namespace Volo.Abp.EventBus.Distributed { - public class OutboxConfigList : Dictionary + public class OutboxConfigDictionary : Dictionary { + public void Configure(Action configAction) + { + Configure("Default", configAction); + } + public void Configure(string outboxName, Action configAction) { var outboxConfig = this.GetOrAdd(outboxName, () => new OutboxConfig(outboxName)); diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/OutgoingEventInfo.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/OutgoingEventInfo.cs index 91cf806ba9..643db882d2 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/OutgoingEventInfo.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/OutgoingEventInfo.cs @@ -30,7 +30,7 @@ namespace Volo.Abp.EventBus.Distributed DateTime creationTime) { Id = id; - EventName = eventName; + EventName = Check.NotNullOrWhiteSpace(eventName, nameof(eventName), MaxEventNameLength); EventData = eventData; CreationTime = creationTime; ExtraProperties = new ExtraPropertyDictionary(); diff --git a/test/DistEvents/DistDemoApp/DistDemoAppModule.cs b/test/DistEvents/DistDemoApp/DistDemoAppModule.cs index c4eab2937f..b7fbe1c930 100644 --- a/test/DistEvents/DistDemoApp/DistDemoAppModule.cs +++ b/test/DistEvents/DistDemoApp/DistDemoAppModule.cs @@ -46,7 +46,12 @@ namespace DistDemoApp Configure(options => { - options.Outboxes.Configure("Default", config => + options.Outboxes.Configure(config => + { + config.UseDbContext(); + }); + + options.Inboxes.Configure(config => { config.UseDbContext(); }); diff --git a/test/DistEvents/DistDemoApp/Migrations/20210909113934_Added_Inbox.Designer.cs b/test/DistEvents/DistDemoApp/Migrations/20210909113934_Added_Inbox.Designer.cs new file mode 100644 index 0000000000..e02cee4b76 --- /dev/null +++ b/test/DistEvents/DistDemoApp/Migrations/20210909113934_Added_Inbox.Designer.cs @@ -0,0 +1,149 @@ +// +using System; +using DistDemoApp; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Volo.Abp.EntityFrameworkCore; + +namespace DistDemoApp.Migrations +{ + [DbContext(typeof(TodoDbContext))] + [Migration("20210909113934_Added_Inbox")] + partial class Added_Inbox + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) + .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("ProductVersion", "5.0.9") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("DistDemoApp.TodoItem", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Text") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.ToTable("TodoItems"); + }); + + modelBuilder.Entity("DistDemoApp.TodoSummary", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Day") + .HasColumnType("tinyint"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Month") + .HasColumnType("tinyint"); + + b.Property("TotalCount") + .HasColumnType("int"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("TodoSummaries"); + }); + + modelBuilder.Entity("Volo.Abp.EntityFrameworkCore.DistributedEvents.IncomingEventRecord", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("EventData") + .IsRequired() + .HasColumnType("varbinary(max)"); + + b.Property("EventName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.HasKey("Id"); + + b.ToTable("AbpEventInbox"); + }); + + modelBuilder.Entity("Volo.Abp.EntityFrameworkCore.DistributedEvents.OutgoingEventRecord", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("EventData") + .IsRequired() + .HasColumnType("varbinary(max)"); + + b.Property("EventName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.HasKey("Id"); + + b.ToTable("AbpEventOutbox"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/test/DistEvents/DistDemoApp/Migrations/20210909113934_Added_Inbox.cs b/test/DistEvents/DistDemoApp/Migrations/20210909113934_Added_Inbox.cs new file mode 100644 index 0000000000..f154ee3ff6 --- /dev/null +++ b/test/DistEvents/DistDemoApp/Migrations/20210909113934_Added_Inbox.cs @@ -0,0 +1,32 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace DistDemoApp.Migrations +{ + public partial class Added_Inbox : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "AbpEventInbox", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true), + EventName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + EventData = table.Column(type: "varbinary(max)", nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpEventInbox", x => x.Id); + }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AbpEventInbox"); + } + } +} diff --git a/test/DistEvents/DistDemoApp/Migrations/TodoDbContextModelSnapshot.cs b/test/DistEvents/DistDemoApp/Migrations/TodoDbContextModelSnapshot.cs index f1b3330485..3423520512 100644 --- a/test/DistEvents/DistDemoApp/Migrations/TodoDbContextModelSnapshot.cs +++ b/test/DistEvents/DistDemoApp/Migrations/TodoDbContextModelSnapshot.cs @@ -88,6 +88,33 @@ namespace DistDemoApp.Migrations b.ToTable("TodoSummaries"); }); + modelBuilder.Entity("Volo.Abp.EntityFrameworkCore.DistributedEvents.IncomingEventRecord", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("EventData") + .IsRequired() + .HasColumnType("varbinary(max)"); + + b.Property("EventName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.HasKey("Id"); + + b.ToTable("AbpEventInbox"); + }); + modelBuilder.Entity("Volo.Abp.EntityFrameworkCore.DistributedEvents.OutgoingEventRecord", b => { b.Property("Id") diff --git a/test/DistEvents/DistDemoApp/TodoDbContext.cs b/test/DistEvents/DistDemoApp/TodoDbContext.cs index 3db006535a..5a1ddd2c3f 100644 --- a/test/DistEvents/DistDemoApp/TodoDbContext.cs +++ b/test/DistEvents/DistDemoApp/TodoDbContext.cs @@ -5,11 +5,12 @@ using Volo.Abp.EntityFrameworkCore.DistributedEvents; namespace DistDemoApp { - public class TodoDbContext : AbpDbContext, IHasEventOutbox + public class TodoDbContext : AbpDbContext, IHasEventOutbox, IHasEventInbox { public DbSet TodoItems { get; set; } public DbSet TodoSummaries { get; set; } - public DbSet OutgoingEventRecords { get; set; } + public DbSet OutgoingEvents { get; set; } + public DbSet IncomingEvents { get; set; } public TodoDbContext(DbContextOptions options) : base(options) @@ -22,6 +23,7 @@ namespace DistDemoApp base.OnModelCreating(modelBuilder); modelBuilder.ConfigureEventOutbox(); + modelBuilder.ConfigureEventInbox(); modelBuilder.Entity(b => { From 8af7ccdbaf499004a9506ac643bcba4566505eb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Thu, 9 Sep 2021 21:26:14 +0300 Subject: [PATCH 12/36] Implemented initial inbox processing logic --- .../DistributedEvents/DbContextEventInbox.cs | 21 ++- .../DistributedEvents/DbContextEventOutbox.cs | 1 + .../DistributedEvents/IncomingEventRecord.cs | 10 ++ .../EventBus/Boxes/AbpEventBusBoxesModule.cs | 1 + .../Abp/EventBus/Boxes/IInboxProcessor.cs | 13 ++ .../Volo/Abp/EventBus/Boxes/IOutboxSender.cs | 1 + .../Abp/EventBus/Boxes/InboxProcessManager.cs | 48 ++++++ .../Volo/Abp/EventBus/Boxes/InboxProcessor.cs | 111 +++++++++++++ .../Abp/EventBus/Boxes/OutboxSenderManager.cs | 4 +- .../Kafka/KafkaDistributedEventBus.cs | 17 ++ .../RabbitMq/RabbitMqDistributedEventBus.cs | 21 ++- .../Rebus/RebusDistributedEventBus.cs | 6 + .../Distributed/DistributedEventBusBase.cs | 2 + .../Abp/EventBus/Distributed/IEventInbox.cs | 5 +- .../Distributed/IRawEventPublisher.cs | 7 +- .../Volo/Abp/EventBus/EventBusBase.cs | 13 ++ ...51_Added_Inbox_Process_Columns.Designer.cs | 155 ++++++++++++++++++ ...10909182251_Added_Inbox_Process_Columns.cs | 35 ++++ .../Migrations/TodoDbContextModelSnapshot.cs | 6 + 19 files changed, 470 insertions(+), 7 deletions(-) create mode 100644 framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/IInboxProcessor.cs create mode 100644 framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/InboxProcessManager.cs create mode 100644 framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/InboxProcessor.cs create mode 100644 test/DistEvents/DistDemoApp/Migrations/20210909182251_Added_Inbox_Process_Columns.Designer.cs create mode 100644 test/DistEvents/DistDemoApp/Migrations/20210909182251_Added_Inbox_Process_Columns.cs diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventInbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventInbox.cs index aeaeebe948..df45d50ae5 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventInbox.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventInbox.cs @@ -1,8 +1,10 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Volo.Abp.EventBus.Distributed; +using Volo.Abp.Timing; using Volo.Abp.Uow; namespace Volo.Abp.EntityFrameworkCore.DistributedEvents @@ -11,11 +13,14 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents where TDbContext : IHasEventInbox { protected IDbContextProvider DbContextProvider { get; } + protected IClock Clock { get; } public DbContextEventInbox( - IDbContextProvider dbContextProvider) + IDbContextProvider dbContextProvider, + IClock clock) { DbContextProvider = dbContextProvider; + Clock = clock; } [UnitOfWork] @@ -35,6 +40,7 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents var outgoingEventRecords = await dbContext .IncomingEvents .AsNoTracking() + .Where(x => !x.Processed) .OrderBy(x => x.CreationTime) .Take(maxCount) .ToListAsync(); @@ -43,5 +49,16 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents .Select(x => x.ToIncomingEventInfo()) .ToList(); } + + public async Task MarkAsProcessedAsync(Guid id) + { + //TODO: Optimize? + var dbContext = (IHasEventInbox) await DbContextProvider.GetDbContextAsync(); + var incomingEvent = await dbContext.IncomingEvents.FindAsync(id); + if (incomingEvent != null) + { + incomingEvent.MarkAsProcessed(Clock.Now); + } + } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventOutbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventOutbox.cs index 89e10bbd75..a785ad7ce5 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventOutbox.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventOutbox.cs @@ -48,6 +48,7 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents [UnitOfWork] public virtual async Task DeleteAsync(Guid id) { + //TODO: Optimize? var dbContext = (IHasEventOutbox) await DbContextProvider.GetDbContextAsync(); var outgoingEvent = await dbContext.OutgoingEvents.FindAsync(id); if (outgoingEvent != null) diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IncomingEventRecord.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IncomingEventRecord.cs index 95bc5fa9d4..62c2781b48 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IncomingEventRecord.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IncomingEventRecord.cs @@ -20,6 +20,10 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents public byte[] EventData { get; private set; } public DateTime CreationTime { get; private set; } + + public bool Processed { get; set; } + + public DateTime? ProcessedTime { get; set; } protected IncomingEventRecord() { @@ -48,5 +52,11 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents CreationTime ); } + + public void MarkAsProcessed(DateTime processedTime) + { + Processed = true; + ProcessedTime = processedTime; + } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/AbpEventBusBoxesModule.cs b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/AbpEventBusBoxesModule.cs index 9445f1de08..8e5eeb2c60 100644 --- a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/AbpEventBusBoxesModule.cs +++ b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/AbpEventBusBoxesModule.cs @@ -12,6 +12,7 @@ namespace Volo.Abp.EventBus.Boxes public override void OnApplicationInitialization(ApplicationInitializationContext context) { context.AddBackgroundWorker(); + context.AddBackgroundWorker(); } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/IInboxProcessor.cs b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/IInboxProcessor.cs new file mode 100644 index 0000000000..e93ff0cc2e --- /dev/null +++ b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/IInboxProcessor.cs @@ -0,0 +1,13 @@ +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp.EventBus.Distributed; + +namespace Volo.Abp.EventBus.Boxes +{ + public interface IInboxProcessor + { + Task StartAsync(InboxConfig inboxConfig, CancellationToken cancellationToken = default); + + Task StopAsync(CancellationToken cancellationToken = default); + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/IOutboxSender.cs b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/IOutboxSender.cs index b9a78060df..4a700eb823 100644 --- a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/IOutboxSender.cs +++ b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/IOutboxSender.cs @@ -7,6 +7,7 @@ namespace Volo.Abp.EventBus.Boxes public interface IOutboxSender { Task StartAsync(OutboxConfig outboxConfig, CancellationToken cancellationToken = default); + Task StopAsync(CancellationToken cancellationToken = default); } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/InboxProcessManager.cs b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/InboxProcessManager.cs new file mode 100644 index 0000000000..310cad2886 --- /dev/null +++ b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/InboxProcessManager.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Volo.Abp.BackgroundWorkers; +using Volo.Abp.EventBus.Distributed; + +namespace Volo.Abp.EventBus.Boxes +{ + public class InboxProcessManager : IBackgroundWorker + { + protected AbpDistributedEventBusOptions Options { get; } + protected IServiceProvider ServiceProvider { get; } + protected List Processors { get; } + + public InboxProcessManager( + IOptions options, + IServiceProvider serviceProvider) + { + ServiceProvider = serviceProvider; + Options = options.Value; + Processors = new List(); + } + + public async Task StartAsync(CancellationToken cancellationToken = default) + { + foreach (var inboxConfig in Options.Inboxes.Values) + { + if (inboxConfig.IsProcessingEnabled) + { + var processor = ServiceProvider.GetRequiredService(); + await processor.StartAsync(inboxConfig, cancellationToken); + Processors.Add(processor); + } + } + } + + public async Task StopAsync(CancellationToken cancellationToken = default) + { + foreach (var processor in Processors) + { + await processor.StopAsync(cancellationToken); + } + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/InboxProcessor.cs b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/InboxProcessor.cs new file mode 100644 index 0000000000..4725e85d51 --- /dev/null +++ b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/InboxProcessor.cs @@ -0,0 +1,111 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using Medallion.Threading; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Volo.Abp.DependencyInjection; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.Threading; +using Volo.Abp.Uow; + +namespace Volo.Abp.EventBus.Boxes +{ + public class InboxProcessor : IInboxProcessor, ITransientDependency + { + protected IServiceProvider ServiceProvider { get; } + protected AbpTimer Timer { get; } + protected IDistributedEventBus DistributedEventBus { get; } + protected IDistributedLockProvider DistributedLockProvider { get; } + protected IUnitOfWorkManager UnitOfWorkManager { get; } + protected IEventInbox Inbox { get; private set; } + protected InboxConfig InboxConfig { get; private set; } + + protected string DistributedLockName => "Inbox_" + InboxConfig.Name; + public ILogger Logger { get; set; } + + public InboxProcessor( + IServiceProvider serviceProvider, + AbpTimer timer, + IDistributedEventBus distributedEventBus, + IDistributedLockProvider distributedLockProvider, + IUnitOfWorkManager unitOfWorkManager) + { + ServiceProvider = serviceProvider; + Timer = timer; + DistributedEventBus = distributedEventBus; + DistributedLockProvider = distributedLockProvider; + UnitOfWorkManager = unitOfWorkManager; + Timer.Period = 2000; //TODO: Config? + Timer.Elapsed += TimerOnElapsed; + Logger = NullLogger.Instance; + } + + private void TimerOnElapsed(object sender, EventArgs e) + { + AsyncHelper.RunSync(RunAsync); + } + + public Task StartAsync(InboxConfig inboxConfig, CancellationToken cancellationToken = default) + { + InboxConfig = inboxConfig; + Inbox = (IEventInbox)ServiceProvider.GetRequiredService(inboxConfig.ImplementationType); + Timer.Start(cancellationToken); + return Task.CompletedTask; + } + + public Task StopAsync(CancellationToken cancellationToken = default) + { + Timer.Stop(cancellationToken); + return Task.CompletedTask; + } + + protected virtual async Task RunAsync() + { + await using (var handle = await DistributedLockProvider.TryAcquireLockAsync(DistributedLockName)) + { + if (handle != null) + { + Logger.LogDebug("Obtained the distributed lock: " + DistributedLockName); + + while (true) + { + var waitingEvents = await Inbox.GetWaitingEventsAsync(1000); //TODO: Config? + if (waitingEvents.Count <= 0) + { + break; + } + + Logger.LogInformation($"Found {waitingEvents.Count} events in the inbox."); + + foreach (var waitingEvent in waitingEvents) + { + using (var uow = UnitOfWorkManager.Begin(isTransactional: true, requiresNew: true)) + { + await DistributedEventBus + .AsRawEventPublisher() + .ProcessRawAsync(waitingEvent.EventName, waitingEvent.EventData); + + /* + await DistributedEventBus + .AsRawEventPublisher() + .PublishRawAsync(waitingEvent.Id, waitingEvent.EventName, waitingEvent.EventData); + */ + await Inbox.MarkAsProcessedAsync(waitingEvent.Id); + await uow.CompleteAsync(); + } + + Logger.LogInformation($"Processed the incoming event with id = {waitingEvent.Id:N}"); + } + } + } + else + { + Logger.LogDebug("Could not obtain the distributed lock: " + DistributedLockName); + await Task.Delay(7000); //TODO: Can we pass a cancellation token to cancel on shutdown? (Config?) + } + } + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSenderManager.cs b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSenderManager.cs index 617913e42f..6d403bd243 100644 --- a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSenderManager.cs +++ b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSenderManager.cs @@ -31,7 +31,7 @@ namespace Volo.Abp.EventBus.Boxes if (outboxConfig.IsSendingEnabled) { var sender = ServiceProvider.GetRequiredService(); - await sender.StartAsync(outboxConfig); + await sender.StartAsync(outboxConfig, cancellationToken); Senders.Add(sender); } } @@ -41,7 +41,7 @@ namespace Volo.Abp.EventBus.Boxes { foreach (var sender in Senders) { - await sender.StopAsync(); + await sender.StopAsync(cancellationToken); } } } diff --git a/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs b/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs index 5977cf159d..ae20ab1dd0 100644 --- a/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs +++ b/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs @@ -211,6 +211,23 @@ namespace Volo.Abp.EventBus.Kafka ); } + public override async Task ProcessRawAsync(string eventName, byte[] eventDataBytes) + { + var eventType = EventTypes.GetOrDefault(eventName); + if (eventType == null) + { + return; + } + + var eventData = Serializer.Deserialize(eventDataBytes, eventType); + var exceptions = new List(); + await TriggerHandlersAsync(eventType, eventData, exceptions); + if (exceptions.Any()) + { + ThrowOriginalExceptions(eventType, exceptions); + } + } + protected override byte[] Serialize(object eventData) { return Serializer.Serialize(eventData); diff --git a/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs b/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs index 59fe5e4b99..d3d74a048c 100644 --- a/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs +++ b/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs @@ -123,7 +123,7 @@ namespace Volo.Abp.EventBus.RabbitMq retryAttempt = (int)ea.BasicProperties.Headers[EventErrorHandlerBase.RetryAttemptKey]; } - errorContext.EventData = Serializer.Deserialize(ea.Body.ToArray(), eventType); + errorContext.EventData = Serializer.Deserialize(eventBytes, eventType); errorContext.SetProperty(EventErrorHandlerBase.HeadersKey, ea.BasicProperties); errorContext.SetProperty(EventErrorHandlerBase.RetryAttemptKey, retryAttempt); }); @@ -217,6 +217,25 @@ namespace Volo.Abp.EventBus.RabbitMq return PublishAsync(eventName, eventData, null, eventId: eventId); } + public override async Task ProcessRawAsync(string eventName, byte[] eventDataBytes) + { + //TODO: We have a duplication in logic and also with the kafka side! + + var eventType = EventTypes.GetOrDefault(eventName); + if (eventType == null) + { + return; + } + + var eventData = Serializer.Deserialize(eventDataBytes, eventType); + var exceptions = new List(); + await TriggerHandlersAsync(eventType, eventData, exceptions); + if (exceptions.Any()) + { + ThrowOriginalExceptions(eventType, exceptions); + } + } + protected override byte[] Serialize(object eventData) { return Serializer.Serialize(eventData); diff --git a/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventBus.cs b/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventBus.cs index 07995d67dd..bbe80d9866 100644 --- a/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventBus.cs +++ b/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventBus.cs @@ -194,6 +194,12 @@ namespace Volo.Abp.EventBus.Rebus throw new NotImplementedException(); } + public override Task ProcessRawAsync(string eventName, byte[] eventDataBytes) + { + /* TODO: IMPLEMENT! */ + throw new NotImplementedException(); + } + protected override byte[] Serialize(object eventData) { return Serializer.Serialize(eventData); diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs index dd4ca189ab..a436294e88 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs @@ -81,6 +81,7 @@ namespace Volo.Abp.EventBus.Distributed } public abstract Task PublishRawAsync(Guid eventId, string eventName, byte[] eventData); + public abstract Task ProcessRawAsync(string eventName, byte[] eventDataBytes); private async Task AddToOutboxAsync(Type eventType, object eventData) { @@ -128,6 +129,7 @@ namespace Volo.Abp.EventBus.Distributed if (inboxConfig.EventSelector == null || inboxConfig.EventSelector(eventType)) { var eventInbox = (IEventInbox) scope.ServiceProvider.GetRequiredService(inboxConfig.ImplementationType); + //TODO: Check if event was received before!! await eventInbox.EnqueueAsync( new IncomingEventInfo( GuidGenerator.Create(), diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IEventInbox.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IEventInbox.cs index dddedab2c0..137a410afa 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IEventInbox.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IEventInbox.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Threading.Tasks; namespace Volo.Abp.EventBus.Distributed @@ -8,5 +9,7 @@ namespace Volo.Abp.EventBus.Distributed Task EnqueueAsync(IncomingEventInfo incomingEvent); Task> GetWaitingEventsAsync(int maxCount); + + Task MarkAsProcessedAsync(Guid id); } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IRawEventPublisher.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IRawEventPublisher.cs index f53eb2b78b..5f96b818b7 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IRawEventPublisher.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IRawEventPublisher.cs @@ -3,11 +3,16 @@ using System.Threading.Tasks; namespace Volo.Abp.EventBus.Distributed { - public interface IRawEventPublisher + public interface IRawEventPublisher //TODO: Rename: ISupportsEventBoxes { Task PublishRawAsync( Guid eventId, string eventName, byte[] eventData); + + Task ProcessRawAsync( + string eventName, + byte[] eventDataBytes + ); } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventBusBase.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventBusBase.cs index c8b7eb6790..c4a61b24a6 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventBusBase.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventBusBase.cs @@ -162,6 +162,19 @@ namespace Volo.Abp.EventBus } } } + + protected void ThrowOriginalExceptions(Type eventType, List exceptions) + { + if (exceptions.Count == 1) + { + exceptions[0].ReThrow(); + } + + throw new AggregateException( + "More than one error has occurred while triggering the event: " + eventType, + exceptions + ); + } protected virtual void SubscribeHandlers(ITypeList handlers) { diff --git a/test/DistEvents/DistDemoApp/Migrations/20210909182251_Added_Inbox_Process_Columns.Designer.cs b/test/DistEvents/DistDemoApp/Migrations/20210909182251_Added_Inbox_Process_Columns.Designer.cs new file mode 100644 index 0000000000..02404db39f --- /dev/null +++ b/test/DistEvents/DistDemoApp/Migrations/20210909182251_Added_Inbox_Process_Columns.Designer.cs @@ -0,0 +1,155 @@ +// +using System; +using DistDemoApp; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Volo.Abp.EntityFrameworkCore; + +namespace DistDemoApp.Migrations +{ + [DbContext(typeof(TodoDbContext))] + [Migration("20210909182251_Added_Inbox_Process_Columns")] + partial class Added_Inbox_Process_Columns + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) + .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("ProductVersion", "5.0.9") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("DistDemoApp.TodoItem", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Text") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.ToTable("TodoItems"); + }); + + modelBuilder.Entity("DistDemoApp.TodoSummary", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Day") + .HasColumnType("tinyint"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Month") + .HasColumnType("tinyint"); + + b.Property("TotalCount") + .HasColumnType("int"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("TodoSummaries"); + }); + + modelBuilder.Entity("Volo.Abp.EntityFrameworkCore.DistributedEvents.IncomingEventRecord", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("EventData") + .IsRequired() + .HasColumnType("varbinary(max)"); + + b.Property("EventName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Processed") + .HasColumnType("bit"); + + b.Property("ProcessedTime") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.ToTable("AbpEventInbox"); + }); + + modelBuilder.Entity("Volo.Abp.EntityFrameworkCore.DistributedEvents.OutgoingEventRecord", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("EventData") + .IsRequired() + .HasColumnType("varbinary(max)"); + + b.Property("EventName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.HasKey("Id"); + + b.ToTable("AbpEventOutbox"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/test/DistEvents/DistDemoApp/Migrations/20210909182251_Added_Inbox_Process_Columns.cs b/test/DistEvents/DistDemoApp/Migrations/20210909182251_Added_Inbox_Process_Columns.cs new file mode 100644 index 0000000000..7da910a1af --- /dev/null +++ b/test/DistEvents/DistDemoApp/Migrations/20210909182251_Added_Inbox_Process_Columns.cs @@ -0,0 +1,35 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace DistDemoApp.Migrations +{ + public partial class Added_Inbox_Process_Columns : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Processed", + table: "AbpEventInbox", + type: "bit", + nullable: false, + defaultValue: false); + + migrationBuilder.AddColumn( + name: "ProcessedTime", + table: "AbpEventInbox", + type: "datetime2", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Processed", + table: "AbpEventInbox"); + + migrationBuilder.DropColumn( + name: "ProcessedTime", + table: "AbpEventInbox"); + } + } +} diff --git a/test/DistEvents/DistDemoApp/Migrations/TodoDbContextModelSnapshot.cs b/test/DistEvents/DistDemoApp/Migrations/TodoDbContextModelSnapshot.cs index 3423520512..87cf72bfd0 100644 --- a/test/DistEvents/DistDemoApp/Migrations/TodoDbContextModelSnapshot.cs +++ b/test/DistEvents/DistDemoApp/Migrations/TodoDbContextModelSnapshot.cs @@ -110,6 +110,12 @@ namespace DistDemoApp.Migrations .HasColumnType("nvarchar(max)") .HasColumnName("ExtraProperties"); + b.Property("Processed") + .HasColumnType("bit"); + + b.Property("ProcessedTime") + .HasColumnType("datetime2"); + b.HasKey("Id"); b.ToTable("AbpEventInbox"); From 2aa45fe208f79909312471d5da0d82b7291503e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 10 Sep 2021 11:43:53 +0300 Subject: [PATCH 13/36] Check handlerselector for inbox event processing --- .../Volo/Abp/EventBus/Boxes/InboxProcessor.cs | 2 +- .../Abp/EventBus/Kafka/KafkaDistributedEventBus.cs | 4 ++-- .../RabbitMq/RabbitMqDistributedEventBus.cs | 4 ++-- .../Abp/EventBus/Rebus/RebusDistributedEventBus.cs | 2 +- .../EventBus/Distributed/DistributedEventBusBase.cs | 2 +- .../Abp/EventBus/Distributed/IRawEventPublisher.cs | 4 ++-- .../Volo/Abp/EventBus/EventBusBase.cs | 13 ++++++++++--- 7 files changed, 19 insertions(+), 12 deletions(-) diff --git a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/InboxProcessor.cs b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/InboxProcessor.cs index 4725e85d51..b1e6a1492b 100644 --- a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/InboxProcessor.cs +++ b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/InboxProcessor.cs @@ -85,7 +85,7 @@ namespace Volo.Abp.EventBus.Boxes { await DistributedEventBus .AsRawEventPublisher() - .ProcessRawAsync(waitingEvent.EventName, waitingEvent.EventData); + .ProcessRawAsync(InboxConfig, waitingEvent.EventName, waitingEvent.EventData); /* await DistributedEventBus diff --git a/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs b/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs index ae20ab1dd0..e587dc9749 100644 --- a/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs +++ b/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs @@ -211,7 +211,7 @@ namespace Volo.Abp.EventBus.Kafka ); } - public override async Task ProcessRawAsync(string eventName, byte[] eventDataBytes) + public override async Task ProcessRawAsync(InboxConfig inboxConfig, string eventName, byte[] eventDataBytes) { var eventType = EventTypes.GetOrDefault(eventName); if (eventType == null) @@ -221,7 +221,7 @@ namespace Volo.Abp.EventBus.Kafka var eventData = Serializer.Deserialize(eventDataBytes, eventType); var exceptions = new List(); - await TriggerHandlersAsync(eventType, eventData, exceptions); + await TriggerHandlersAsync(eventType, eventData, exceptions, inboxConfig); if (exceptions.Any()) { ThrowOriginalExceptions(eventType, exceptions); diff --git a/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs b/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs index d3d74a048c..eb171f7ffb 100644 --- a/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs +++ b/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs @@ -217,7 +217,7 @@ namespace Volo.Abp.EventBus.RabbitMq return PublishAsync(eventName, eventData, null, eventId: eventId); } - public override async Task ProcessRawAsync(string eventName, byte[] eventDataBytes) + public override async Task ProcessRawAsync(InboxConfig inboxConfig, string eventName, byte[] eventDataBytes) { //TODO: We have a duplication in logic and also with the kafka side! @@ -229,7 +229,7 @@ namespace Volo.Abp.EventBus.RabbitMq var eventData = Serializer.Deserialize(eventDataBytes, eventType); var exceptions = new List(); - await TriggerHandlersAsync(eventType, eventData, exceptions); + await TriggerHandlersAsync(eventType, eventData, exceptions, inboxConfig); if (exceptions.Any()) { ThrowOriginalExceptions(eventType, exceptions); diff --git a/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventBus.cs b/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventBus.cs index bbe80d9866..af3d148ecf 100644 --- a/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventBus.cs +++ b/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventBus.cs @@ -194,7 +194,7 @@ namespace Volo.Abp.EventBus.Rebus throw new NotImplementedException(); } - public override Task ProcessRawAsync(string eventName, byte[] eventDataBytes) + public override Task ProcessRawAsync(InboxConfig inboxConfig, string eventName, byte[] eventDataBytes) { /* TODO: IMPLEMENT! */ throw new NotImplementedException(); diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs index a436294e88..8de449058b 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs @@ -81,7 +81,7 @@ namespace Volo.Abp.EventBus.Distributed } public abstract Task PublishRawAsync(Guid eventId, string eventName, byte[] eventData); - public abstract Task ProcessRawAsync(string eventName, byte[] eventDataBytes); + public abstract Task ProcessRawAsync(InboxConfig inboxConfig, string eventName, byte[] eventDataBytes); private async Task AddToOutboxAsync(Type eventType, object eventData) { diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IRawEventPublisher.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IRawEventPublisher.cs index 5f96b818b7..4505239ade 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IRawEventPublisher.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IRawEventPublisher.cs @@ -11,8 +11,8 @@ namespace Volo.Abp.EventBus.Distributed byte[] eventData); Task ProcessRawAsync( + InboxConfig inboxConfig, string eventName, - byte[] eventDataBytes - ); + byte[] eventDataBytes); } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventBusBase.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventBusBase.cs index c4a61b24a6..694166b1bc 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventBusBase.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventBusBase.cs @@ -134,7 +134,7 @@ namespace Volo.Abp.EventBus } } - protected virtual async Task TriggerHandlersAsync(Type eventType, object eventData , List exceptions) + protected virtual async Task TriggerHandlersAsync(Type eventType, object eventData, List exceptions, InboxConfig inboxConfig = null) { await new SynchronizationContextRemover(); @@ -142,7 +142,7 @@ namespace Volo.Abp.EventBus { foreach (var handlerFactory in handlerFactories.EventHandlerFactories) { - await TriggerHandlerAsync(handlerFactory, handlerFactories.EventType, eventData, exceptions); + await TriggerHandlerAsync(handlerFactory, handlerFactories.EventType, eventData, exceptions, inboxConfig); } } @@ -199,7 +199,8 @@ namespace Volo.Abp.EventBus protected abstract IEnumerable GetHandlerFactories(Type eventType); - protected virtual async Task TriggerHandlerAsync(IEventHandlerFactory asyncHandlerFactory, Type eventType, object eventData, List exceptions) + protected virtual async Task TriggerHandlerAsync(IEventHandlerFactory asyncHandlerFactory, Type eventType, + object eventData, List exceptions, InboxConfig inboxConfig = null) { using (var eventHandlerWrapper = asyncHandlerFactory.GetHandler()) { @@ -207,6 +208,12 @@ namespace Volo.Abp.EventBus { var handlerType = eventHandlerWrapper.EventHandler.GetType(); + if (inboxConfig?.HandlerSelector != null && + !inboxConfig.HandlerSelector(handlerType)) + { + return; + } + using (CurrentTenant.Change(GetEventDataTenantId(eventData))) { if (ReflectionHelper.IsAssignableToGenericType(handlerType, typeof(ILocalEventHandler<>))) From eb47e508960f0cfb931232738a9d0460f85cb1a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 10 Sep 2021 13:34:28 +0300 Subject: [PATCH 14/36] Apply ABP concepts on state change, not on savechanges. --- .../Abp/EntityFrameworkCore/AbpDbContext.cs | 37 +++++-------------- 1 file changed, 9 insertions(+), 28 deletions(-) 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 b86f9b83b1..62c8f84d38 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs @@ -162,7 +162,7 @@ namespace Volo.Abp.EntityFrameworkCore entityChangeList = EntityHistoryHelper.CreateChangeList(ChangeTracker.Entries().ToList()); } - ApplyAbpConcepts(); + HandleExtraPropertiesOnSave(); var eventReport = CreateEventReport(); @@ -291,10 +291,12 @@ namespace Volo.Abp.EntityFrameworkCore switch (entry.State) { case EntityState.Added: + ApplyAbpConceptsForAddedEntity(entry); EntityChangeEventHelper.PublishEntityCreatingEvent(entry.Entity); EntityChangeEventHelper.PublishEntityCreatedEvent(entry.Entity); break; case EntityState.Modified: + ApplyAbpConceptsForModifiedEntity(entry); if (entry.Properties.Any(x => x.IsModified && x.Metadata.ValueGenerated == ValueGenerated.Never)) { if (entry.Entity is ISoftDelete && entry.Entity.As().IsDeleted) @@ -311,17 +313,18 @@ namespace Volo.Abp.EntityFrameworkCore break; case EntityState.Deleted: + ApplyAbpConceptsForDeletedEntity(entry); EntityChangeEventHelper.PublishEntityDeletingEvent(entry.Entity); EntityChangeEventHelper.PublishEntityDeletedEvent(entry.Entity); break; } } - protected virtual void ApplyAbpConcepts() + protected virtual void HandleExtraPropertiesOnSave() { foreach (var entry in ChangeTracker.Entries().ToList()) { - ApplyAbpConcepts(entry); + HandleExtraPropertiesOnSave(entry); } } @@ -369,24 +372,6 @@ namespace Volo.Abp.EntityFrameworkCore return eventReport; } - - protected virtual void ApplyAbpConcepts(EntityEntry entry) - { - switch (entry.State) - { - case EntityState.Added: - ApplyAbpConceptsForAddedEntity(entry); - break; - case EntityState.Modified: - ApplyAbpConceptsForModifiedEntity(entry); - break; - case EntityState.Deleted: - ApplyAbpConceptsForDeletedEntity(entry); - break; - } - - HandleExtraPropertiesOnSave(entry); - } protected virtual void HandleExtraPropertiesOnSave(EntityEntry entry) { @@ -485,11 +470,7 @@ namespace Volo.Abp.EntityFrameworkCore protected virtual void ApplyAbpConceptsForDeletedEntity(EntityEntry entry) { - if (TryCancelDeletionForSoftDelete(entry)) - { - UpdateConcurrencyStamp(entry); - SetDeletionAuditProperties(entry); - } + TryCancelDeletionForSoftDelete(entry); } protected virtual bool IsHardDeleted(EntityEntry entry) @@ -510,7 +491,7 @@ namespace Volo.Abp.EntityFrameworkCore { return; } - + Entry(entity).Property(x => x.ConcurrencyStamp).OriginalValue = entity.ConcurrencyStamp; entity.ConcurrencyStamp = Guid.NewGuid().ToString("N"); } @@ -544,8 +525,8 @@ namespace Volo.Abp.EntityFrameworkCore } entry.Reload(); - entry.State = EntityState.Modified; entry.Entity.As().IsDeleted = true; + entry.State = EntityState.Modified; return true; } From 51ce477165843aa975034a6c47cd24b1351ef4bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 10 Sep 2021 14:30:10 +0300 Subject: [PATCH 15/36] Eliminate duplicate incoming events --- .../DistributedEvents/DbContextEventInbox.cs | 27 ++- ...entInboxDbContextModelBuilderExtensions.cs | 3 + .../DistributedEvents/IncomingEventRecord.cs | 4 + .../Kafka/KafkaDistributedEventBus.cs | 13 +- .../RabbitMq/RabbitMqDistributedEventBus.cs | 10 +- .../Distributed/DistributedEventBusBase.cs | 12 +- .../Abp/EventBus/Distributed/IEventInbox.cs | 4 + .../EventBus/Distributed/IncomingEventInfo.cs | 4 + ...910111009_Added_Inbox_New_Cols.Designer.cs | 162 ++++++++++++++++++ .../20210910111009_Added_Inbox_New_Cols.cs | 41 +++++ .../Migrations/TodoDbContextModelSnapshot.cs | 7 + 11 files changed, 276 insertions(+), 11 deletions(-) create mode 100644 test/DistEvents/DistDemoApp/Migrations/20210910111009_Added_Inbox_New_Cols.Designer.cs create mode 100644 test/DistEvents/DistDemoApp/Migrations/20210910111009_Added_Inbox_New_Cols.cs diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventInbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventInbox.cs index df45d50ae5..f5f1d7010e 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventInbox.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventInbox.cs @@ -26,7 +26,8 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents [UnitOfWork] public virtual async Task EnqueueAsync(IncomingEventInfo incomingEvent) { - var dbContext = (IHasEventInbox) await DbContextProvider.GetDbContextAsync(); + var dbContext = await GetDbContextAsync(); + dbContext.IncomingEvents.Add( new IncomingEventRecord(incomingEvent) ); @@ -35,8 +36,8 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents [UnitOfWork] public virtual async Task> GetWaitingEventsAsync(int maxCount) { - var dbContext = (IHasEventInbox) await DbContextProvider.GetDbContextAsync(); - + var dbContext = await GetDbContextAsync(); + var outgoingEventRecords = await dbContext .IncomingEvents .AsNoTracking() @@ -50,15 +51,33 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents .ToList(); } + [UnitOfWork] public async Task MarkAsProcessedAsync(Guid id) { //TODO: Optimize? - var dbContext = (IHasEventInbox) await DbContextProvider.GetDbContextAsync(); + var dbContext = await GetDbContextAsync(); var incomingEvent = await dbContext.IncomingEvents.FindAsync(id); if (incomingEvent != null) { incomingEvent.MarkAsProcessed(Clock.Now); } } + + [UnitOfWork] + public async Task ExistsByMessageIdAsync(string messageId) + { + var dbContext = await GetDbContextAsync(); + return await dbContext.IncomingEvents.AnyAsync(x => x.MessageId == messageId); + } + + private async Task GetDbContextAsync() + { + return (IHasEventInbox)await DbContextProvider.GetDbContextAsync(); + } + + public Task DeleteOldEventsAsync() + { + throw new NotImplementedException(); + } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/EventInboxDbContextModelBuilderExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/EventInboxDbContextModelBuilderExtensions.cs index d3e3a6cc26..29c9f0042c 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/EventInboxDbContextModelBuilderExtensions.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/EventInboxDbContextModelBuilderExtensions.cs @@ -15,6 +15,9 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents b.ConfigureByConvention(); b.Property(x => x.EventName).IsRequired().HasMaxLength(IncomingEventRecord.MaxEventNameLength); b.Property(x => x.EventData).IsRequired(); + + b.HasIndex(x => new { x.Processed, x.CreationTime }); + b.HasIndex(x => x.MessageId); }); } } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IncomingEventRecord.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IncomingEventRecord.cs index 62c2781b48..a1f971bbaa 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IncomingEventRecord.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IncomingEventRecord.cs @@ -15,6 +15,8 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents public ExtraPropertyDictionary ExtraProperties { get; private set; } + public string MessageId { get; private set; } + public string EventName { get; private set; } public byte[] EventData { get; private set; } @@ -35,6 +37,7 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents IncomingEventInfo eventInfo) : base(eventInfo.Id) { + MessageId = eventInfo.MessageId; EventName = eventInfo.EventName; EventData = eventInfo.EventData; CreationTime = eventInfo.CreationTime; @@ -47,6 +50,7 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents { return new IncomingEventInfo( Id, + MessageId, EventName, EventData, CreationTime diff --git a/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs b/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs index e587dc9749..3ffe3bb880 100644 --- a/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs +++ b/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs @@ -86,8 +86,15 @@ namespace Volo.Abp.EventBus.Kafka { return; } + + string messageId = null; + + if (message.Headers.TryGetLastBytes("messageId", out var messageIdBytes)) + { + messageId = System.Text.Encoding.UTF8.GetString(messageIdBytes); + } - if (await AddToInboxAsync(eventName, eventType, message.Value)) + if (await AddToInboxAsync(messageId, eventName, eventType, message.Value)) { return; } @@ -183,7 +190,7 @@ namespace Volo.Abp.EventBus.Kafka eventData, new Headers { - { "messageId", Serializer.Serialize(Guid.NewGuid()) } + { "messageId", System.Text.Encoding.UTF8.GetBytes(Guid.NewGuid().ToString("N")) } }, null ); @@ -205,7 +212,7 @@ namespace Volo.Abp.EventBus.Kafka eventData, new Headers { - { "messageId", Serializer.Serialize(eventId) } + { "messageId", System.Text.Encoding.UTF8.GetBytes(eventId.ToString("N")) } }, null ); diff --git a/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs b/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs index eb171f7ffb..deb20b5ff3 100644 --- a/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs +++ b/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs @@ -106,8 +106,8 @@ namespace Volo.Abp.EventBus.RabbitMq } var eventBytes = ea.Body.ToArray(); - - if (await AddToInboxAsync(eventName, eventType, eventBytes)) + + if (await AddToInboxAsync(ea.BasicProperties.MessageId, eventName, eventType, eventBytes)) { return; } @@ -268,9 +268,13 @@ namespace Volo.Abp.EventBus.RabbitMq { properties = channel.CreateBasicProperties(); properties.DeliveryMode = RabbitMqConsts.DeliveryModes.Persistent; - properties.MessageId = (eventId ?? GuidGenerator.Create()).ToString("N"); } + if (properties.MessageId.IsNullOrEmpty()) + { + properties.MessageId = (eventId ?? GuidGenerator.Create()).ToString("N"); + } + SetEventMessageHeaders(properties, headersArguments); channel.BasicPublish( diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs index 8de449058b..1fdaf0d26f 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs @@ -113,6 +113,7 @@ namespace Volo.Abp.EventBus.Distributed } protected async Task AddToInboxAsync( + string messageId, string eventName, Type eventType, byte[] eventBytes) @@ -129,10 +130,19 @@ namespace Volo.Abp.EventBus.Distributed if (inboxConfig.EventSelector == null || inboxConfig.EventSelector(eventType)) { var eventInbox = (IEventInbox) scope.ServiceProvider.GetRequiredService(inboxConfig.ImplementationType); - //TODO: Check if event was received before!! + + if (!messageId.IsNullOrEmpty()) + { + if (await eventInbox.ExistsByMessageIdAsync(messageId)) + { + continue; + } + } + await eventInbox.EnqueueAsync( new IncomingEventInfo( GuidGenerator.Create(), + messageId, eventName, eventBytes, Clock.Now diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IEventInbox.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IEventInbox.cs index 137a410afa..bee802a126 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IEventInbox.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IEventInbox.cs @@ -11,5 +11,9 @@ namespace Volo.Abp.EventBus.Distributed Task> GetWaitingEventsAsync(int maxCount); Task MarkAsProcessedAsync(Guid id); + + Task ExistsByMessageIdAsync(string messageId); + + Task DeleteOldEventsAsync(); } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IncomingEventInfo.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IncomingEventInfo.cs index 7cd628cf91..571c62602b 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IncomingEventInfo.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IncomingEventInfo.cs @@ -11,6 +11,8 @@ namespace Volo.Abp.EventBus.Distributed public Guid Id { get; } + public string MessageId { get; } + public string EventName { get; } public byte[] EventData { get; } @@ -25,11 +27,13 @@ namespace Volo.Abp.EventBus.Distributed public IncomingEventInfo( Guid id, + string messageId, string eventName, byte[] eventData, DateTime creationTime) { Id = id; + MessageId = messageId; EventName = Check.NotNullOrWhiteSpace(eventName, nameof(eventName), MaxEventNameLength); EventData = eventData; CreationTime = creationTime; diff --git a/test/DistEvents/DistDemoApp/Migrations/20210910111009_Added_Inbox_New_Cols.Designer.cs b/test/DistEvents/DistDemoApp/Migrations/20210910111009_Added_Inbox_New_Cols.Designer.cs new file mode 100644 index 0000000000..7b552dfcfc --- /dev/null +++ b/test/DistEvents/DistDemoApp/Migrations/20210910111009_Added_Inbox_New_Cols.Designer.cs @@ -0,0 +1,162 @@ +// +using System; +using DistDemoApp; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Volo.Abp.EntityFrameworkCore; + +namespace DistDemoApp.Migrations +{ + [DbContext(typeof(TodoDbContext))] + [Migration("20210910111009_Added_Inbox_New_Cols")] + partial class Added_Inbox_New_Cols + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) + .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("ProductVersion", "5.0.9") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("DistDemoApp.TodoItem", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Text") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.ToTable("TodoItems"); + }); + + modelBuilder.Entity("DistDemoApp.TodoSummary", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Day") + .HasColumnType("tinyint"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Month") + .HasColumnType("tinyint"); + + b.Property("TotalCount") + .HasColumnType("int"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("TodoSummaries"); + }); + + modelBuilder.Entity("Volo.Abp.EntityFrameworkCore.DistributedEvents.IncomingEventRecord", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("EventData") + .IsRequired() + .HasColumnType("varbinary(max)"); + + b.Property("EventName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("MessageId") + .HasColumnType("nvarchar(450)"); + + b.Property("Processed") + .HasColumnType("bit"); + + b.Property("ProcessedTime") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.HasIndex("MessageId"); + + b.HasIndex("Processed", "CreationTime"); + + b.ToTable("AbpEventInbox"); + }); + + modelBuilder.Entity("Volo.Abp.EntityFrameworkCore.DistributedEvents.OutgoingEventRecord", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("EventData") + .IsRequired() + .HasColumnType("varbinary(max)"); + + b.Property("EventName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.HasKey("Id"); + + b.ToTable("AbpEventOutbox"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/test/DistEvents/DistDemoApp/Migrations/20210910111009_Added_Inbox_New_Cols.cs b/test/DistEvents/DistDemoApp/Migrations/20210910111009_Added_Inbox_New_Cols.cs new file mode 100644 index 0000000000..24f65ff23c --- /dev/null +++ b/test/DistEvents/DistDemoApp/Migrations/20210910111009_Added_Inbox_New_Cols.cs @@ -0,0 +1,41 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace DistDemoApp.Migrations +{ + public partial class Added_Inbox_New_Cols : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "MessageId", + table: "AbpEventInbox", + type: "nvarchar(450)", + nullable: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpEventInbox_MessageId", + table: "AbpEventInbox", + column: "MessageId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpEventInbox_Processed_CreationTime", + table: "AbpEventInbox", + columns: new[] { "Processed", "CreationTime" }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_AbpEventInbox_MessageId", + table: "AbpEventInbox"); + + migrationBuilder.DropIndex( + name: "IX_AbpEventInbox_Processed_CreationTime", + table: "AbpEventInbox"); + + migrationBuilder.DropColumn( + name: "MessageId", + table: "AbpEventInbox"); + } + } +} diff --git a/test/DistEvents/DistDemoApp/Migrations/TodoDbContextModelSnapshot.cs b/test/DistEvents/DistDemoApp/Migrations/TodoDbContextModelSnapshot.cs index 87cf72bfd0..57e8c14442 100644 --- a/test/DistEvents/DistDemoApp/Migrations/TodoDbContextModelSnapshot.cs +++ b/test/DistEvents/DistDemoApp/Migrations/TodoDbContextModelSnapshot.cs @@ -110,6 +110,9 @@ namespace DistDemoApp.Migrations .HasColumnType("nvarchar(max)") .HasColumnName("ExtraProperties"); + b.Property("MessageId") + .HasColumnType("nvarchar(450)"); + b.Property("Processed") .HasColumnType("bit"); @@ -118,6 +121,10 @@ namespace DistDemoApp.Migrations b.HasKey("Id"); + b.HasIndex("MessageId"); + + b.HasIndex("Processed", "CreationTime"); + b.ToTable("AbpEventInbox"); }); From 4e0e0de1d73c372a4ef74046e3a0dc595db3553d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 10 Sep 2021 15:42:21 +0300 Subject: [PATCH 16/36] Regularly delete old events --- .../DistributedEvents/DbContextEventInbox.cs | 25 +++++++++-------- .../Volo/Abp/EventBus/Boxes/InboxProcessor.cs | 28 +++++++++++++++---- 2 files changed, 36 insertions(+), 17 deletions(-) diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventInbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventInbox.cs index f5f1d7010e..2b0a448f74 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventInbox.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventInbox.cs @@ -26,7 +26,7 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents [UnitOfWork] public virtual async Task EnqueueAsync(IncomingEventInfo incomingEvent) { - var dbContext = await GetDbContextAsync(); + var dbContext = await DbContextProvider.GetDbContextAsync(); dbContext.IncomingEvents.Add( new IncomingEventRecord(incomingEvent) @@ -36,7 +36,7 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents [UnitOfWork] public virtual async Task> GetWaitingEventsAsync(int maxCount) { - var dbContext = await GetDbContextAsync(); + var dbContext = await DbContextProvider.GetDbContextAsync(); var outgoingEventRecords = await dbContext .IncomingEvents @@ -55,7 +55,7 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents public async Task MarkAsProcessedAsync(Guid id) { //TODO: Optimize? - var dbContext = await GetDbContextAsync(); + var dbContext = await DbContextProvider.GetDbContextAsync(); var incomingEvent = await dbContext.IncomingEvents.FindAsync(id); if (incomingEvent != null) { @@ -66,18 +66,21 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents [UnitOfWork] public async Task ExistsByMessageIdAsync(string messageId) { - var dbContext = await GetDbContextAsync(); + //TODO: Optimize + var dbContext = await DbContextProvider.GetDbContextAsync(); return await dbContext.IncomingEvents.AnyAsync(x => x.MessageId == messageId); } - private async Task GetDbContextAsync() - { - return (IHasEventInbox)await DbContextProvider.GetDbContextAsync(); - } - - public Task DeleteOldEventsAsync() + [UnitOfWork] + public async Task DeleteOldEventsAsync() { - throw new NotImplementedException(); + //TODO: Optimize + var dbContext = await DbContextProvider.GetDbContextAsync(); + var timeToKeepEvents = Clock.Now.AddHours(-2); //TODO: Config? + var oldEvents = await dbContext.IncomingEvents + .Where(x => x.Processed && x.CreationTime < timeToKeepEvents) + .ToListAsync(); + dbContext.IncomingEvents.RemoveRange(oldEvents); } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/InboxProcessor.cs b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/InboxProcessor.cs index b1e6a1492b..bba97fe3d6 100644 --- a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/InboxProcessor.cs +++ b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/InboxProcessor.cs @@ -8,6 +8,7 @@ using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus.Distributed; using Volo.Abp.Threading; +using Volo.Abp.Timing; using Volo.Abp.Uow; namespace Volo.Abp.EventBus.Boxes @@ -19,9 +20,12 @@ namespace Volo.Abp.EventBus.Boxes protected IDistributedEventBus DistributedEventBus { get; } protected IDistributedLockProvider DistributedLockProvider { get; } protected IUnitOfWorkManager UnitOfWorkManager { get; } + protected IClock Clock { get; } protected IEventInbox Inbox { get; private set; } protected InboxConfig InboxConfig { get; private set; } + protected DateTime? LastCleanTime { get; set; } + protected string DistributedLockName => "Inbox_" + InboxConfig.Name; public ILogger Logger { get; set; } @@ -30,13 +34,15 @@ namespace Volo.Abp.EventBus.Boxes AbpTimer timer, IDistributedEventBus distributedEventBus, IDistributedLockProvider distributedLockProvider, - IUnitOfWorkManager unitOfWorkManager) + IUnitOfWorkManager unitOfWorkManager, + IClock clock) { ServiceProvider = serviceProvider; Timer = timer; DistributedEventBus = distributedEventBus; DistributedLockProvider = distributedLockProvider; UnitOfWorkManager = unitOfWorkManager; + Clock = clock; Timer.Period = 2000; //TODO: Config? Timer.Elapsed += TimerOnElapsed; Logger = NullLogger.Instance; @@ -69,6 +75,8 @@ namespace Volo.Abp.EventBus.Boxes { Logger.LogDebug("Obtained the distributed lock: " + DistributedLockName); + await DeleteOldEventsAsync(); + while (true) { var waitingEvents = await Inbox.GetWaitingEventsAsync(1000); //TODO: Config? @@ -87,12 +95,8 @@ namespace Volo.Abp.EventBus.Boxes .AsRawEventPublisher() .ProcessRawAsync(InboxConfig, waitingEvent.EventName, waitingEvent.EventData); - /* - await DistributedEventBus - .AsRawEventPublisher() - .PublishRawAsync(waitingEvent.Id, waitingEvent.EventName, waitingEvent.EventData); - */ await Inbox.MarkAsProcessedAsync(waitingEvent.Id); + await uow.CompleteAsync(); } @@ -107,5 +111,17 @@ namespace Volo.Abp.EventBus.Boxes } } } + + protected virtual async Task DeleteOldEventsAsync() + { + if (LastCleanTime != null && LastCleanTime > Clock.Now.AddHours(6)) //TODO: Config? + { + return; + } + + await Inbox.DeleteOldEventsAsync(); + + LastCleanTime = DateTime.Now; + } } } \ No newline at end of file From 3b7d1514a9f089383126df8445b38e06f01cd8c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 10 Sep 2021 17:28:03 +0300 Subject: [PATCH 17/36] Added initial mongodb boxing services --- .../Repositories/MongoDB/MongoDbRepository.cs | 3 +- .../Volo/Abp/MongoDB/AbpMongoDbModule.cs | 11 ++++ .../DistributedEvents/DbContextEventInbox.cs | 36 ++++++++++ .../DistributedEvents/DbContextEventOutbox.cs | 27 ++++++++ .../DistributedEvents/IDbContextEventInbox.cs | 10 +++ .../IDbContextEventOutbox.cs | 10 +++ .../DistributedEvents/IHasEventInbox.cs | 9 +++ .../DistributedEvents/IHasEventOutbox.cs | 9 +++ .../DistributedEvents/IncomingEventRecord.cs | 66 +++++++++++++++++++ .../DistributedEvents/OutgoingEventRecord.cs | 52 +++++++++++++++ 10 files changed, 232 insertions(+), 1 deletion(-) create mode 100644 framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/DbContextEventInbox.cs create mode 100644 framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/DbContextEventOutbox.cs create mode 100644 framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IDbContextEventInbox.cs create mode 100644 framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IDbContextEventOutbox.cs create mode 100644 framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IHasEventInbox.cs create mode 100644 framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IHasEventOutbox.cs create mode 100644 framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IncomingEventRecord.cs create mode 100644 framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/OutgoingEventRecord.cs 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 a40117e0ff..a90549cf5d 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 @@ -570,12 +570,13 @@ namespace Volo.Abp.Domain.Repositories.MongoDB ); } - protected virtual async Task ApplyAbpConceptsForAddedEntityAsync(TEntity entity) + protected virtual Task ApplyAbpConceptsForAddedEntityAsync(TEntity entity) { CheckAndSetId(entity); SetCreationAuditProperties(entity); TriggerEntityCreateEvents(entity); TriggerDomainEvents(entity); + return Task.CompletedTask; } private void TriggerEntityCreateEvents(TEntity entity) diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbModule.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbModule.cs index d32f015a33..9a5d327055 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbModule.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbModule.cs @@ -5,6 +5,7 @@ using Volo.Abp.Domain.Repositories.MongoDB; using Volo.Abp.Modularity; using Volo.Abp.MongoDB.DependencyInjection; using Volo.Abp.Uow.MongoDB; +using Volo.Abp.MongoDB.DistributedEvents; namespace Volo.Abp.MongoDB { @@ -32,6 +33,16 @@ namespace Volo.Abp.MongoDB typeof(IMongoDbRepositoryFilterer<,>), typeof(MongoDbRepositoryFilterer<,>) ); + + context.Services.AddTransient( + typeof(IDbContextEventOutbox<>), + typeof(DbContextEventOutbox<>) + ); + + context.Services.AddTransient( + typeof(IDbContextEventInbox<>), + typeof(DbContextEventInbox<>) + ); } } } diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/DbContextEventInbox.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/DbContextEventInbox.cs new file mode 100644 index 0000000000..955f142add --- /dev/null +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/DbContextEventInbox.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.EventBus.Distributed; + +namespace Volo.Abp.MongoDB.DistributedEvents +{ + public class DbContextEventInbox : IDbContextEventInbox + where TDbContext : IHasEventInbox + { + public Task EnqueueAsync(IncomingEventInfo incomingEvent) + { + throw new NotImplementedException(); + } + + public Task> GetWaitingEventsAsync(int maxCount) + { + throw new NotImplementedException(); + } + + public Task MarkAsProcessedAsync(Guid id) + { + throw new NotImplementedException(); + } + + public Task ExistsByMessageIdAsync(string messageId) + { + throw new NotImplementedException(); + } + + public Task DeleteOldEventsAsync() + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/DbContextEventOutbox.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/DbContextEventOutbox.cs new file mode 100644 index 0000000000..3b054732be --- /dev/null +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/DbContextEventOutbox.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.Uow; + +namespace Volo.Abp.MongoDB.DistributedEvents +{ + public class DbContextEventOutbox : IDbContextEventOutbox + where TDbContext : IHasEventOutbox + { + public Task EnqueueAsync(OutgoingEventInfo outgoingEvent) + { + throw new NotImplementedException(); + } + + public Task> GetWaitingEventsAsync(int maxCount) + { + throw new NotImplementedException(); + } + + public Task DeleteAsync(Guid id) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IDbContextEventInbox.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IDbContextEventInbox.cs new file mode 100644 index 0000000000..d76bac2412 --- /dev/null +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IDbContextEventInbox.cs @@ -0,0 +1,10 @@ +using Volo.Abp.EventBus.Distributed; + +namespace Volo.Abp.MongoDB.DistributedEvents +{ + public interface IDbContextEventInbox : IEventInbox + where TDbContext : IHasEventInbox + { + + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IDbContextEventOutbox.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IDbContextEventOutbox.cs new file mode 100644 index 0000000000..bcc0a4705a --- /dev/null +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IDbContextEventOutbox.cs @@ -0,0 +1,10 @@ +using Volo.Abp.EventBus.Distributed; + +namespace Volo.Abp.MongoDB.DistributedEvents +{ + public interface IDbContextEventOutbox : IEventOutbox + where TDbContext : IHasEventOutbox + { + + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IHasEventInbox.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IHasEventInbox.cs new file mode 100644 index 0000000000..387e860bce --- /dev/null +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IHasEventInbox.cs @@ -0,0 +1,9 @@ +using MongoDB.Driver; + +namespace Volo.Abp.MongoDB.DistributedEvents +{ + public interface IHasEventInbox : IAbpMongoDbContext + { + IMongoCollection IncomingEvents { get; set; } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IHasEventOutbox.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IHasEventOutbox.cs new file mode 100644 index 0000000000..cf57aaa699 --- /dev/null +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IHasEventOutbox.cs @@ -0,0 +1,9 @@ +using MongoDB.Driver; + +namespace Volo.Abp.MongoDB.DistributedEvents +{ + public interface IHasEventOutbox : IAbpMongoDbContext + { + IMongoCollection OutgoingEvents { get; set; } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IncomingEventRecord.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IncomingEventRecord.cs new file mode 100644 index 0000000000..5e9d07c33f --- /dev/null +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IncomingEventRecord.cs @@ -0,0 +1,66 @@ +using System; +using Volo.Abp.Auditing; +using Volo.Abp.Data; +using Volo.Abp.Domain.Entities; +using Volo.Abp.EventBus.Distributed; + +namespace Volo.Abp.MongoDB.DistributedEvents +{ + public class IncomingEventRecord : + BasicAggregateRoot, + IHasExtraProperties, + IHasCreationTime + { + public static int MaxEventNameLength { get; set; } = 256; + + public ExtraPropertyDictionary ExtraProperties { get; private set; } + + public string MessageId { get; private set; } + + public string EventName { get; private set; } + + public byte[] EventData { get; private set; } + + public DateTime CreationTime { get; private set; } + + public bool Processed { get; set; } + + public DateTime? ProcessedTime { get; set; } + + protected IncomingEventRecord() + { + ExtraProperties = new ExtraPropertyDictionary(); + this.SetDefaultsForExtraProperties(); + } + + public IncomingEventRecord( + IncomingEventInfo eventInfo) + : base(eventInfo.Id) + { + MessageId = eventInfo.MessageId; + EventName = eventInfo.EventName; + EventData = eventInfo.EventData; + CreationTime = eventInfo.CreationTime; + + ExtraProperties = new ExtraPropertyDictionary(); + this.SetDefaultsForExtraProperties(); + } + + public IncomingEventInfo ToIncomingEventInfo() + { + return new IncomingEventInfo( + Id, + MessageId, + EventName, + EventData, + CreationTime + ); + } + + public void MarkAsProcessed(DateTime processedTime) + { + Processed = true; + ProcessedTime = processedTime; + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/OutgoingEventRecord.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/OutgoingEventRecord.cs new file mode 100644 index 0000000000..c38de0cd91 --- /dev/null +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/OutgoingEventRecord.cs @@ -0,0 +1,52 @@ +using System; +using Volo.Abp.Auditing; +using Volo.Abp.Data; +using Volo.Abp.Domain.Entities; +using Volo.Abp.EventBus.Distributed; + +namespace Volo.Abp.MongoDB.DistributedEvents +{ + public class OutgoingEventRecord : + BasicAggregateRoot, + IHasExtraProperties, + IHasCreationTime + { + public static int MaxEventNameLength { get; set; } = 256; + + public ExtraPropertyDictionary ExtraProperties { get; private set; } + + public string EventName { get; private set; } + + public byte[] EventData { get; private set; } + + public DateTime CreationTime { get; private set; } + + protected OutgoingEventRecord() + { + ExtraProperties = new ExtraPropertyDictionary(); + this.SetDefaultsForExtraProperties(); + } + + public OutgoingEventRecord( + OutgoingEventInfo eventInfo) + : base(eventInfo.Id) + { + EventName = eventInfo.EventName; + EventData = eventInfo.EventData; + CreationTime = eventInfo.CreationTime; + + ExtraProperties = new ExtraPropertyDictionary(); + this.SetDefaultsForExtraProperties(); + } + + public OutgoingEventInfo ToOutgoingEventInfo() + { + return new OutgoingEventInfo( + Id, + EventName, + EventData, + CreationTime + ); + } + } +} \ No newline at end of file From 59dada8814dabd022061d16206120361a91bf467 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 10 Sep 2021 18:29:18 +0300 Subject: [PATCH 18/36] Refactored the example solution. Added mongodb extensions --- .../Volo/Abp/MongoDB/AbpMongoDbModule.cs | 8 +- .../DistributedEvents/DbContextEventInbox.cs | 36 ---- ...tInbox.cs => IMongoDbContextEventInbox.cs} | 2 +- ...utbox.cs => IMongoDbContextEventOutbox.cs} | 2 +- .../MongoDbContextEventInbox.cs | 81 +++++++++ ...Outbox.cs => MongoDbContextEventOutbox.cs} | 4 +- .../MongoDbInboxConfigExtensions.cs | 13 ++ .../MongoDbOutboxConfigExtensions.cs | 13 ++ .../DistDemoApp.EfCoreRabbitMq.csproj} | 13 +- .../DistDemoAppEfCoreRabbitMqModule.cs} | 27 +-- ...910152547_Added_Boxes_Initial.Designer.cs} | 4 +- .../20210910152547_Added_Boxes_Initial.cs | 103 ++++++++++++ .../Migrations/TodoDbContextModelSnapshot.cs | 0 .../Program.cs | 2 +- .../TodoDbContext.cs | 0 .../TodoDbContextFactory.cs | 0 .../appsettings.json | 0 .../DistDemoApp.MongoDbKafka.csproj | 9 + .../DistDemoApp.MongoDbKafka/Program.cs | 12 ++ .../DemoService.cs | 0 .../DistDemoApp.Shared.csproj | 23 +++ .../DistDemoAppHostedService.cs} | 4 +- .../DistDemoAppSharedModule.cs | 39 +++++ .../TodoEventHandler.cs | 0 .../TodoItem.cs | 0 .../TodoItemEto.cs | 0 .../TodoItemObjectMapper.cs | 0 .../TodoSummary.cs | 0 .../20210825110134_Initial.Designer.cs | 61 ------- .../Migrations/20210825110134_Initial.cs | 33 ---- ...0825112717_Added_Summary_Table.Designer.cs | 95 ----------- .../20210825112717_Added_Summary_Table.cs | 34 ---- .../20210908063422_Added_Outbox.Designer.cs | 118 ------------- .../Migrations/20210908063422_Added_Outbox.cs | 31 ---- ...5344_Added_Outbox_CreationTime.Designer.cs | 122 -------------- ...0210908075344_Added_Outbox_CreationTime.cs | 25 --- .../20210909113934_Added_Inbox.Designer.cs | 149 ----------------- .../Migrations/20210909113934_Added_Inbox.cs | 32 ---- ...51_Added_Inbox_Process_Columns.Designer.cs | 155 ------------------ ...10909182251_Added_Inbox_Process_Columns.cs | 35 ---- .../20210910111009_Added_Inbox_New_Cols.cs | 41 ----- test/DistEvents/DistEventsDemo.sln | 14 +- 42 files changed, 323 insertions(+), 1017 deletions(-) delete mode 100644 framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/DbContextEventInbox.cs rename framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/{IDbContextEventInbox.cs => IMongoDbContextEventInbox.cs} (66%) rename framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/{IDbContextEventOutbox.cs => IMongoDbContextEventOutbox.cs} (66%) create mode 100644 framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventInbox.cs rename framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/{DbContextEventOutbox.cs => MongoDbContextEventOutbox.cs} (79%) create mode 100644 framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbInboxConfigExtensions.cs create mode 100644 framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbOutboxConfigExtensions.cs rename test/DistEvents/{DistDemoApp/DistDemoApp.csproj => DistDemoApp.EfCoreRabbitMq/DistDemoApp.EfCoreRabbitMq.csproj} (58%) rename test/DistEvents/{DistDemoApp/DistDemoAppModule.cs => DistDemoApp.EfCoreRabbitMq/DistDemoAppEfCoreRabbitMqModule.cs} (54%) rename test/DistEvents/{DistDemoApp/Migrations/20210910111009_Added_Inbox_New_Cols.Designer.cs => DistDemoApp.EfCoreRabbitMq/Migrations/20210910152547_Added_Boxes_Initial.Designer.cs} (98%) create mode 100644 test/DistEvents/DistDemoApp.EfCoreRabbitMq/Migrations/20210910152547_Added_Boxes_Initial.cs rename test/DistEvents/{DistDemoApp => DistDemoApp.EfCoreRabbitMq}/Migrations/TodoDbContextModelSnapshot.cs (100%) rename test/DistEvents/{DistDemoApp => DistDemoApp.EfCoreRabbitMq}/Program.cs (95%) rename test/DistEvents/{DistDemoApp => DistDemoApp.EfCoreRabbitMq}/TodoDbContext.cs (100%) rename test/DistEvents/{DistDemoApp => DistDemoApp.EfCoreRabbitMq}/TodoDbContextFactory.cs (100%) rename test/DistEvents/{DistDemoApp => DistDemoApp.EfCoreRabbitMq}/appsettings.json (100%) create mode 100644 test/DistEvents/DistDemoApp.MongoDbKafka/DistDemoApp.MongoDbKafka.csproj create mode 100644 test/DistEvents/DistDemoApp.MongoDbKafka/Program.cs rename test/DistEvents/{DistDemoApp => DistDemoApp.Shared}/DemoService.cs (100%) create mode 100644 test/DistEvents/DistDemoApp.Shared/DistDemoApp.Shared.csproj rename test/DistEvents/{DistDemoApp/MyProjectNameHostedService.cs => DistDemoApp.Shared/DistDemoAppHostedService.cs} (90%) create mode 100644 test/DistEvents/DistDemoApp.Shared/DistDemoAppSharedModule.cs rename test/DistEvents/{DistDemoApp => DistDemoApp.Shared}/TodoEventHandler.cs (100%) rename test/DistEvents/{DistDemoApp => DistDemoApp.Shared}/TodoItem.cs (100%) rename test/DistEvents/{DistDemoApp => DistDemoApp.Shared}/TodoItemEto.cs (100%) rename test/DistEvents/{DistDemoApp => DistDemoApp.Shared}/TodoItemObjectMapper.cs (100%) rename test/DistEvents/{DistDemoApp => DistDemoApp.Shared}/TodoSummary.cs (100%) delete mode 100644 test/DistEvents/DistDemoApp/Migrations/20210825110134_Initial.Designer.cs delete mode 100644 test/DistEvents/DistDemoApp/Migrations/20210825110134_Initial.cs delete mode 100644 test/DistEvents/DistDemoApp/Migrations/20210825112717_Added_Summary_Table.Designer.cs delete mode 100644 test/DistEvents/DistDemoApp/Migrations/20210825112717_Added_Summary_Table.cs delete mode 100644 test/DistEvents/DistDemoApp/Migrations/20210908063422_Added_Outbox.Designer.cs delete mode 100644 test/DistEvents/DistDemoApp/Migrations/20210908063422_Added_Outbox.cs delete mode 100644 test/DistEvents/DistDemoApp/Migrations/20210908075344_Added_Outbox_CreationTime.Designer.cs delete mode 100644 test/DistEvents/DistDemoApp/Migrations/20210908075344_Added_Outbox_CreationTime.cs delete mode 100644 test/DistEvents/DistDemoApp/Migrations/20210909113934_Added_Inbox.Designer.cs delete mode 100644 test/DistEvents/DistDemoApp/Migrations/20210909113934_Added_Inbox.cs delete mode 100644 test/DistEvents/DistDemoApp/Migrations/20210909182251_Added_Inbox_Process_Columns.Designer.cs delete mode 100644 test/DistEvents/DistDemoApp/Migrations/20210909182251_Added_Inbox_Process_Columns.cs delete mode 100644 test/DistEvents/DistDemoApp/Migrations/20210910111009_Added_Inbox_New_Cols.cs diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbModule.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbModule.cs index 9a5d327055..7598066579 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbModule.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbModule.cs @@ -35,13 +35,13 @@ namespace Volo.Abp.MongoDB ); context.Services.AddTransient( - typeof(IDbContextEventOutbox<>), - typeof(DbContextEventOutbox<>) + typeof(IMongoDbContextEventOutbox<>), + typeof(MongoDbContextEventOutbox<>) ); context.Services.AddTransient( - typeof(IDbContextEventInbox<>), - typeof(DbContextEventInbox<>) + typeof(IMongoDbContextEventInbox<>), + typeof(MongoDbContextEventInbox<>) ); } } diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/DbContextEventInbox.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/DbContextEventInbox.cs deleted file mode 100644 index 955f142add..0000000000 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/DbContextEventInbox.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using Volo.Abp.EventBus.Distributed; - -namespace Volo.Abp.MongoDB.DistributedEvents -{ - public class DbContextEventInbox : IDbContextEventInbox - where TDbContext : IHasEventInbox - { - public Task EnqueueAsync(IncomingEventInfo incomingEvent) - { - throw new NotImplementedException(); - } - - public Task> GetWaitingEventsAsync(int maxCount) - { - throw new NotImplementedException(); - } - - public Task MarkAsProcessedAsync(Guid id) - { - throw new NotImplementedException(); - } - - public Task ExistsByMessageIdAsync(string messageId) - { - throw new NotImplementedException(); - } - - public Task DeleteOldEventsAsync() - { - throw new NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IDbContextEventInbox.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IMongoDbContextEventInbox.cs similarity index 66% rename from framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IDbContextEventInbox.cs rename to framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IMongoDbContextEventInbox.cs index d76bac2412..71e0d14562 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IDbContextEventInbox.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IMongoDbContextEventInbox.cs @@ -2,7 +2,7 @@ using Volo.Abp.EventBus.Distributed; namespace Volo.Abp.MongoDB.DistributedEvents { - public interface IDbContextEventInbox : IEventInbox + public interface IMongoDbContextEventInbox : IEventInbox where TDbContext : IHasEventInbox { diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IDbContextEventOutbox.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IMongoDbContextEventOutbox.cs similarity index 66% rename from framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IDbContextEventOutbox.cs rename to framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IMongoDbContextEventOutbox.cs index bcc0a4705a..ddb9cd19c5 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IDbContextEventOutbox.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IMongoDbContextEventOutbox.cs @@ -2,7 +2,7 @@ using Volo.Abp.EventBus.Distributed; namespace Volo.Abp.MongoDB.DistributedEvents { - public interface IDbContextEventOutbox : IEventOutbox + public interface IMongoDbContextEventOutbox : IEventOutbox where TDbContext : IHasEventOutbox { diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventInbox.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventInbox.cs new file mode 100644 index 0000000000..d98e144ada --- /dev/null +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventInbox.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using MongoDB.Driver; +using MongoDB.Driver.Linq; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.Timing; +using Volo.Abp.Uow; + +namespace Volo.Abp.MongoDB.DistributedEvents +{ + public class MongoDbContextEventInbox : IMongoDbContextEventInbox + where TMongoDbContext : IHasEventInbox + { + protected IMongoDbContextProvider DbContextProvider { get; } + protected IClock Clock { get; } + + public MongoDbContextEventInbox( + IMongoDbContextProvider dbContextProvider, + IClock clock) + { + DbContextProvider = dbContextProvider; + Clock = clock; + } + + + [UnitOfWork] + public virtual async Task EnqueueAsync(IncomingEventInfo incomingEvent) + { + var dbContext = await DbContextProvider.GetDbContextAsync(); + if (dbContext.SessionHandle != null) + { + await dbContext.IncomingEvents.InsertOneAsync( + dbContext.SessionHandle, + new IncomingEventRecord(incomingEvent) + ); + } + else + { + await dbContext.IncomingEvents.InsertOneAsync( + new IncomingEventRecord(incomingEvent) + ); + } + } + + [UnitOfWork] + public virtual async Task> GetWaitingEventsAsync(int maxCount) + { + var dbContext = await DbContextProvider.GetDbContextAsync(); + + var outgoingEventRecords = await dbContext + .IncomingEvents + .AsQueryable() + .Where(x => !x.Processed) + .OrderBy(x => x.CreationTime) + .Take(maxCount) + .ToListAsync(); + + return outgoingEventRecords + .Select(x => x.ToIncomingEventInfo()) + .ToList(); + } + + [UnitOfWork] + public async Task MarkAsProcessedAsync(Guid id) + { + throw new NotImplementedException(); + } + + public Task ExistsByMessageIdAsync(string messageId) + { + throw new NotImplementedException(); + } + + public Task DeleteOldEventsAsync() + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/DbContextEventOutbox.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventOutbox.cs similarity index 79% rename from framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/DbContextEventOutbox.cs rename to framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventOutbox.cs index 3b054732be..1bec9e0834 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/DbContextEventOutbox.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventOutbox.cs @@ -6,8 +6,8 @@ using Volo.Abp.Uow; namespace Volo.Abp.MongoDB.DistributedEvents { - public class DbContextEventOutbox : IDbContextEventOutbox - where TDbContext : IHasEventOutbox + public class MongoDbContextEventOutbox : IMongoDbContextEventOutbox + where TMongoDbContext : IHasEventOutbox { public Task EnqueueAsync(OutgoingEventInfo outgoingEvent) { diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbInboxConfigExtensions.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbInboxConfigExtensions.cs new file mode 100644 index 0000000000..27be4a078b --- /dev/null +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbInboxConfigExtensions.cs @@ -0,0 +1,13 @@ +using Volo.Abp.EventBus.Distributed; + +namespace Volo.Abp.MongoDB.DistributedEvents +{ + public static class MongoDbInboxConfigExtensions + { + public static void UseMongoDbContext(this InboxConfig outboxConfig) + where TMongoDbContext : IHasEventInbox + { + outboxConfig.ImplementationType = typeof(IMongoDbContextEventInbox); + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbOutboxConfigExtensions.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbOutboxConfigExtensions.cs new file mode 100644 index 0000000000..6da1513451 --- /dev/null +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbOutboxConfigExtensions.cs @@ -0,0 +1,13 @@ +using Volo.Abp.EventBus.Distributed; + +namespace Volo.Abp.MongoDB.DistributedEvents +{ + public static class MongoDbOutboxConfigExtensions + { + public static void UseMongoDbContext(this OutboxConfig outboxConfig) + where TMongoDbContext : IHasEventOutbox + { + outboxConfig.ImplementationType = typeof(IMongoDbContextEventOutbox); + } + } +} \ No newline at end of file diff --git a/test/DistEvents/DistDemoApp/DistDemoApp.csproj b/test/DistEvents/DistDemoApp.EfCoreRabbitMq/DistDemoApp.EfCoreRabbitMq.csproj similarity index 58% rename from test/DistEvents/DistDemoApp/DistDemoApp.csproj rename to test/DistEvents/DistDemoApp.EfCoreRabbitMq/DistDemoApp.EfCoreRabbitMq.csproj index 66623bfde4..fa3ffda64d 100644 --- a/test/DistEvents/DistDemoApp/DistDemoApp.csproj +++ b/test/DistEvents/DistDemoApp.EfCoreRabbitMq/DistDemoApp.EfCoreRabbitMq.csproj @@ -3,22 +3,13 @@ Exe net5.0 + DistDemoApp - - - - - - - - - - - + diff --git a/test/DistEvents/DistDemoApp/DistDemoAppModule.cs b/test/DistEvents/DistDemoApp.EfCoreRabbitMq/DistDemoAppEfCoreRabbitMqModule.cs similarity index 54% rename from test/DistEvents/DistDemoApp/DistDemoAppModule.cs rename to test/DistEvents/DistDemoApp.EfCoreRabbitMq/DistDemoAppEfCoreRabbitMqModule.cs index b7fbe1c930..da2e7a1445 100644 --- a/test/DistEvents/DistDemoApp/DistDemoAppModule.cs +++ b/test/DistEvents/DistDemoApp.EfCoreRabbitMq/DistDemoAppEfCoreRabbitMqModule.cs @@ -1,13 +1,7 @@ -using Medallion.Threading; -using Medallion.Threading.Redis; using Microsoft.Extensions.DependencyInjection; -using StackExchange.Redis; -using Volo.Abp.Autofac; -using Volo.Abp.Domain.Entities.Events.Distributed; using Volo.Abp.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore.DistributedEvents; using Volo.Abp.EntityFrameworkCore.SqlServer; -using Volo.Abp.EventBus.Boxes; using Volo.Abp.EventBus.Distributed; using Volo.Abp.EventBus.RabbitMq; using Volo.Abp.Modularity; @@ -16,18 +10,13 @@ namespace DistDemoApp { [DependsOn( typeof(AbpEntityFrameworkCoreSqlServerModule), - typeof(AbpAutofacModule), typeof(AbpEventBusRabbitMqModule), - typeof(AbpEventBusBoxesModule) + typeof(DistDemoAppSharedModule) )] - public class DistDemoAppModule : AbpModule + public class DistDemoAppEfCoreRabbitMqModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { - var configuration = context.Services.GetConfiguration(); - - context.Services.AddHostedService(); - context.Services.AddAbpDbContext(options => { options.AddDefaultRepositories(); @@ -38,12 +27,6 @@ namespace DistDemoApp options.UseSqlServer(); }); - Configure(options => - { - options.EtoMappings.Add(); - options.AutoEventSelectors.Add(); - }); - Configure(options => { options.Outboxes.Configure(config => @@ -56,12 +39,6 @@ namespace DistDemoApp config.UseDbContext(); }); }); - - context.Services.AddSingleton(sp => - { - var connection = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]); - return new RedisDistributedSynchronizationProvider(connection.GetDatabase()); - }); } } } \ No newline at end of file diff --git a/test/DistEvents/DistDemoApp/Migrations/20210910111009_Added_Inbox_New_Cols.Designer.cs b/test/DistEvents/DistDemoApp.EfCoreRabbitMq/Migrations/20210910152547_Added_Boxes_Initial.Designer.cs similarity index 98% rename from test/DistEvents/DistDemoApp/Migrations/20210910111009_Added_Inbox_New_Cols.Designer.cs rename to test/DistEvents/DistDemoApp.EfCoreRabbitMq/Migrations/20210910152547_Added_Boxes_Initial.Designer.cs index 7b552dfcfc..292cff66f9 100644 --- a/test/DistEvents/DistDemoApp/Migrations/20210910111009_Added_Inbox_New_Cols.Designer.cs +++ b/test/DistEvents/DistDemoApp.EfCoreRabbitMq/Migrations/20210910152547_Added_Boxes_Initial.Designer.cs @@ -11,8 +11,8 @@ using Volo.Abp.EntityFrameworkCore; namespace DistDemoApp.Migrations { [DbContext(typeof(TodoDbContext))] - [Migration("20210910111009_Added_Inbox_New_Cols")] - partial class Added_Inbox_New_Cols + [Migration("20210910152547_Added_Boxes_Initial")] + partial class Added_Boxes_Initial { protected override void BuildTargetModel(ModelBuilder modelBuilder) { diff --git a/test/DistEvents/DistDemoApp.EfCoreRabbitMq/Migrations/20210910152547_Added_Boxes_Initial.cs b/test/DistEvents/DistDemoApp.EfCoreRabbitMq/Migrations/20210910152547_Added_Boxes_Initial.cs new file mode 100644 index 0000000000..9094eaa8c9 --- /dev/null +++ b/test/DistEvents/DistDemoApp.EfCoreRabbitMq/Migrations/20210910152547_Added_Boxes_Initial.cs @@ -0,0 +1,103 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace DistDemoApp.Migrations +{ + public partial class Added_Boxes_Initial : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "AbpEventInbox", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true), + MessageId = table.Column(type: "nvarchar(450)", nullable: true), + EventName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + EventData = table.Column(type: "varbinary(max)", nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false), + Processed = table.Column(type: "bit", nullable: false), + ProcessedTime = table.Column(type: "datetime2", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpEventInbox", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpEventOutbox", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true), + EventName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + EventData = table.Column(type: "varbinary(max)", nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpEventOutbox", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "TodoItems", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + Text = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true), + ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: true), + CreationTime = table.Column(type: "datetime2", nullable: false), + CreatorId = table.Column(type: "uniqueidentifier", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_TodoItems", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "TodoSummaries", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Year = table.Column(type: "int", nullable: false), + Month = table.Column(type: "tinyint", nullable: false), + Day = table.Column(type: "tinyint", nullable: false), + TotalCount = table.Column(type: "int", nullable: false), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true), + ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_TodoSummaries", x => x.Id); + }); + + migrationBuilder.CreateIndex( + name: "IX_AbpEventInbox_MessageId", + table: "AbpEventInbox", + column: "MessageId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpEventInbox_Processed_CreationTime", + table: "AbpEventInbox", + columns: new[] { "Processed", "CreationTime" }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AbpEventInbox"); + + migrationBuilder.DropTable( + name: "AbpEventOutbox"); + + migrationBuilder.DropTable( + name: "TodoItems"); + + migrationBuilder.DropTable( + name: "TodoSummaries"); + } + } +} diff --git a/test/DistEvents/DistDemoApp/Migrations/TodoDbContextModelSnapshot.cs b/test/DistEvents/DistDemoApp.EfCoreRabbitMq/Migrations/TodoDbContextModelSnapshot.cs similarity index 100% rename from test/DistEvents/DistDemoApp/Migrations/TodoDbContextModelSnapshot.cs rename to test/DistEvents/DistDemoApp.EfCoreRabbitMq/Migrations/TodoDbContextModelSnapshot.cs diff --git a/test/DistEvents/DistDemoApp/Program.cs b/test/DistEvents/DistDemoApp.EfCoreRabbitMq/Program.cs similarity index 95% rename from test/DistEvents/DistDemoApp/Program.cs rename to test/DistEvents/DistDemoApp.EfCoreRabbitMq/Program.cs index 676a07e357..597b29ae22 100644 --- a/test/DistEvents/DistDemoApp/Program.cs +++ b/test/DistEvents/DistDemoApp.EfCoreRabbitMq/Program.cs @@ -51,7 +51,7 @@ namespace DistDemoApp }) .ConfigureServices((hostContext, services) => { - services.AddApplication(); + services.AddApplication(); }); } } diff --git a/test/DistEvents/DistDemoApp/TodoDbContext.cs b/test/DistEvents/DistDemoApp.EfCoreRabbitMq/TodoDbContext.cs similarity index 100% rename from test/DistEvents/DistDemoApp/TodoDbContext.cs rename to test/DistEvents/DistDemoApp.EfCoreRabbitMq/TodoDbContext.cs diff --git a/test/DistEvents/DistDemoApp/TodoDbContextFactory.cs b/test/DistEvents/DistDemoApp.EfCoreRabbitMq/TodoDbContextFactory.cs similarity index 100% rename from test/DistEvents/DistDemoApp/TodoDbContextFactory.cs rename to test/DistEvents/DistDemoApp.EfCoreRabbitMq/TodoDbContextFactory.cs diff --git a/test/DistEvents/DistDemoApp/appsettings.json b/test/DistEvents/DistDemoApp.EfCoreRabbitMq/appsettings.json similarity index 100% rename from test/DistEvents/DistDemoApp/appsettings.json rename to test/DistEvents/DistDemoApp.EfCoreRabbitMq/appsettings.json diff --git a/test/DistEvents/DistDemoApp.MongoDbKafka/DistDemoApp.MongoDbKafka.csproj b/test/DistEvents/DistDemoApp.MongoDbKafka/DistDemoApp.MongoDbKafka.csproj new file mode 100644 index 0000000000..cfd73d51bb --- /dev/null +++ b/test/DistEvents/DistDemoApp.MongoDbKafka/DistDemoApp.MongoDbKafka.csproj @@ -0,0 +1,9 @@ + + + + Exe + net5.0 + DistDemoApp + + + diff --git a/test/DistEvents/DistDemoApp.MongoDbKafka/Program.cs b/test/DistEvents/DistDemoApp.MongoDbKafka/Program.cs new file mode 100644 index 0000000000..d0e4cdf4ca --- /dev/null +++ b/test/DistEvents/DistDemoApp.MongoDbKafka/Program.cs @@ -0,0 +1,12 @@ +using System; + +namespace DistDemoApp +{ + class Program + { + static void Main(string[] args) + { + Console.WriteLine("Hello World!"); + } + } +} \ No newline at end of file diff --git a/test/DistEvents/DistDemoApp/DemoService.cs b/test/DistEvents/DistDemoApp.Shared/DemoService.cs similarity index 100% rename from test/DistEvents/DistDemoApp/DemoService.cs rename to test/DistEvents/DistDemoApp.Shared/DemoService.cs diff --git a/test/DistEvents/DistDemoApp.Shared/DistDemoApp.Shared.csproj b/test/DistEvents/DistDemoApp.Shared/DistDemoApp.Shared.csproj new file mode 100644 index 0000000000..4dc9d1dd64 --- /dev/null +++ b/test/DistEvents/DistDemoApp.Shared/DistDemoApp.Shared.csproj @@ -0,0 +1,23 @@ + + + + net5.0 + DistDemoApp + + + + + + + + + + + + + + + + + + diff --git a/test/DistEvents/DistDemoApp/MyProjectNameHostedService.cs b/test/DistEvents/DistDemoApp.Shared/DistDemoAppHostedService.cs similarity index 90% rename from test/DistEvents/DistDemoApp/MyProjectNameHostedService.cs rename to test/DistEvents/DistDemoApp.Shared/DistDemoAppHostedService.cs index 7522d9fe9d..ba72d6902a 100644 --- a/test/DistEvents/DistDemoApp/MyProjectNameHostedService.cs +++ b/test/DistEvents/DistDemoApp.Shared/DistDemoAppHostedService.cs @@ -6,13 +6,13 @@ using Volo.Abp; namespace DistDemoApp { - public class MyProjectNameHostedService : IHostedService + public class DistDemoAppHostedService : IHostedService { private readonly IAbpApplicationWithExternalServiceProvider _application; private readonly IServiceProvider _serviceProvider; private readonly DemoService _demoService; - public MyProjectNameHostedService( + public DistDemoAppHostedService( IAbpApplicationWithExternalServiceProvider application, IServiceProvider serviceProvider, DemoService demoService) diff --git a/test/DistEvents/DistDemoApp.Shared/DistDemoAppSharedModule.cs b/test/DistEvents/DistDemoApp.Shared/DistDemoAppSharedModule.cs new file mode 100644 index 0000000000..5755f63677 --- /dev/null +++ b/test/DistEvents/DistDemoApp.Shared/DistDemoAppSharedModule.cs @@ -0,0 +1,39 @@ +using Medallion.Threading; +using Medallion.Threading.Redis; +using Microsoft.Extensions.DependencyInjection; +using StackExchange.Redis; +using Volo.Abp.Autofac; +using Volo.Abp.Domain; +using Volo.Abp.Domain.Entities.Events.Distributed; +using Volo.Abp.EventBus.Boxes; +using Volo.Abp.Modularity; + +namespace DistDemoApp +{ + [DependsOn( + typeof(AbpAutofacModule), + typeof(AbpDddDomainModule), + typeof(AbpEventBusBoxesModule) + )] + public class DistDemoAppSharedModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + var configuration = context.Services.GetConfiguration(); + + context.Services.AddHostedService(); + + Configure(options => + { + options.EtoMappings.Add(); + options.AutoEventSelectors.Add(); + }); + + context.Services.AddSingleton(sp => + { + var connection = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]); + return new RedisDistributedSynchronizationProvider(connection.GetDatabase()); + }); + } + } +} \ No newline at end of file diff --git a/test/DistEvents/DistDemoApp/TodoEventHandler.cs b/test/DistEvents/DistDemoApp.Shared/TodoEventHandler.cs similarity index 100% rename from test/DistEvents/DistDemoApp/TodoEventHandler.cs rename to test/DistEvents/DistDemoApp.Shared/TodoEventHandler.cs diff --git a/test/DistEvents/DistDemoApp/TodoItem.cs b/test/DistEvents/DistDemoApp.Shared/TodoItem.cs similarity index 100% rename from test/DistEvents/DistDemoApp/TodoItem.cs rename to test/DistEvents/DistDemoApp.Shared/TodoItem.cs diff --git a/test/DistEvents/DistDemoApp/TodoItemEto.cs b/test/DistEvents/DistDemoApp.Shared/TodoItemEto.cs similarity index 100% rename from test/DistEvents/DistDemoApp/TodoItemEto.cs rename to test/DistEvents/DistDemoApp.Shared/TodoItemEto.cs diff --git a/test/DistEvents/DistDemoApp/TodoItemObjectMapper.cs b/test/DistEvents/DistDemoApp.Shared/TodoItemObjectMapper.cs similarity index 100% rename from test/DistEvents/DistDemoApp/TodoItemObjectMapper.cs rename to test/DistEvents/DistDemoApp.Shared/TodoItemObjectMapper.cs diff --git a/test/DistEvents/DistDemoApp/TodoSummary.cs b/test/DistEvents/DistDemoApp.Shared/TodoSummary.cs similarity index 100% rename from test/DistEvents/DistDemoApp/TodoSummary.cs rename to test/DistEvents/DistDemoApp.Shared/TodoSummary.cs diff --git a/test/DistEvents/DistDemoApp/Migrations/20210825110134_Initial.Designer.cs b/test/DistEvents/DistDemoApp/Migrations/20210825110134_Initial.Designer.cs deleted file mode 100644 index 990ef3e967..0000000000 --- a/test/DistEvents/DistDemoApp/Migrations/20210825110134_Initial.Designer.cs +++ /dev/null @@ -1,61 +0,0 @@ -// -using System; -using DistDemoApp; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Volo.Abp.EntityFrameworkCore; - -namespace DistDemoApp.Migrations -{ - [DbContext(typeof(TodoDbContext))] - [Migration("20210825110134_Initial")] - partial class Initial - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("ProductVersion", "5.0.9") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - modelBuilder.Entity("DistDemoApp.TodoItem", b => - { - b.Property("Id") - .HasColumnType("uniqueidentifier"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasMaxLength(40) - .HasColumnType("nvarchar(40)") - .HasColumnName("ConcurrencyStamp"); - - b.Property("CreationTime") - .HasColumnType("datetime2") - .HasColumnName("CreationTime"); - - b.Property("CreatorId") - .HasColumnType("uniqueidentifier") - .HasColumnName("CreatorId"); - - b.Property("ExtraProperties") - .HasColumnType("nvarchar(max)") - .HasColumnName("ExtraProperties"); - - b.Property("Text") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.HasKey("Id"); - - b.ToTable("TodoItems"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/test/DistEvents/DistDemoApp/Migrations/20210825110134_Initial.cs b/test/DistEvents/DistDemoApp/Migrations/20210825110134_Initial.cs deleted file mode 100644 index b84d1f433f..0000000000 --- a/test/DistEvents/DistDemoApp/Migrations/20210825110134_Initial.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace DistDemoApp.Migrations -{ - public partial class Initial : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "TodoItems", - columns: table => new - { - Id = table.Column(type: "uniqueidentifier", nullable: false), - Text = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), - ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true), - ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: true), - CreationTime = table.Column(type: "datetime2", nullable: false), - CreatorId = table.Column(type: "uniqueidentifier", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_TodoItems", x => x.Id); - }); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "TodoItems"); - } - } -} diff --git a/test/DistEvents/DistDemoApp/Migrations/20210825112717_Added_Summary_Table.Designer.cs b/test/DistEvents/DistDemoApp/Migrations/20210825112717_Added_Summary_Table.Designer.cs deleted file mode 100644 index 4c2cf9abbb..0000000000 --- a/test/DistEvents/DistDemoApp/Migrations/20210825112717_Added_Summary_Table.Designer.cs +++ /dev/null @@ -1,95 +0,0 @@ -// -using System; -using DistDemoApp; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Volo.Abp.EntityFrameworkCore; - -namespace DistDemoApp.Migrations -{ - [DbContext(typeof(TodoDbContext))] - [Migration("20210825112717_Added_Summary_Table")] - partial class Added_Summary_Table - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("ProductVersion", "5.0.9") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - modelBuilder.Entity("DistDemoApp.TodoItem", b => - { - b.Property("Id") - .HasColumnType("uniqueidentifier"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasMaxLength(40) - .HasColumnType("nvarchar(40)") - .HasColumnName("ConcurrencyStamp"); - - b.Property("CreationTime") - .HasColumnType("datetime2") - .HasColumnName("CreationTime"); - - b.Property("CreatorId") - .HasColumnType("uniqueidentifier") - .HasColumnName("CreatorId"); - - b.Property("ExtraProperties") - .HasColumnType("nvarchar(max)") - .HasColumnName("ExtraProperties"); - - b.Property("Text") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.HasKey("Id"); - - b.ToTable("TodoItems"); - }); - - modelBuilder.Entity("DistDemoApp.TodoSummary", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasMaxLength(40) - .HasColumnType("nvarchar(40)") - .HasColumnName("ConcurrencyStamp"); - - b.Property("Day") - .HasColumnType("tinyint"); - - b.Property("ExtraProperties") - .HasColumnType("nvarchar(max)") - .HasColumnName("ExtraProperties"); - - b.Property("Month") - .HasColumnType("tinyint"); - - b.Property("TotalCount") - .HasColumnType("int"); - - b.Property("Year") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.ToTable("TodoSummaries"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/test/DistEvents/DistDemoApp/Migrations/20210825112717_Added_Summary_Table.cs b/test/DistEvents/DistDemoApp/Migrations/20210825112717_Added_Summary_Table.cs deleted file mode 100644 index 7a7f167470..0000000000 --- a/test/DistEvents/DistDemoApp/Migrations/20210825112717_Added_Summary_Table.cs +++ /dev/null @@ -1,34 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -namespace DistDemoApp.Migrations -{ - public partial class Added_Summary_Table : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "TodoSummaries", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Year = table.Column(type: "int", nullable: false), - Month = table.Column(type: "tinyint", nullable: false), - Day = table.Column(type: "tinyint", nullable: false), - TotalCount = table.Column(type: "int", nullable: false), - ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true), - ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_TodoSummaries", x => x.Id); - }); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "TodoSummaries"); - } - } -} diff --git a/test/DistEvents/DistDemoApp/Migrations/20210908063422_Added_Outbox.Designer.cs b/test/DistEvents/DistDemoApp/Migrations/20210908063422_Added_Outbox.Designer.cs deleted file mode 100644 index 9c350598bf..0000000000 --- a/test/DistEvents/DistDemoApp/Migrations/20210908063422_Added_Outbox.Designer.cs +++ /dev/null @@ -1,118 +0,0 @@ -// -using System; -using DistDemoApp; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Volo.Abp.EntityFrameworkCore; - -namespace DistDemoApp.Migrations -{ - [DbContext(typeof(TodoDbContext))] - [Migration("20210908063422_Added_Outbox")] - partial class Added_Outbox - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("ProductVersion", "5.0.9") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - modelBuilder.Entity("DistDemoApp.TodoItem", b => - { - b.Property("Id") - .HasColumnType("uniqueidentifier"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasMaxLength(40) - .HasColumnType("nvarchar(40)") - .HasColumnName("ConcurrencyStamp"); - - b.Property("CreationTime") - .HasColumnType("datetime2") - .HasColumnName("CreationTime"); - - b.Property("CreatorId") - .HasColumnType("uniqueidentifier") - .HasColumnName("CreatorId"); - - b.Property("ExtraProperties") - .HasColumnType("nvarchar(max)") - .HasColumnName("ExtraProperties"); - - b.Property("Text") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.HasKey("Id"); - - b.ToTable("TodoItems"); - }); - - modelBuilder.Entity("DistDemoApp.TodoSummary", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasMaxLength(40) - .HasColumnType("nvarchar(40)") - .HasColumnName("ConcurrencyStamp"); - - b.Property("Day") - .HasColumnType("tinyint"); - - b.Property("ExtraProperties") - .HasColumnType("nvarchar(max)") - .HasColumnName("ExtraProperties"); - - b.Property("Month") - .HasColumnType("tinyint"); - - b.Property("TotalCount") - .HasColumnType("int"); - - b.Property("Year") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.ToTable("TodoSummaries"); - }); - - modelBuilder.Entity("Volo.Abp.EntityFrameworkCore.DistributedEvents.OutgoingEventRecord", b => - { - b.Property("Id") - .HasColumnType("uniqueidentifier"); - - b.Property("EventData") - .IsRequired() - .HasColumnType("varbinary(max)"); - - b.Property("EventName") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("ExtraProperties") - .HasColumnType("nvarchar(max)") - .HasColumnName("ExtraProperties"); - - b.HasKey("Id"); - - b.ToTable("AbpEventOutbox"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/test/DistEvents/DistDemoApp/Migrations/20210908063422_Added_Outbox.cs b/test/DistEvents/DistDemoApp/Migrations/20210908063422_Added_Outbox.cs deleted file mode 100644 index 2954acdac7..0000000000 --- a/test/DistEvents/DistDemoApp/Migrations/20210908063422_Added_Outbox.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace DistDemoApp.Migrations -{ - public partial class Added_Outbox : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "AbpEventOutbox", - columns: table => new - { - Id = table.Column(type: "uniqueidentifier", nullable: false), - ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true), - EventName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), - EventData = table.Column(type: "varbinary(max)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AbpEventOutbox", x => x.Id); - }); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "AbpEventOutbox"); - } - } -} diff --git a/test/DistEvents/DistDemoApp/Migrations/20210908075344_Added_Outbox_CreationTime.Designer.cs b/test/DistEvents/DistDemoApp/Migrations/20210908075344_Added_Outbox_CreationTime.Designer.cs deleted file mode 100644 index def5ebc7d7..0000000000 --- a/test/DistEvents/DistDemoApp/Migrations/20210908075344_Added_Outbox_CreationTime.Designer.cs +++ /dev/null @@ -1,122 +0,0 @@ -// -using System; -using DistDemoApp; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Volo.Abp.EntityFrameworkCore; - -namespace DistDemoApp.Migrations -{ - [DbContext(typeof(TodoDbContext))] - [Migration("20210908075344_Added_Outbox_CreationTime")] - partial class Added_Outbox_CreationTime - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("ProductVersion", "5.0.9") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - modelBuilder.Entity("DistDemoApp.TodoItem", b => - { - b.Property("Id") - .HasColumnType("uniqueidentifier"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasMaxLength(40) - .HasColumnType("nvarchar(40)") - .HasColumnName("ConcurrencyStamp"); - - b.Property("CreationTime") - .HasColumnType("datetime2") - .HasColumnName("CreationTime"); - - b.Property("CreatorId") - .HasColumnType("uniqueidentifier") - .HasColumnName("CreatorId"); - - b.Property("ExtraProperties") - .HasColumnType("nvarchar(max)") - .HasColumnName("ExtraProperties"); - - b.Property("Text") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.HasKey("Id"); - - b.ToTable("TodoItems"); - }); - - modelBuilder.Entity("DistDemoApp.TodoSummary", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasMaxLength(40) - .HasColumnType("nvarchar(40)") - .HasColumnName("ConcurrencyStamp"); - - b.Property("Day") - .HasColumnType("tinyint"); - - b.Property("ExtraProperties") - .HasColumnType("nvarchar(max)") - .HasColumnName("ExtraProperties"); - - b.Property("Month") - .HasColumnType("tinyint"); - - b.Property("TotalCount") - .HasColumnType("int"); - - b.Property("Year") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.ToTable("TodoSummaries"); - }); - - modelBuilder.Entity("Volo.Abp.EntityFrameworkCore.DistributedEvents.OutgoingEventRecord", b => - { - b.Property("Id") - .HasColumnType("uniqueidentifier"); - - b.Property("CreationTime") - .HasColumnType("datetime2") - .HasColumnName("CreationTime"); - - b.Property("EventData") - .IsRequired() - .HasColumnType("varbinary(max)"); - - b.Property("EventName") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("ExtraProperties") - .HasColumnType("nvarchar(max)") - .HasColumnName("ExtraProperties"); - - b.HasKey("Id"); - - b.ToTable("AbpEventOutbox"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/test/DistEvents/DistDemoApp/Migrations/20210908075344_Added_Outbox_CreationTime.cs b/test/DistEvents/DistDemoApp/Migrations/20210908075344_Added_Outbox_CreationTime.cs deleted file mode 100644 index 2899933b8f..0000000000 --- a/test/DistEvents/DistDemoApp/Migrations/20210908075344_Added_Outbox_CreationTime.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace DistDemoApp.Migrations -{ - public partial class Added_Outbox_CreationTime : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "CreationTime", - table: "AbpEventOutbox", - type: "datetime2", - nullable: false, - defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "CreationTime", - table: "AbpEventOutbox"); - } - } -} diff --git a/test/DistEvents/DistDemoApp/Migrations/20210909113934_Added_Inbox.Designer.cs b/test/DistEvents/DistDemoApp/Migrations/20210909113934_Added_Inbox.Designer.cs deleted file mode 100644 index e02cee4b76..0000000000 --- a/test/DistEvents/DistDemoApp/Migrations/20210909113934_Added_Inbox.Designer.cs +++ /dev/null @@ -1,149 +0,0 @@ -// -using System; -using DistDemoApp; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Volo.Abp.EntityFrameworkCore; - -namespace DistDemoApp.Migrations -{ - [DbContext(typeof(TodoDbContext))] - [Migration("20210909113934_Added_Inbox")] - partial class Added_Inbox - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("ProductVersion", "5.0.9") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - modelBuilder.Entity("DistDemoApp.TodoItem", b => - { - b.Property("Id") - .HasColumnType("uniqueidentifier"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasMaxLength(40) - .HasColumnType("nvarchar(40)") - .HasColumnName("ConcurrencyStamp"); - - b.Property("CreationTime") - .HasColumnType("datetime2") - .HasColumnName("CreationTime"); - - b.Property("CreatorId") - .HasColumnType("uniqueidentifier") - .HasColumnName("CreatorId"); - - b.Property("ExtraProperties") - .HasColumnType("nvarchar(max)") - .HasColumnName("ExtraProperties"); - - b.Property("Text") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.HasKey("Id"); - - b.ToTable("TodoItems"); - }); - - modelBuilder.Entity("DistDemoApp.TodoSummary", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasMaxLength(40) - .HasColumnType("nvarchar(40)") - .HasColumnName("ConcurrencyStamp"); - - b.Property("Day") - .HasColumnType("tinyint"); - - b.Property("ExtraProperties") - .HasColumnType("nvarchar(max)") - .HasColumnName("ExtraProperties"); - - b.Property("Month") - .HasColumnType("tinyint"); - - b.Property("TotalCount") - .HasColumnType("int"); - - b.Property("Year") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.ToTable("TodoSummaries"); - }); - - modelBuilder.Entity("Volo.Abp.EntityFrameworkCore.DistributedEvents.IncomingEventRecord", b => - { - b.Property("Id") - .HasColumnType("uniqueidentifier"); - - b.Property("CreationTime") - .HasColumnType("datetime2") - .HasColumnName("CreationTime"); - - b.Property("EventData") - .IsRequired() - .HasColumnType("varbinary(max)"); - - b.Property("EventName") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("ExtraProperties") - .HasColumnType("nvarchar(max)") - .HasColumnName("ExtraProperties"); - - b.HasKey("Id"); - - b.ToTable("AbpEventInbox"); - }); - - modelBuilder.Entity("Volo.Abp.EntityFrameworkCore.DistributedEvents.OutgoingEventRecord", b => - { - b.Property("Id") - .HasColumnType("uniqueidentifier"); - - b.Property("CreationTime") - .HasColumnType("datetime2") - .HasColumnName("CreationTime"); - - b.Property("EventData") - .IsRequired() - .HasColumnType("varbinary(max)"); - - b.Property("EventName") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("ExtraProperties") - .HasColumnType("nvarchar(max)") - .HasColumnName("ExtraProperties"); - - b.HasKey("Id"); - - b.ToTable("AbpEventOutbox"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/test/DistEvents/DistDemoApp/Migrations/20210909113934_Added_Inbox.cs b/test/DistEvents/DistDemoApp/Migrations/20210909113934_Added_Inbox.cs deleted file mode 100644 index f154ee3ff6..0000000000 --- a/test/DistEvents/DistDemoApp/Migrations/20210909113934_Added_Inbox.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace DistDemoApp.Migrations -{ - public partial class Added_Inbox : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "AbpEventInbox", - columns: table => new - { - Id = table.Column(type: "uniqueidentifier", nullable: false), - ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true), - EventName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), - EventData = table.Column(type: "varbinary(max)", nullable: false), - CreationTime = table.Column(type: "datetime2", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AbpEventInbox", x => x.Id); - }); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "AbpEventInbox"); - } - } -} diff --git a/test/DistEvents/DistDemoApp/Migrations/20210909182251_Added_Inbox_Process_Columns.Designer.cs b/test/DistEvents/DistDemoApp/Migrations/20210909182251_Added_Inbox_Process_Columns.Designer.cs deleted file mode 100644 index 02404db39f..0000000000 --- a/test/DistEvents/DistDemoApp/Migrations/20210909182251_Added_Inbox_Process_Columns.Designer.cs +++ /dev/null @@ -1,155 +0,0 @@ -// -using System; -using DistDemoApp; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Volo.Abp.EntityFrameworkCore; - -namespace DistDemoApp.Migrations -{ - [DbContext(typeof(TodoDbContext))] - [Migration("20210909182251_Added_Inbox_Process_Columns")] - partial class Added_Inbox_Process_Columns - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("ProductVersion", "5.0.9") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - modelBuilder.Entity("DistDemoApp.TodoItem", b => - { - b.Property("Id") - .HasColumnType("uniqueidentifier"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasMaxLength(40) - .HasColumnType("nvarchar(40)") - .HasColumnName("ConcurrencyStamp"); - - b.Property("CreationTime") - .HasColumnType("datetime2") - .HasColumnName("CreationTime"); - - b.Property("CreatorId") - .HasColumnType("uniqueidentifier") - .HasColumnName("CreatorId"); - - b.Property("ExtraProperties") - .HasColumnType("nvarchar(max)") - .HasColumnName("ExtraProperties"); - - b.Property("Text") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.HasKey("Id"); - - b.ToTable("TodoItems"); - }); - - modelBuilder.Entity("DistDemoApp.TodoSummary", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasMaxLength(40) - .HasColumnType("nvarchar(40)") - .HasColumnName("ConcurrencyStamp"); - - b.Property("Day") - .HasColumnType("tinyint"); - - b.Property("ExtraProperties") - .HasColumnType("nvarchar(max)") - .HasColumnName("ExtraProperties"); - - b.Property("Month") - .HasColumnType("tinyint"); - - b.Property("TotalCount") - .HasColumnType("int"); - - b.Property("Year") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.ToTable("TodoSummaries"); - }); - - modelBuilder.Entity("Volo.Abp.EntityFrameworkCore.DistributedEvents.IncomingEventRecord", b => - { - b.Property("Id") - .HasColumnType("uniqueidentifier"); - - b.Property("CreationTime") - .HasColumnType("datetime2") - .HasColumnName("CreationTime"); - - b.Property("EventData") - .IsRequired() - .HasColumnType("varbinary(max)"); - - b.Property("EventName") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("ExtraProperties") - .HasColumnType("nvarchar(max)") - .HasColumnName("ExtraProperties"); - - b.Property("Processed") - .HasColumnType("bit"); - - b.Property("ProcessedTime") - .HasColumnType("datetime2"); - - b.HasKey("Id"); - - b.ToTable("AbpEventInbox"); - }); - - modelBuilder.Entity("Volo.Abp.EntityFrameworkCore.DistributedEvents.OutgoingEventRecord", b => - { - b.Property("Id") - .HasColumnType("uniqueidentifier"); - - b.Property("CreationTime") - .HasColumnType("datetime2") - .HasColumnName("CreationTime"); - - b.Property("EventData") - .IsRequired() - .HasColumnType("varbinary(max)"); - - b.Property("EventName") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("ExtraProperties") - .HasColumnType("nvarchar(max)") - .HasColumnName("ExtraProperties"); - - b.HasKey("Id"); - - b.ToTable("AbpEventOutbox"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/test/DistEvents/DistDemoApp/Migrations/20210909182251_Added_Inbox_Process_Columns.cs b/test/DistEvents/DistDemoApp/Migrations/20210909182251_Added_Inbox_Process_Columns.cs deleted file mode 100644 index 7da910a1af..0000000000 --- a/test/DistEvents/DistDemoApp/Migrations/20210909182251_Added_Inbox_Process_Columns.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace DistDemoApp.Migrations -{ - public partial class Added_Inbox_Process_Columns : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "Processed", - table: "AbpEventInbox", - type: "bit", - nullable: false, - defaultValue: false); - - migrationBuilder.AddColumn( - name: "ProcessedTime", - table: "AbpEventInbox", - type: "datetime2", - nullable: true); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "Processed", - table: "AbpEventInbox"); - - migrationBuilder.DropColumn( - name: "ProcessedTime", - table: "AbpEventInbox"); - } - } -} diff --git a/test/DistEvents/DistDemoApp/Migrations/20210910111009_Added_Inbox_New_Cols.cs b/test/DistEvents/DistDemoApp/Migrations/20210910111009_Added_Inbox_New_Cols.cs deleted file mode 100644 index 24f65ff23c..0000000000 --- a/test/DistEvents/DistDemoApp/Migrations/20210910111009_Added_Inbox_New_Cols.cs +++ /dev/null @@ -1,41 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -namespace DistDemoApp.Migrations -{ - public partial class Added_Inbox_New_Cols : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "MessageId", - table: "AbpEventInbox", - type: "nvarchar(450)", - nullable: true); - - migrationBuilder.CreateIndex( - name: "IX_AbpEventInbox_MessageId", - table: "AbpEventInbox", - column: "MessageId"); - - migrationBuilder.CreateIndex( - name: "IX_AbpEventInbox_Processed_CreationTime", - table: "AbpEventInbox", - columns: new[] { "Processed", "CreationTime" }); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropIndex( - name: "IX_AbpEventInbox_MessageId", - table: "AbpEventInbox"); - - migrationBuilder.DropIndex( - name: "IX_AbpEventInbox_Processed_CreationTime", - table: "AbpEventInbox"); - - migrationBuilder.DropColumn( - name: "MessageId", - table: "AbpEventInbox"); - } - } -} diff --git a/test/DistEvents/DistEventsDemo.sln b/test/DistEvents/DistEventsDemo.sln index de7a36535a..4e53ba6367 100644 --- a/test/DistEvents/DistEventsDemo.sln +++ b/test/DistEvents/DistEventsDemo.sln @@ -1,6 +1,10 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DistDemoApp", "DistDemoApp\DistDemoApp.csproj", "{10DBC6BC-1269-4C68-9F6C-12209A3FBF5B}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DistDemoApp.EfCoreRabbitMq", "DistDemoApp.EfCoreRabbitMq\DistDemoApp.EfCoreRabbitMq.csproj", "{10DBC6BC-1269-4C68-9F6C-12209A3FBF5B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DistDemoApp.MongoDbKafka", "DistDemoApp.MongoDbKafka\DistDemoApp.MongoDbKafka.csproj", "{19762F48-4CDB-4723-A72F-D859C0DC815A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DistDemoApp.Shared", "DistDemoApp.Shared\DistDemoApp.Shared.csproj", "{C515F4E2-0ED3-4561-BC58-FC633B50E2EB}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -12,5 +16,13 @@ Global {10DBC6BC-1269-4C68-9F6C-12209A3FBF5B}.Debug|Any CPU.Build.0 = Debug|Any CPU {10DBC6BC-1269-4C68-9F6C-12209A3FBF5B}.Release|Any CPU.ActiveCfg = Release|Any CPU {10DBC6BC-1269-4C68-9F6C-12209A3FBF5B}.Release|Any CPU.Build.0 = Release|Any CPU + {19762F48-4CDB-4723-A72F-D859C0DC815A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {19762F48-4CDB-4723-A72F-D859C0DC815A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {19762F48-4CDB-4723-A72F-D859C0DC815A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {19762F48-4CDB-4723-A72F-D859C0DC815A}.Release|Any CPU.Build.0 = Release|Any CPU + {C515F4E2-0ED3-4561-BC58-FC633B50E2EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C515F4E2-0ED3-4561-BC58-FC633B50E2EB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C515F4E2-0ED3-4561-BC58-FC633B50E2EB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C515F4E2-0ED3-4561-BC58-FC633B50E2EB}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal From c8d525716d699c400f0b1fec8d617f93dc50d91a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 10 Sep 2021 19:53:20 +0300 Subject: [PATCH 19/36] Fix concurrencystamp & tests --- .../Abp/EntityFrameworkCore/AbpDbContext.cs | 42 +++++++++---------- 1 file changed, 20 insertions(+), 22 deletions(-) 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 62c8f84d38..8e7926f9ae 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs @@ -162,7 +162,7 @@ namespace Volo.Abp.EntityFrameworkCore entityChangeList = EntityHistoryHelper.CreateChangeList(ChangeTracker.Entries().ToList()); } - HandleExtraPropertiesOnSave(); + HandlePropertiesBeforeSave(); var eventReport = CreateEventReport(); @@ -320,11 +320,16 @@ namespace Volo.Abp.EntityFrameworkCore } } - protected virtual void HandleExtraPropertiesOnSave() + protected virtual void HandlePropertiesBeforeSave() { foreach (var entry in ChangeTracker.Entries().ToList()) { HandleExtraPropertiesOnSave(entry); + + if (entry.State.IsIn(EntityState.Modified, EntityState.Deleted)) + { + UpdateConcurrencyStamp(entry); + } } } @@ -458,7 +463,6 @@ namespace Volo.Abp.EntityFrameworkCore { if (entry.State == EntityState.Modified && entry.Properties.Any(x => x.IsModified && x.Metadata.ValueGenerated == ValueGenerated.Never)) { - UpdateConcurrencyStamp(entry); SetModificationAuditProperties(entry); if (entry.Entity is ISoftDelete && entry.Entity.As().IsDeleted) @@ -470,7 +474,19 @@ namespace Volo.Abp.EntityFrameworkCore protected virtual void ApplyAbpConceptsForDeletedEntity(EntityEntry entry) { - TryCancelDeletionForSoftDelete(entry); + if (!(entry.Entity is ISoftDelete)) + { + return; + } + + if (IsHardDeleted(entry)) + { + return; + } + + entry.Reload(); + entry.Entity.As().IsDeleted = true; + entry.State = EntityState.Modified; } protected virtual bool IsHardDeleted(EntityEntry entry) @@ -512,24 +528,6 @@ namespace Volo.Abp.EntityFrameworkCore entity.ConcurrencyStamp = Guid.NewGuid().ToString("N"); } - protected virtual bool TryCancelDeletionForSoftDelete(EntityEntry entry) - { - if (!(entry.Entity is ISoftDelete)) - { - return false; - } - - if (IsHardDeleted(entry)) - { - return false; - } - - entry.Reload(); - entry.Entity.As().IsDeleted = true; - entry.State = EntityState.Modified; - return true; - } - protected virtual void CheckAndSetId(EntityEntry entry) { if (entry.Entity is IEntity entityWithGuidId) From 60d97be47787640727ccde8578986a82b37b98f5 Mon Sep 17 00:00:00 2001 From: maliming Date: Tue, 14 Sep 2021 09:49:05 +0800 Subject: [PATCH 20/36] Use `AbpAsyncTimer` to replace `AbpTimer`. --- .../Volo/Abp/EventBus/Boxes/InboxProcessor.cs | 38 +++++++++---------- .../Volo/Abp/EventBus/Boxes/OutboxSender.cs | 20 +++++----- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/InboxProcessor.cs b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/InboxProcessor.cs index bba97fe3d6..ec56db7b0a 100644 --- a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/InboxProcessor.cs +++ b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/InboxProcessor.cs @@ -16,23 +16,23 @@ namespace Volo.Abp.EventBus.Boxes public class InboxProcessor : IInboxProcessor, ITransientDependency { protected IServiceProvider ServiceProvider { get; } - protected AbpTimer Timer { get; } + protected AbpAsyncTimer Timer { get; } protected IDistributedEventBus DistributedEventBus { get; } protected IDistributedLockProvider DistributedLockProvider { get; } protected IUnitOfWorkManager UnitOfWorkManager { get; } protected IClock Clock { get; } protected IEventInbox Inbox { get; private set; } protected InboxConfig InboxConfig { get; private set; } - + protected DateTime? LastCleanTime { get; set; } - + protected string DistributedLockName => "Inbox_" + InboxConfig.Name; public ILogger Logger { get; set; } public InboxProcessor( IServiceProvider serviceProvider, - AbpTimer timer, - IDistributedEventBus distributedEventBus, + AbpAsyncTimer timer, + IDistributedEventBus distributedEventBus, IDistributedLockProvider distributedLockProvider, IUnitOfWorkManager unitOfWorkManager, IClock clock) @@ -47,18 +47,18 @@ namespace Volo.Abp.EventBus.Boxes Timer.Elapsed += TimerOnElapsed; Logger = NullLogger.Instance; } - - private void TimerOnElapsed(object sender, EventArgs e) + + private async Task TimerOnElapsed(AbpAsyncTimer arg) { - AsyncHelper.RunSync(RunAsync); + await RunAsync(); } - + public Task StartAsync(InboxConfig inboxConfig, CancellationToken cancellationToken = default) { InboxConfig = inboxConfig; Inbox = (IEventInbox)ServiceProvider.GetRequiredService(inboxConfig.ImplementationType); Timer.Start(cancellationToken); - return Task.CompletedTask; + return Task.CompletedTask; } public Task StopAsync(CancellationToken cancellationToken = default) @@ -66,7 +66,7 @@ namespace Volo.Abp.EventBus.Boxes Timer.Stop(cancellationToken); return Task.CompletedTask; } - + protected virtual async Task RunAsync() { await using (var handle = await DistributedLockProvider.TryAcquireLockAsync(DistributedLockName)) @@ -74,9 +74,9 @@ namespace Volo.Abp.EventBus.Boxes if (handle != null) { Logger.LogDebug("Obtained the distributed lock: " + DistributedLockName); - + await DeleteOldEventsAsync(); - + while (true) { var waitingEvents = await Inbox.GetWaitingEventsAsync(1000); //TODO: Config? @@ -86,7 +86,7 @@ namespace Volo.Abp.EventBus.Boxes } Logger.LogInformation($"Found {waitingEvents.Count} events in the inbox."); - + foreach (var waitingEvent in waitingEvents) { using (var uow = UnitOfWorkManager.Begin(isTransactional: true, requiresNew: true)) @@ -94,12 +94,12 @@ namespace Volo.Abp.EventBus.Boxes await DistributedEventBus .AsRawEventPublisher() .ProcessRawAsync(InboxConfig, waitingEvent.EventName, waitingEvent.EventData); - + await Inbox.MarkAsProcessedAsync(waitingEvent.Id); - + await uow.CompleteAsync(); } - + Logger.LogInformation($"Processed the incoming event with id = {waitingEvent.Id:N}"); } } @@ -120,8 +120,8 @@ namespace Volo.Abp.EventBus.Boxes } await Inbox.DeleteOldEventsAsync(); - + LastCleanTime = DateTime.Now; } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs index 94d0175e10..df0d616b28 100644 --- a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs +++ b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs @@ -15,7 +15,7 @@ namespace Volo.Abp.EventBus.Boxes public class OutboxSender : IOutboxSender, ITransientDependency { protected IServiceProvider ServiceProvider { get; } - protected AbpTimer Timer { get; } + protected AbpAsyncTimer Timer { get; } protected IDistributedEventBus DistributedEventBus { get; } protected IDistributedLockProvider DistributedLockProvider { get; } protected IEventOutbox Outbox { get; private set; } @@ -25,8 +25,8 @@ namespace Volo.Abp.EventBus.Boxes public OutboxSender( IServiceProvider serviceProvider, - AbpTimer timer, - IDistributedEventBus distributedEventBus, + AbpAsyncTimer timer, + IDistributedEventBus distributedEventBus, IDistributedLockProvider distributedLockProvider) { ServiceProvider = serviceProvider; @@ -51,10 +51,10 @@ namespace Volo.Abp.EventBus.Boxes Timer.Stop(cancellationToken); return Task.CompletedTask; } - - private void TimerOnElapsed(object sender, EventArgs e) + + private async Task TimerOnElapsed(AbpAsyncTimer arg) { - AsyncHelper.RunSync(RunAsync); + await RunAsync(); } protected virtual async Task RunAsync() @@ -64,7 +64,7 @@ namespace Volo.Abp.EventBus.Boxes if (handle != null) { Logger.LogDebug("Obtained the distributed lock: " + DistributedLockName); - + while (true) { var waitingEvents = await Outbox.GetWaitingEventsAsync(1000); //TODO: Config? @@ -74,7 +74,7 @@ namespace Volo.Abp.EventBus.Boxes } Logger.LogInformation($"Found {waitingEvents.Count} events in the outbox."); - + foreach (var waitingEvent in waitingEvents) { await DistributedEventBus @@ -82,7 +82,7 @@ namespace Volo.Abp.EventBus.Boxes .PublishRawAsync(waitingEvent.Id, waitingEvent.EventName, waitingEvent.EventData); await Outbox.DeleteAsync(waitingEvent.Id); - + Logger.LogInformation($"Sent the event to the message broker with id = {waitingEvent.Id:N}"); } } @@ -95,4 +95,4 @@ namespace Volo.Abp.EventBus.Boxes } } } -} \ No newline at end of file +} From 8114a628ac92452cf5721243efea0cf5e2a7a57d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Tue, 14 Sep 2021 18:17:11 +0300 Subject: [PATCH 21/36] delete old todo note --- .../Volo/Abp/EventBus/Boxes/OutboxSender.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs index df0d616b28..261ff6512b 100644 --- a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs +++ b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs @@ -11,7 +11,6 @@ using Volo.Abp.Threading; namespace Volo.Abp.EventBus.Boxes { - //TODO: use distributed lock! public class OutboxSender : IOutboxSender, ITransientDependency { protected IServiceProvider ServiceProvider { get; } From 2db1a1cf91bc2c435751888c5efc433ebb3caf5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 15 Sep 2021 09:22:15 +0300 Subject: [PATCH 22/36] Fast stop on application stop. --- .../Volo/Abp/EventBus/Boxes/InboxProcessor.cs | 17 +++++++++++++--- .../Volo/Abp/EventBus/Boxes/OutboxSender.cs | 11 +++++++--- .../Volo/Abp/EventBus/Boxes/TaskHelper.cs | 20 +++++++++++++++++++ .../DistDemoAppSharedModule.cs | 2 +- 4 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/TaskHelper.cs diff --git a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/InboxProcessor.cs b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/InboxProcessor.cs index ec56db7b0a..c9b45a3ea8 100644 --- a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/InboxProcessor.cs +++ b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/InboxProcessor.cs @@ -28,6 +28,8 @@ namespace Volo.Abp.EventBus.Boxes protected string DistributedLockName => "Inbox_" + InboxConfig.Name; public ILogger Logger { get; set; } + protected CancellationTokenSource StoppingTokenSource { get; } + protected CancellationToken StoppingToken { get; } public InboxProcessor( IServiceProvider serviceProvider, @@ -46,6 +48,8 @@ namespace Volo.Abp.EventBus.Boxes Timer.Period = 2000; //TODO: Config? Timer.Elapsed += TimerOnElapsed; Logger = NullLogger.Instance; + StoppingTokenSource = new CancellationTokenSource(); + StoppingToken = StoppingTokenSource.Token; } private async Task TimerOnElapsed(AbpAsyncTimer arg) @@ -63,13 +67,20 @@ namespace Volo.Abp.EventBus.Boxes public Task StopAsync(CancellationToken cancellationToken = default) { + StoppingTokenSource.Cancel(); Timer.Stop(cancellationToken); + StoppingTokenSource.Dispose(); return Task.CompletedTask; } protected virtual async Task RunAsync() { - await using (var handle = await DistributedLockProvider.TryAcquireLockAsync(DistributedLockName)) + if (StoppingToken.IsCancellationRequested) + { + return; + } + + await using (var handle = await DistributedLockProvider.TryAcquireLockAsync(DistributedLockName, cancellationToken: StoppingToken)) { if (handle != null) { @@ -79,7 +90,7 @@ namespace Volo.Abp.EventBus.Boxes while (true) { - var waitingEvents = await Inbox.GetWaitingEventsAsync(1000); //TODO: Config? + var waitingEvents = await Inbox.GetWaitingEventsAsync(1000); //TODO: Config? Pass StoppingToken! if (waitingEvents.Count <= 0) { break; @@ -107,7 +118,7 @@ namespace Volo.Abp.EventBus.Boxes else { Logger.LogDebug("Could not obtain the distributed lock: " + DistributedLockName); - await Task.Delay(7000); //TODO: Can we pass a cancellation token to cancel on shutdown? (Config?) + await TaskDelayHelper.DelayAsync(15000, StoppingToken); //TODO: Config? } } } diff --git a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs index 261ff6512b..1a2e0b9d79 100644 --- a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs +++ b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs @@ -21,6 +21,9 @@ namespace Volo.Abp.EventBus.Boxes protected OutboxConfig OutboxConfig { get; private set; } protected string DistributedLockName => "Outbox_" + OutboxConfig.Name; public ILogger Logger { get; set; } + + protected CancellationTokenSource StoppingTokenSource { get; } + protected CancellationToken StoppingToken { get; } public OutboxSender( IServiceProvider serviceProvider, @@ -35,6 +38,8 @@ namespace Volo.Abp.EventBus.Boxes Timer.Period = 2000; //TODO: Config? Timer.Elapsed += TimerOnElapsed; Logger = NullLogger.Instance; + StoppingTokenSource = new CancellationTokenSource(); + StoppingToken = StoppingTokenSource.Token; } public virtual Task StartAsync(OutboxConfig outboxConfig, CancellationToken cancellationToken = default) @@ -47,7 +52,9 @@ namespace Volo.Abp.EventBus.Boxes public virtual Task StopAsync(CancellationToken cancellationToken = default) { + StoppingTokenSource.Cancel(); Timer.Stop(cancellationToken); + StoppingTokenSource.Dispose(); return Task.CompletedTask; } @@ -62,8 +69,6 @@ namespace Volo.Abp.EventBus.Boxes { if (handle != null) { - Logger.LogDebug("Obtained the distributed lock: " + DistributedLockName); - while (true) { var waitingEvents = await Outbox.GetWaitingEventsAsync(1000); //TODO: Config? @@ -89,7 +94,7 @@ namespace Volo.Abp.EventBus.Boxes else { Logger.LogDebug("Could not obtain the distributed lock: " + DistributedLockName); - await Task.Delay(7000); //TODO: Can we pass a cancellation token to cancel on shutdown? (Config?) + await TaskDelayHelper.DelayAsync(15000, StoppingToken); //TODO: Config? } } } diff --git a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/TaskHelper.cs b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/TaskHelper.cs new file mode 100644 index 0000000000..87abe18da8 --- /dev/null +++ b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/TaskHelper.cs @@ -0,0 +1,20 @@ +using System.Threading; +using System.Threading.Tasks; + +namespace Volo.Abp.EventBus.Boxes +{ + internal static class TaskDelayHelper + { + public static async Task DelayAsync(int milliseconds, CancellationToken cancellationToken = default) + { + try + { + await Task.Delay(milliseconds, cancellationToken); + } + catch (TaskCanceledException) + { + return; + } + } + } +} \ No newline at end of file diff --git a/test/DistEvents/DistDemoApp.Shared/DistDemoAppSharedModule.cs b/test/DistEvents/DistDemoApp.Shared/DistDemoAppSharedModule.cs index 5755f63677..138b64f567 100644 --- a/test/DistEvents/DistDemoApp.Shared/DistDemoAppSharedModule.cs +++ b/test/DistEvents/DistDemoApp.Shared/DistDemoAppSharedModule.cs @@ -14,7 +14,7 @@ namespace DistDemoApp typeof(AbpAutofacModule), typeof(AbpDddDomainModule), typeof(AbpEventBusBoxesModule) - )] + )] public class DistDemoAppSharedModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) From 4af63febff5d2a3a36a68262de00526da9ee996b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 15 Sep 2021 09:55:26 +0300 Subject: [PATCH 23/36] Rename IRawEventPublisher to ISupportsEventBoxes and refactor methods. --- .../Boxes/AbpDistributedEventBusExtensions.cs | 6 +++--- .../Volo/Abp/EventBus/Boxes/InboxProcessor.cs | 4 ++-- .../Volo/Abp/EventBus/Boxes/OutboxSender.cs | 8 ++++--- .../Kafka/KafkaDistributedEventBus.cs | 21 ++++++++++--------- .../RabbitMq/RabbitMqDistributedEventBus.cs | 14 ++++++++----- .../Rebus/RebusDistributedEventBus.cs | 8 +++++-- .../Distributed/DistributedEventBusBase.cs | 12 ++++++++--- .../Distributed/IRawEventPublisher.cs | 18 ---------------- .../Distributed/ISupportsEventBoxes.cs | 17 +++++++++++++++ 9 files changed, 62 insertions(+), 46 deletions(-) delete mode 100644 framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IRawEventPublisher.cs create mode 100644 framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/ISupportsEventBoxes.cs diff --git a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/AbpDistributedEventBusExtensions.cs b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/AbpDistributedEventBusExtensions.cs index dda6f71245..ed652f677f 100644 --- a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/AbpDistributedEventBusExtensions.cs +++ b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/AbpDistributedEventBusExtensions.cs @@ -4,12 +4,12 @@ namespace Volo.Abp.EventBus.Boxes { public static class AbpDistributedEventBusExtensions { - public static IRawEventPublisher AsRawEventPublisher(this IDistributedEventBus eventBus) + public static ISupportsEventBoxes AsSupportsEventBoxes(this IDistributedEventBus eventBus) { - var rawPublisher = eventBus as IRawEventPublisher; + var rawPublisher = eventBus as ISupportsEventBoxes; if (rawPublisher == null) { - throw new AbpException($"Given type ({eventBus.GetType().AssemblyQualifiedName}) should implement {nameof(IRawEventPublisher)}!"); + throw new AbpException($"Given type ({eventBus.GetType().AssemblyQualifiedName}) should implement {nameof(ISupportsEventBoxes)}!"); } return rawPublisher; diff --git a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/InboxProcessor.cs b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/InboxProcessor.cs index c9b45a3ea8..7f238728f7 100644 --- a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/InboxProcessor.cs +++ b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/InboxProcessor.cs @@ -103,8 +103,8 @@ namespace Volo.Abp.EventBus.Boxes using (var uow = UnitOfWorkManager.Begin(isTransactional: true, requiresNew: true)) { await DistributedEventBus - .AsRawEventPublisher() - .ProcessRawAsync(InboxConfig, waitingEvent.EventName, waitingEvent.EventData); + .AsSupportsEventBoxes() + .ProcessFromInboxAsync(waitingEvent, InboxConfig); await Inbox.MarkAsProcessedAsync(waitingEvent.Id); diff --git a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs index 1a2e0b9d79..1be2374268 100644 --- a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs +++ b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs @@ -82,11 +82,13 @@ namespace Volo.Abp.EventBus.Boxes foreach (var waitingEvent in waitingEvents) { await DistributedEventBus - .AsRawEventPublisher() - .PublishRawAsync(waitingEvent.Id, waitingEvent.EventName, waitingEvent.EventData); + .AsSupportsEventBoxes() + .PublishFromOutboxAsync( + waitingEvent, + OutboxConfig + ); await Outbox.DeleteAsync(waitingEvent.Id); - Logger.LogInformation($"Sent the event to the message broker with id = {waitingEvent.Id:N}"); } } diff --git a/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs b/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs index 3ffe3bb880..b747a858d2 100644 --- a/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs +++ b/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs @@ -201,32 +201,33 @@ namespace Volo.Abp.EventBus.Kafka unitOfWork.AddOrReplaceDistributedEvent(eventRecord); } - public override Task PublishRawAsync( - Guid eventId, - string eventName, - byte[] eventData) + public override Task PublishFromOutboxAsync( + OutgoingEventInfo outgoingEvent, + OutboxConfig outboxConfig) { return PublishAsync( AbpKafkaEventBusOptions.TopicName, - eventName, - eventData, + outgoingEvent.EventName, + outgoingEvent.EventData, new Headers { - { "messageId", System.Text.Encoding.UTF8.GetBytes(eventId.ToString("N")) } + { "messageId", System.Text.Encoding.UTF8.GetBytes(outgoingEvent.Id.ToString("N")) } }, null ); } - public override async Task ProcessRawAsync(InboxConfig inboxConfig, string eventName, byte[] eventDataBytes) + public override async Task ProcessFromInboxAsync( + IncomingEventInfo incomingEvent, + InboxConfig inboxConfig) { - var eventType = EventTypes.GetOrDefault(eventName); + var eventType = EventTypes.GetOrDefault(incomingEvent.EventName); if (eventType == null) { return; } - var eventData = Serializer.Deserialize(eventDataBytes, eventType); + var eventData = Serializer.Deserialize(incomingEvent.EventData, eventType); var exceptions = new List(); await TriggerHandlersAsync(eventType, eventData, exceptions, inboxConfig); if (exceptions.Any()) diff --git a/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs b/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs index deb20b5ff3..12eec80ce7 100644 --- a/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs +++ b/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs @@ -212,22 +212,26 @@ namespace Volo.Abp.EventBus.RabbitMq unitOfWork.AddOrReplaceDistributedEvent(eventRecord); } - public override Task PublishRawAsync(Guid eventId, string eventName, byte[] eventData) + public override Task PublishFromOutboxAsync( + OutgoingEventInfo outgoingEvent, + OutboxConfig outboxConfig) { - return PublishAsync(eventName, eventData, null, eventId: eventId); + return PublishAsync(outgoingEvent.EventName, outgoingEvent.EventData, null, eventId: outgoingEvent.Id); } - public override async Task ProcessRawAsync(InboxConfig inboxConfig, string eventName, byte[] eventDataBytes) + public override async Task ProcessFromInboxAsync( + IncomingEventInfo incomingEvent, + InboxConfig inboxConfig) { //TODO: We have a duplication in logic and also with the kafka side! - var eventType = EventTypes.GetOrDefault(eventName); + var eventType = EventTypes.GetOrDefault(incomingEvent.EventName); if (eventType == null) { return; } - var eventData = Serializer.Deserialize(eventDataBytes, eventType); + var eventData = Serializer.Deserialize(incomingEvent.EventData, eventType); var exceptions = new List(); await TriggerHandlersAsync(eventType, eventData, exceptions, inboxConfig); if (exceptions.Any()) diff --git a/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventBus.cs b/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventBus.cs index af3d148ecf..8dac885036 100644 --- a/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventBus.cs +++ b/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventBus.cs @@ -188,13 +188,17 @@ namespace Volo.Abp.EventBus.Rebus return false; } - public override Task PublishRawAsync(Guid eventId, string eventName, byte[] eventData) + public override Task PublishFromOutboxAsync( + OutgoingEventInfo outgoingEvent, + OutboxConfig outboxConfig) { /* TODO: IMPLEMENT! */ throw new NotImplementedException(); } - public override Task ProcessRawAsync(InboxConfig inboxConfig, string eventName, byte[] eventDataBytes) + public override Task ProcessFromInboxAsync( + IncomingEventInfo incomingEvent, + InboxConfig inboxConfig) { /* TODO: IMPLEMENT! */ throw new NotImplementedException(); diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs index 1fdaf0d26f..70c5bd5533 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs @@ -10,7 +10,7 @@ using Volo.Abp.Uow; namespace Volo.Abp.EventBus.Distributed { - public abstract class DistributedEventBusBase : EventBusBase, IDistributedEventBus, IRawEventPublisher + public abstract class DistributedEventBusBase : EventBusBase, IDistributedEventBus, ISupportsEventBoxes { protected IGuidGenerator GuidGenerator { get; } protected IClock Clock { get; } @@ -80,8 +80,14 @@ namespace Volo.Abp.EventBus.Distributed await PublishToEventBusAsync(eventType, eventData); } - public abstract Task PublishRawAsync(Guid eventId, string eventName, byte[] eventData); - public abstract Task ProcessRawAsync(InboxConfig inboxConfig, string eventName, byte[] eventDataBytes); + public abstract Task PublishFromOutboxAsync( + OutgoingEventInfo outgoingEvent, + OutboxConfig outboxConfig + ); + + public abstract Task ProcessFromInboxAsync( + IncomingEventInfo incomingEvent, + InboxConfig inboxConfig); private async Task AddToOutboxAsync(Type eventType, object eventData) { diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IRawEventPublisher.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IRawEventPublisher.cs deleted file mode 100644 index 4505239ade..0000000000 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IRawEventPublisher.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.Threading.Tasks; - -namespace Volo.Abp.EventBus.Distributed -{ - public interface IRawEventPublisher //TODO: Rename: ISupportsEventBoxes - { - Task PublishRawAsync( - Guid eventId, - string eventName, - byte[] eventData); - - Task ProcessRawAsync( - InboxConfig inboxConfig, - string eventName, - byte[] eventDataBytes); - } -} \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/ISupportsEventBoxes.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/ISupportsEventBoxes.cs new file mode 100644 index 0000000000..7a13696bc0 --- /dev/null +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/ISupportsEventBoxes.cs @@ -0,0 +1,17 @@ +using System.Threading.Tasks; + +namespace Volo.Abp.EventBus.Distributed +{ + public interface ISupportsEventBoxes + { + Task PublishFromOutboxAsync( + OutgoingEventInfo outgoingEvent, + OutboxConfig outboxConfig + ); + + Task ProcessFromInboxAsync( + IncomingEventInfo incomingEvent, + InboxConfig inboxConfig + ); + } +} \ No newline at end of file From 8200298f5dc35177ff3fe9d226f84e87b7d68afa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 15 Sep 2021 09:56:34 +0300 Subject: [PATCH 24/36] Remove unnecessary log --- .../Volo/Abp/EventBus/Boxes/InboxProcessor.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/InboxProcessor.cs b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/InboxProcessor.cs index 7f238728f7..e711e5798e 100644 --- a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/InboxProcessor.cs +++ b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/InboxProcessor.cs @@ -84,8 +84,6 @@ namespace Volo.Abp.EventBus.Boxes { if (handle != null) { - Logger.LogDebug("Obtained the distributed lock: " + DistributedLockName); - await DeleteOldEventsAsync(); while (true) From 8859803254ed40af878903d090762d0041495734 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 15 Sep 2021 10:00:04 +0300 Subject: [PATCH 25/36] Remove old TODOs --- .../Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs b/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs index 12eec80ce7..ceba890234 100644 --- a/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs +++ b/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs @@ -20,8 +20,6 @@ using Volo.Abp.Uow; namespace Volo.Abp.EventBus.RabbitMq { /* TODO: How to handle unsubscribe to unbind on RabbitMq (may not be possible for) - * TODO: Implement Retry system - * TODO: Should be improved */ [Dependency(ReplaceServices = true)] [ExposeServices(typeof(IDistributedEventBus), typeof(RabbitMqDistributedEventBus))] @@ -223,8 +221,6 @@ namespace Volo.Abp.EventBus.RabbitMq IncomingEventInfo incomingEvent, InboxConfig inboxConfig) { - //TODO: We have a duplication in logic and also with the kafka side! - var eventType = EventTypes.GetOrDefault(incomingEvent.EventName); if (eventType == null) { From cc14ae65594abb28b69c8341a14be4abfd2d4c9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 15 Sep 2021 10:11:54 +0300 Subject: [PATCH 26/36] Define index for the creationtime. --- .../EventOutboxDbContextModelBuilderExtensions.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/EventOutboxDbContextModelBuilderExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/EventOutboxDbContextModelBuilderExtensions.cs index 5443968343..a8236ac43a 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/EventOutboxDbContextModelBuilderExtensions.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/EventOutboxDbContextModelBuilderExtensions.cs @@ -15,6 +15,8 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents b.ConfigureByConvention(); b.Property(x => x.EventName).IsRequired().HasMaxLength(OutgoingEventRecord.MaxEventNameLength); b.Property(x => x.EventData).IsRequired(); + + b.HasIndex(x => x.CreationTime); }); } } From fc70729d5423e887c2fd43372ffd7d4f2a7851f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 15 Sep 2021 13:12:57 +0300 Subject: [PATCH 27/36] Rename local variable: rawPublisher to supportsEventBoxes. --- .../Abp/EventBus/Boxes/AbpDistributedEventBusExtensions.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/AbpDistributedEventBusExtensions.cs b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/AbpDistributedEventBusExtensions.cs index ed652f677f..a943f6faa7 100644 --- a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/AbpDistributedEventBusExtensions.cs +++ b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/AbpDistributedEventBusExtensions.cs @@ -6,13 +6,13 @@ namespace Volo.Abp.EventBus.Boxes { public static ISupportsEventBoxes AsSupportsEventBoxes(this IDistributedEventBus eventBus) { - var rawPublisher = eventBus as ISupportsEventBoxes; - if (rawPublisher == null) + var supportsEventBoxes = eventBus as ISupportsEventBoxes; + if (supportsEventBoxes == null) { throw new AbpException($"Given type ({eventBus.GetType().AssemblyQualifiedName}) should implement {nameof(ISupportsEventBoxes)}!"); } - return rawPublisher; + return supportsEventBoxes; } } } \ No newline at end of file From 9ecea2d83ab51972a3a7ce0cc0ee10f6d573d689 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Tue, 28 Sep 2021 08:59:23 +0300 Subject: [PATCH 28/36] Update TodoEventHandler.cs --- test/DistEvents/DistDemoApp.Shared/TodoEventHandler.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/DistEvents/DistDemoApp.Shared/TodoEventHandler.cs b/test/DistEvents/DistDemoApp.Shared/TodoEventHandler.cs index c7fd43aea3..7a69ceed1e 100644 --- a/test/DistEvents/DistDemoApp.Shared/TodoEventHandler.cs +++ b/test/DistEvents/DistDemoApp.Shared/TodoEventHandler.cs @@ -41,8 +41,6 @@ namespace DistDemoApp } Console.WriteLine("Increased total count: " + todoSummary); - - //throw new ApplicationException("Thrown to rollback the UOW!"); } public async Task HandleEventAsync(EntityDeletedEto eventData) From 0cf5d248fdf36b29cdd74bf62446a1f5e60368f0 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Tue, 28 Sep 2021 15:59:22 +0800 Subject: [PATCH 29/36] Complete the Outbox & Inbox Patterns feature --- .../DistributedEvents/DbContextEventInbox.cs | 19 +++--- .../DistributedEvents/DbContextEventOutbox.cs | 15 ++--- .../EventBus/Boxes/AbpEventBusBoxesOptions.cs | 43 +++++++++++++ .../Volo/Abp/EventBus/Boxes/InboxProcessor.cs | 16 +++-- .../Volo/Abp/EventBus/Boxes/OutboxSender.cs | 16 +++-- ...bitMqSerializer.cs => IRebusSerializer.cs} | 0 .../Rebus/RebusDistributedEventBus.cs | 37 +++++++++-- .../RebusDistributedEventHandlerAdapter.cs | 2 +- .../AbpDistributedEventBusOptions.cs | 13 +++- .../Abp/EventBus/Distributed/IEventInbox.cs | 11 ++-- .../Abp/EventBus/Distributed/IEventOutbox.cs | 9 +-- .../MongoDbContextEventInbox.cs | 60 +++++++++++++----- .../MongoDbContextEventOutbox.cs | 61 ++++++++++++++++--- .../appsettings.json | 2 +- .../DistDemoApp.MongoDbKafka.csproj | 12 ++++ .../DistDemoAppMongoDbKafkaModule.cs | 38 ++++++++++++ .../DistDemoApp.MongoDbKafka/Program.cs | 53 ++++++++++++++-- .../TodoMongoDbContext.cs | 26 ++++++++ .../DistDemoApp.MongoDbKafka/appsettings.json | 19 ++++++ .../DistDemoApp.MongoDbRebus.csproj | 21 +++++++ .../DistDemoAppMongoDbRebusModule.cs | 53 ++++++++++++++++ .../DistDemoApp.MongoDbRebus/Program.cs | 57 +++++++++++++++++ .../TodoMongoDbContext.cs | 26 ++++++++ .../DistDemoApp.MongoDbRebus/appsettings.json | 19 ++++++ test/DistEvents/DistEventsDemo.sln | 6 ++ 25 files changed, 563 insertions(+), 71 deletions(-) create mode 100644 framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/AbpEventBusBoxesOptions.cs rename framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/{IRabbitMqSerializer.cs => IRebusSerializer.cs} (100%) create mode 100644 test/DistEvents/DistDemoApp.MongoDbKafka/DistDemoAppMongoDbKafkaModule.cs create mode 100644 test/DistEvents/DistDemoApp.MongoDbKafka/TodoMongoDbContext.cs create mode 100644 test/DistEvents/DistDemoApp.MongoDbKafka/appsettings.json create mode 100644 test/DistEvents/DistDemoApp.MongoDbRebus/DistDemoApp.MongoDbRebus.csproj create mode 100644 test/DistEvents/DistDemoApp.MongoDbRebus/DistDemoAppMongoDbRebusModule.cs create mode 100644 test/DistEvents/DistDemoApp.MongoDbRebus/Program.cs create mode 100644 test/DistEvents/DistDemoApp.MongoDbRebus/TodoMongoDbContext.cs create mode 100644 test/DistEvents/DistDemoApp.MongoDbRebus/appsettings.json diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventInbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventInbox.cs index 2b0a448f74..86fc78cab3 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventInbox.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventInbox.cs @@ -1,26 +1,31 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Options; using Volo.Abp.EventBus.Distributed; using Volo.Abp.Timing; using Volo.Abp.Uow; namespace Volo.Abp.EntityFrameworkCore.DistributedEvents { - public class DbContextEventInbox : IDbContextEventInbox + public class DbContextEventInbox : IDbContextEventInbox where TDbContext : IHasEventInbox { protected IDbContextProvider DbContextProvider { get; } + protected AbpDistributedEventBusOptions DistributedEventsOptions { get; } protected IClock Clock { get; } public DbContextEventInbox( IDbContextProvider dbContextProvider, - IClock clock) + IClock clock, + IOptions distributedEventsOptions) { DbContextProvider = dbContextProvider; Clock = clock; + DistributedEventsOptions = distributedEventsOptions.Value; } [UnitOfWork] @@ -34,7 +39,7 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents } [UnitOfWork] - public virtual async Task> GetWaitingEventsAsync(int maxCount) + public virtual async Task> GetWaitingEventsAsync(int maxCount, CancellationToken cancellationToken = default) { var dbContext = await DbContextProvider.GetDbContextAsync(); @@ -44,8 +49,8 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents .Where(x => !x.Processed) .OrderBy(x => x.CreationTime) .Take(maxCount) - .ToListAsync(); - + .ToListAsync(cancellationToken: cancellationToken); + return outgoingEventRecords .Select(x => x.ToIncomingEventInfo()) .ToList(); @@ -76,11 +81,11 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents { //TODO: Optimize var dbContext = await DbContextProvider.GetDbContextAsync(); - var timeToKeepEvents = Clock.Now.AddHours(-2); //TODO: Config? + var timeToKeepEvents = Clock.Now.Add(DistributedEventsOptions.InboxKeepEventTimeSpan); var oldEvents = await dbContext.IncomingEvents .Where(x => x.Processed && x.CreationTime < timeToKeepEvents) .ToListAsync(); dbContext.IncomingEvents.RemoveRange(oldEvents); } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventOutbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventOutbox.cs index a785ad7ce5..435bc70398 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventOutbox.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventOutbox.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Volo.Abp.EventBus.Distributed; @@ -8,7 +9,7 @@ using Volo.Abp.Uow; namespace Volo.Abp.EntityFrameworkCore.DistributedEvents { - public class DbContextEventOutbox : IDbContextEventOutbox + public class DbContextEventOutbox : IDbContextEventOutbox where TDbContext : IHasEventOutbox { protected IDbContextProvider DbContextProvider { get; } @@ -18,7 +19,7 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents { DbContextProvider = dbContextProvider; } - + [UnitOfWork] public virtual async Task EnqueueAsync(OutgoingEventInfo outgoingEvent) { @@ -29,17 +30,17 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents } [UnitOfWork] - public virtual async Task> GetWaitingEventsAsync(int maxCount) + public virtual async Task> GetWaitingEventsAsync(int maxCount, CancellationToken cancellationToken = default) { var dbContext = (IHasEventOutbox) await DbContextProvider.GetDbContextAsync(); - + var outgoingEventRecords = await dbContext .OutgoingEvents .AsNoTracking() .OrderBy(x => x.CreationTime) .Take(maxCount) - .ToListAsync(); - + .ToListAsync(cancellationToken: cancellationToken); + return outgoingEventRecords .Select(x => x.ToOutgoingEventInfo()) .ToList(); @@ -57,4 +58,4 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents } } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/AbpEventBusBoxesOptions.cs b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/AbpEventBusBoxesOptions.cs new file mode 100644 index 0000000000..da91d672d3 --- /dev/null +++ b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/AbpEventBusBoxesOptions.cs @@ -0,0 +1,43 @@ +using System; + +namespace Volo.Abp.EventBus.Boxes +{ + public class AbpEventBusBoxesOptions + { + /// + /// Default: 6 hours + /// + public TimeSpan CleanOldEventTimeIntervalSpan { get; set; } + + /// + /// Default: 1000 + /// + public int InboxWaitingEventMaxCount { get; set; } + + /// + /// Default: 1000 + /// + public int OutboxWaitingEventMaxCount { get; set; } + + /// + /// Period time of and + /// Default: 2 seconds + /// + public TimeSpan PeriodTimeSpan { get; set; } + + /// + /// Delay time of and + /// Default: 15 seconds + /// + public TimeSpan DelayTimeSpan { get; set; } + + public AbpEventBusBoxesOptions() + { + CleanOldEventTimeIntervalSpan = TimeSpan.FromHours(6); + InboxWaitingEventMaxCount = 1000; + OutboxWaitingEventMaxCount = 1000; + PeriodTimeSpan = TimeSpan.FromSeconds(2); + DelayTimeSpan = TimeSpan.FromSeconds(15); + } + } +} diff --git a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/InboxProcessor.cs b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/InboxProcessor.cs index e711e5798e..29cca3d624 100644 --- a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/InboxProcessor.cs +++ b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/InboxProcessor.cs @@ -5,6 +5,7 @@ using Medallion.Threading; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus.Distributed; using Volo.Abp.Threading; @@ -23,6 +24,7 @@ namespace Volo.Abp.EventBus.Boxes protected IClock Clock { get; } protected IEventInbox Inbox { get; private set; } protected InboxConfig InboxConfig { get; private set; } + protected AbpEventBusBoxesOptions EventBusBoxesOptions { get; } protected DateTime? LastCleanTime { get; set; } @@ -37,7 +39,8 @@ namespace Volo.Abp.EventBus.Boxes IDistributedEventBus distributedEventBus, IDistributedLockProvider distributedLockProvider, IUnitOfWorkManager unitOfWorkManager, - IClock clock) + IClock clock, + IOptions eventBusBoxesOptions) { ServiceProvider = serviceProvider; Timer = timer; @@ -45,7 +48,8 @@ namespace Volo.Abp.EventBus.Boxes DistributedLockProvider = distributedLockProvider; UnitOfWorkManager = unitOfWorkManager; Clock = clock; - Timer.Period = 2000; //TODO: Config? + EventBusBoxesOptions = eventBusBoxesOptions.Value; + Timer.Period = EventBusBoxesOptions.PeriodTimeSpan.Seconds; Timer.Elapsed += TimerOnElapsed; Logger = NullLogger.Instance; StoppingTokenSource = new CancellationTokenSource(); @@ -79,7 +83,7 @@ namespace Volo.Abp.EventBus.Boxes { return; } - + await using (var handle = await DistributedLockProvider.TryAcquireLockAsync(DistributedLockName, cancellationToken: StoppingToken)) { if (handle != null) @@ -88,7 +92,7 @@ namespace Volo.Abp.EventBus.Boxes while (true) { - var waitingEvents = await Inbox.GetWaitingEventsAsync(1000); //TODO: Config? Pass StoppingToken! + var waitingEvents = await Inbox.GetWaitingEventsAsync(EventBusBoxesOptions.InboxWaitingEventMaxCount, StoppingToken); if (waitingEvents.Count <= 0) { break; @@ -116,14 +120,14 @@ namespace Volo.Abp.EventBus.Boxes else { Logger.LogDebug("Could not obtain the distributed lock: " + DistributedLockName); - await TaskDelayHelper.DelayAsync(15000, StoppingToken); //TODO: Config? + await TaskDelayHelper.DelayAsync(EventBusBoxesOptions.DelayTimeSpan.Milliseconds, StoppingToken); } } } protected virtual async Task DeleteOldEventsAsync() { - if (LastCleanTime != null && LastCleanTime > Clock.Now.AddHours(6)) //TODO: Config? + if (LastCleanTime != null && LastCleanTime > Clock.Now.Add(EventBusBoxesOptions.CleanOldEventTimeIntervalSpan)) { return; } diff --git a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs index 1be2374268..e8a05c60ba 100644 --- a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs +++ b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs @@ -5,6 +5,7 @@ using Medallion.Threading; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus.Distributed; using Volo.Abp.Threading; @@ -19,9 +20,10 @@ namespace Volo.Abp.EventBus.Boxes protected IDistributedLockProvider DistributedLockProvider { get; } protected IEventOutbox Outbox { get; private set; } protected OutboxConfig OutboxConfig { get; private set; } + protected AbpEventBusBoxesOptions EventBusBoxesOptions { get; } protected string DistributedLockName => "Outbox_" + OutboxConfig.Name; public ILogger Logger { get; set; } - + protected CancellationTokenSource StoppingTokenSource { get; } protected CancellationToken StoppingToken { get; } @@ -29,13 +31,15 @@ namespace Volo.Abp.EventBus.Boxes IServiceProvider serviceProvider, AbpAsyncTimer timer, IDistributedEventBus distributedEventBus, - IDistributedLockProvider distributedLockProvider) + IDistributedLockProvider distributedLockProvider, + IOptions eventBusBoxesOptions) { ServiceProvider = serviceProvider; Timer = timer; DistributedEventBus = distributedEventBus; DistributedLockProvider = distributedLockProvider; - Timer.Period = 2000; //TODO: Config? + EventBusBoxesOptions = eventBusBoxesOptions.Value; + Timer.Period = EventBusBoxesOptions.PeriodTimeSpan.Seconds; Timer.Elapsed += TimerOnElapsed; Logger = NullLogger.Instance; StoppingTokenSource = new CancellationTokenSource(); @@ -65,13 +69,13 @@ namespace Volo.Abp.EventBus.Boxes protected virtual async Task RunAsync() { - await using (var handle = await DistributedLockProvider.TryAcquireLockAsync(DistributedLockName)) + await using (var handle = await DistributedLockProvider.TryAcquireLockAsync(DistributedLockName, cancellationToken: StoppingToken)) { if (handle != null) { while (true) { - var waitingEvents = await Outbox.GetWaitingEventsAsync(1000); //TODO: Config? + var waitingEvents = await Outbox.GetWaitingEventsAsync(EventBusBoxesOptions.OutboxWaitingEventMaxCount, StoppingToken); if (waitingEvents.Count <= 0) { break; @@ -96,7 +100,7 @@ namespace Volo.Abp.EventBus.Boxes else { Logger.LogDebug("Could not obtain the distributed lock: " + DistributedLockName); - await TaskDelayHelper.DelayAsync(15000, StoppingToken); //TODO: Config? + await TaskDelayHelper.DelayAsync(EventBusBoxesOptions.DelayTimeSpan.Milliseconds, StoppingToken); } } } diff --git a/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/IRabbitMqSerializer.cs b/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/IRebusSerializer.cs similarity index 100% rename from framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/IRabbitMqSerializer.cs rename to framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/IRebusSerializer.cs diff --git a/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventBus.cs b/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventBus.cs index 8dac885036..1cb380679f 100644 --- a/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventBus.cs +++ b/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventBus.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Rebus.Bus; +using Rebus.Pipeline; using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus.Distributed; using Volo.Abp.Guids; @@ -134,6 +135,19 @@ namespace Volo.Abp.EventBus.Rebus Rebus.Unsubscribe(eventType); } + public async Task ProcessEventAsync(Type eventType, object eventData) + { + var messageId = MessageContext.Current.TransportMessage.GetMessageId(); + var eventName = EventNameAttribute.GetNameOrDefault(eventType); + + if (await AddToInboxAsync(messageId, eventName, eventType, MessageContext.Current.TransportMessage.Body)) + { + return; + } + + await TriggerHandlersAsync(eventType, eventData); + } + protected override async Task PublishToEventBusAsync(Type eventType, object eventData) { await AbpRebusEventBusOptions.Publish(Rebus, eventType, eventData); @@ -192,16 +206,29 @@ namespace Volo.Abp.EventBus.Rebus OutgoingEventInfo outgoingEvent, OutboxConfig outboxConfig) { - /* TODO: IMPLEMENT! */ - throw new NotImplementedException(); + var eventType = EventTypes.GetOrDefault(outgoingEvent.EventName); + var eventData = Serializer.Deserialize(outgoingEvent.EventData, eventType); + + return PublishToEventBusAsync(eventType, eventData); } - public override Task ProcessFromInboxAsync( + public override async Task ProcessFromInboxAsync( IncomingEventInfo incomingEvent, InboxConfig inboxConfig) { - /* TODO: IMPLEMENT! */ - throw new NotImplementedException(); + var eventType = EventTypes.GetOrDefault(incomingEvent.EventName); + if (eventType == null) + { + return; + } + + var eventData = Serializer.Deserialize(incomingEvent.EventData, eventType); + var exceptions = new List(); + await TriggerHandlersAsync(eventType, eventData, exceptions, inboxConfig); + if (exceptions.Any()) + { + ThrowOriginalExceptions(eventType, exceptions); + } } protected override byte[] Serialize(object eventData) diff --git a/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventHandlerAdapter.cs b/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventHandlerAdapter.cs index 005226b885..61330828b4 100644 --- a/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventHandlerAdapter.cs +++ b/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventHandlerAdapter.cs @@ -14,7 +14,7 @@ namespace Volo.Abp.EventBus.Rebus public async Task Handle(TEventData message) { - await RebusDistributedEventBus.TriggerHandlersAsync(typeof(TEventData), message); + await RebusDistributedEventBus.ProcessEventAsync(message.GetType(), message); } } } diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/AbpDistributedEventBusOptions.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/AbpDistributedEventBusOptions.cs index 896dfd4f7d..5b71542665 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/AbpDistributedEventBusOptions.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/AbpDistributedEventBusOptions.cs @@ -1,3 +1,4 @@ +using System; using Volo.Abp.Collections; namespace Volo.Abp.EventBus.Distributed @@ -5,16 +6,22 @@ namespace Volo.Abp.EventBus.Distributed public class AbpDistributedEventBusOptions { public ITypeList Handlers { get; } - + public OutboxConfigDictionary Outboxes { get; } - + public InboxConfigDictionary Inboxes { get; } + /// + /// Default: -2 hours + /// + public TimeSpan InboxKeepEventTimeSpan { get; set; } + public AbpDistributedEventBusOptions() { Handlers = new TypeList(); Outboxes = new OutboxConfigDictionary(); Inboxes = new InboxConfigDictionary(); + InboxKeepEventTimeSpan = TimeSpan.FromHours(-2); } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IEventInbox.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IEventInbox.cs index bee802a126..d072f5d922 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IEventInbox.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IEventInbox.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Threading; using System.Threading.Tasks; namespace Volo.Abp.EventBus.Distributed @@ -7,13 +8,13 @@ namespace Volo.Abp.EventBus.Distributed public interface IEventInbox { Task EnqueueAsync(IncomingEventInfo incomingEvent); - - Task> GetWaitingEventsAsync(int maxCount); - + + Task> GetWaitingEventsAsync(int maxCount, CancellationToken cancellationToken = default); + Task MarkAsProcessedAsync(Guid id); - + Task ExistsByMessageIdAsync(string messageId); Task DeleteOldEventsAsync(); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IEventOutbox.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IEventOutbox.cs index 0b50993e8e..cc00ee6654 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IEventOutbox.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IEventOutbox.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Threading; using System.Threading.Tasks; namespace Volo.Abp.EventBus.Distributed @@ -7,9 +8,9 @@ namespace Volo.Abp.EventBus.Distributed public interface IEventOutbox { Task EnqueueAsync(OutgoingEventInfo outgoingEvent); - - Task> GetWaitingEventsAsync(int maxCount); - + + Task> GetWaitingEventsAsync(int maxCount, CancellationToken cancellationToken = default); + Task DeleteAsync(Guid id); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventInbox.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventInbox.cs index d98e144ada..886a7744d1 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventInbox.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventInbox.cs @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.Options; using MongoDB.Driver; using MongoDB.Driver.Linq; using Volo.Abp.EventBus.Distributed; @@ -10,21 +12,24 @@ using Volo.Abp.Uow; namespace Volo.Abp.MongoDB.DistributedEvents { - public class MongoDbContextEventInbox : IMongoDbContextEventInbox + public class MongoDbContextEventInbox : IMongoDbContextEventInbox where TMongoDbContext : IHasEventInbox { protected IMongoDbContextProvider DbContextProvider { get; } + protected AbpDistributedEventBusOptions DistributedEventsOptions { get; } protected IClock Clock { get; } - + public MongoDbContextEventInbox( IMongoDbContextProvider dbContextProvider, - IClock clock) + IClock clock, + IOptions distributedEventsOptions) { DbContextProvider = dbContextProvider; Clock = clock; + DistributedEventsOptions = distributedEventsOptions.Value; } - + [UnitOfWork] public virtual async Task EnqueueAsync(IncomingEventInfo incomingEvent) { @@ -45,9 +50,9 @@ namespace Volo.Abp.MongoDB.DistributedEvents } [UnitOfWork] - public virtual async Task> GetWaitingEventsAsync(int maxCount) + public virtual async Task> GetWaitingEventsAsync(int maxCount, CancellationToken cancellationToken = default) { - var dbContext = await DbContextProvider.GetDbContextAsync(); + var dbContext = await DbContextProvider.GetDbContextAsync(cancellationToken); var outgoingEventRecords = await dbContext .IncomingEvents @@ -55,8 +60,8 @@ namespace Volo.Abp.MongoDB.DistributedEvents .Where(x => !x.Processed) .OrderBy(x => x.CreationTime) .Take(maxCount) - .ToListAsync(); - + .ToListAsync(cancellationToken: cancellationToken); + return outgoingEventRecords .Select(x => x.ToIncomingEventInfo()) .ToList(); @@ -65,17 +70,44 @@ namespace Volo.Abp.MongoDB.DistributedEvents [UnitOfWork] public async Task MarkAsProcessedAsync(Guid id) { - throw new NotImplementedException(); + var dbContext = await DbContextProvider.GetDbContextAsync(); + var incomingEvent = await dbContext.IncomingEvents.Find(x => x.Id.Equals(id)).FirstOrDefaultAsync(); + if (incomingEvent != null) + { + incomingEvent.MarkAsProcessed(Clock.Now); + + if (dbContext.SessionHandle != null) + { + await dbContext.IncomingEvents.ReplaceOneAsync(dbContext.SessionHandle, Builders.Filter.Eq(e => e.Id, incomingEvent.Id), incomingEvent); + } + else + { + await dbContext.IncomingEvents.ReplaceOneAsync(Builders.Filter.Eq(e => e.Id, incomingEvent.Id), incomingEvent); + } + } } - public Task ExistsByMessageIdAsync(string messageId) + [UnitOfWork] + public async Task ExistsByMessageIdAsync(string messageId) { - throw new NotImplementedException(); + var dbContext = await DbContextProvider.GetDbContextAsync(); + return await dbContext.IncomingEvents.AsQueryable().AnyAsync(x => x.MessageId == messageId); } - public Task DeleteOldEventsAsync() + [UnitOfWork] + public async Task DeleteOldEventsAsync() { - throw new NotImplementedException(); + var dbContext = await DbContextProvider.GetDbContextAsync(); + var timeToKeepEvents = Clock.Now.Add(DistributedEventsOptions.InboxKeepEventTimeSpan); + + if (dbContext.SessionHandle != null) + { + await dbContext.IncomingEvents.DeleteManyAsync(dbContext.SessionHandle, x => x.Processed && x.CreationTime < timeToKeepEvents); + } + else + { + await dbContext.IncomingEvents.DeleteManyAsync(x => x.Processed && x.CreationTime < timeToKeepEvents); + } } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventOutbox.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventOutbox.cs index 1bec9e0834..df8aa108ee 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventOutbox.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventOutbox.cs @@ -1,27 +1,72 @@ using System; using System.Collections.Generic; +using System.Linq; +using System.Threading; using System.Threading.Tasks; +using MongoDB.Driver; +using MongoDB.Driver.Linq; using Volo.Abp.EventBus.Distributed; using Volo.Abp.Uow; namespace Volo.Abp.MongoDB.DistributedEvents { - public class MongoDbContextEventOutbox : IMongoDbContextEventOutbox + public class MongoDbContextEventOutbox : IMongoDbContextEventOutbox where TMongoDbContext : IHasEventOutbox { - public Task EnqueueAsync(OutgoingEventInfo outgoingEvent) + protected IMongoDbContextProvider MongoDbContextProvider { get; } + + public MongoDbContextEventOutbox(IMongoDbContextProvider mongoDbContextProvider) + { + MongoDbContextProvider = mongoDbContextProvider; + } + + [UnitOfWork] + public async Task EnqueueAsync(OutgoingEventInfo outgoingEvent) { - throw new NotImplementedException(); + var dbContext = (IHasEventOutbox) await MongoDbContextProvider.GetDbContextAsync(); + if (dbContext.SessionHandle != null) + { + await dbContext.OutgoingEvents.InsertOneAsync( + dbContext.SessionHandle, + new OutgoingEventRecord(outgoingEvent) + ); + } + else + { + await dbContext.OutgoingEvents.InsertOneAsync( + new OutgoingEventRecord(outgoingEvent) + ); + } } - public Task> GetWaitingEventsAsync(int maxCount) + [UnitOfWork] + public async Task> GetWaitingEventsAsync(int maxCount, CancellationToken cancellationToken = default) { - throw new NotImplementedException(); + var dbContext = (IHasEventOutbox) await MongoDbContextProvider.GetDbContextAsync(cancellationToken); + + var outgoingEventRecords = await dbContext + .OutgoingEvents.AsQueryable() + .OrderBy(x => x.CreationTime) + .Take(maxCount) + .ToListAsync(cancellationToken: cancellationToken); + + return outgoingEventRecords + .Select(x => x.ToOutgoingEventInfo()) + .ToList(); } - public Task DeleteAsync(Guid id) + [UnitOfWork] + public async Task DeleteAsync(Guid id) { - throw new NotImplementedException(); + var dbContext = (IHasEventOutbox) await MongoDbContextProvider.GetDbContextAsync(); + if (dbContext.SessionHandle != null) + { + await dbContext.OutgoingEvents.DeleteOneAsync(dbContext.SessionHandle, x => x.Id.Equals(id)); + } + else + { + await dbContext.OutgoingEvents.DeleteOneAsync(x => x.Id.Equals(id)); + } } } -} \ No newline at end of file +} diff --git a/test/DistEvents/DistDemoApp.EfCoreRabbitMq/appsettings.json b/test/DistEvents/DistDemoApp.EfCoreRabbitMq/appsettings.json index 1ed30c80a9..5359c021b7 100644 --- a/test/DistEvents/DistDemoApp.EfCoreRabbitMq/appsettings.json +++ b/test/DistEvents/DistDemoApp.EfCoreRabbitMq/appsettings.json @@ -16,4 +16,4 @@ "Redis": { "Configuration": "127.0.0.1" } -} \ No newline at end of file +} diff --git a/test/DistEvents/DistDemoApp.MongoDbKafka/DistDemoApp.MongoDbKafka.csproj b/test/DistEvents/DistDemoApp.MongoDbKafka/DistDemoApp.MongoDbKafka.csproj index cfd73d51bb..a503c6f6c0 100644 --- a/test/DistEvents/DistDemoApp.MongoDbKafka/DistDemoApp.MongoDbKafka.csproj +++ b/test/DistEvents/DistDemoApp.MongoDbKafka/DistDemoApp.MongoDbKafka.csproj @@ -6,4 +6,16 @@ DistDemoApp + + + + + + + + + Always + + + diff --git a/test/DistEvents/DistDemoApp.MongoDbKafka/DistDemoAppMongoDbKafkaModule.cs b/test/DistEvents/DistDemoApp.MongoDbKafka/DistDemoAppMongoDbKafkaModule.cs new file mode 100644 index 0000000000..b2e41b6ca7 --- /dev/null +++ b/test/DistEvents/DistDemoApp.MongoDbKafka/DistDemoAppMongoDbKafkaModule.cs @@ -0,0 +1,38 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.EventBus.Kafka; +using Volo.Abp.Modularity; +using Volo.Abp.MongoDB; +using Volo.Abp.MongoDB.DistributedEvents; + +namespace DistDemoApp +{ + [DependsOn( + typeof(AbpMongoDbModule), + typeof(AbpEventBusKafkaModule), + typeof(DistDemoAppSharedModule) + )] + public class DistDemoAppMongoDbKafkaModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddMongoDbContext(options => + { + options.AddDefaultRepositories(); + }); + + Configure(options => + { + options.Outboxes.Configure(config => + { + config.UseMongoDbContext(); + }); + + options.Inboxes.Configure(config => + { + config.UseMongoDbContext(); + }); + }); + } + } +} diff --git a/test/DistEvents/DistDemoApp.MongoDbKafka/Program.cs b/test/DistEvents/DistDemoApp.MongoDbKafka/Program.cs index d0e4cdf4ca..b048c17389 100644 --- a/test/DistEvents/DistDemoApp.MongoDbKafka/Program.cs +++ b/test/DistEvents/DistDemoApp.MongoDbKafka/Program.cs @@ -1,12 +1,57 @@ using System; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Serilog; +using Serilog.Events; namespace DistDemoApp { - class Program + public class Program { - static void Main(string[] args) + public static async Task Main(string[] args) { - Console.WriteLine("Hello World!"); + Log.Logger = new LoggerConfiguration() +#if DEBUG + .MinimumLevel.Debug() +#else + .MinimumLevel.Information() +#endif + .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) + .Enrich.FromLogContext() + .WriteTo.Async(c => c.File("Logs/logs.txt")) + .WriteTo.Async(c => c.Console()) + .CreateLogger(); + + try + { + Log.Information("Starting console host."); + await CreateHostBuilder(args).RunConsoleAsync(); + return 0; + } + catch (Exception ex) + { + Log.Fatal(ex, "Host terminated unexpectedly!"); + return 1; + } + finally + { + Log.CloseAndFlush(); + } + } + + internal static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .UseAutofac() + .UseSerilog() + .ConfigureAppConfiguration((context, config) => + { + //setup your additional configuration sources + }) + .ConfigureServices((hostContext, services) => + { + services.AddApplication(); + }); } -} \ No newline at end of file +} diff --git a/test/DistEvents/DistDemoApp.MongoDbKafka/TodoMongoDbContext.cs b/test/DistEvents/DistDemoApp.MongoDbKafka/TodoMongoDbContext.cs new file mode 100644 index 0000000000..a7f1b78f86 --- /dev/null +++ b/test/DistEvents/DistDemoApp.MongoDbKafka/TodoMongoDbContext.cs @@ -0,0 +1,26 @@ +using MongoDB.Driver; +using Volo.Abp.Data; +using Volo.Abp.MongoDB; +using Volo.Abp.MongoDB.DistributedEvents; + +namespace DistDemoApp +{ + [ConnectionStringName("Default")] + public class TodoMongoDbContext : AbpMongoDbContext, IHasEventOutbox, IHasEventInbox + { + public IMongoCollection TodoItems => Collection(); + public IMongoCollection TodoSummaries => Collection(); + + public IMongoCollection OutgoingEvents + { + get => Collection(); + set {} + } + public IMongoCollection IncomingEvents + { + get => Collection(); + set {} + } + } + +} diff --git a/test/DistEvents/DistDemoApp.MongoDbKafka/appsettings.json b/test/DistEvents/DistDemoApp.MongoDbKafka/appsettings.json new file mode 100644 index 0000000000..d8c528fe87 --- /dev/null +++ b/test/DistEvents/DistDemoApp.MongoDbKafka/appsettings.json @@ -0,0 +1,19 @@ +{ + "ConnectionStrings": { + "Default": "mongodb://localhost:27018,localhost:27019,localhost:27020/DistEventsDemo" + }, + "Kafka": { + "Connections": { + "Default": { + "BootstrapServers": "localhost:9092" + } + }, + "EventBus": { + "GroupId": "DistDemoApp", + "TopicName": "DistDemoTopic" + } + }, + "Redis": { + "Configuration": "127.0.0.1" + } +} diff --git a/test/DistEvents/DistDemoApp.MongoDbRebus/DistDemoApp.MongoDbRebus.csproj b/test/DistEvents/DistDemoApp.MongoDbRebus/DistDemoApp.MongoDbRebus.csproj new file mode 100644 index 0000000000..c102adb382 --- /dev/null +++ b/test/DistEvents/DistDemoApp.MongoDbRebus/DistDemoApp.MongoDbRebus.csproj @@ -0,0 +1,21 @@ + + + + Exe + net5.0 + DistDemoApp + + + + + + + + + + + Always + + + + diff --git a/test/DistEvents/DistDemoApp.MongoDbRebus/DistDemoAppMongoDbRebusModule.cs b/test/DistEvents/DistDemoApp.MongoDbRebus/DistDemoAppMongoDbRebusModule.cs new file mode 100644 index 0000000000..21dab7b9b5 --- /dev/null +++ b/test/DistEvents/DistDemoApp.MongoDbRebus/DistDemoAppMongoDbRebusModule.cs @@ -0,0 +1,53 @@ +using Microsoft.Extensions.DependencyInjection; +using Rebus.Persistence.InMem; +using Rebus.Transport.InMem; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.EventBus.Rebus; +using Volo.Abp.Modularity; +using Volo.Abp.MongoDB; +using Volo.Abp.MongoDB.DistributedEvents; + +namespace DistDemoApp +{ + [DependsOn( + typeof(AbpMongoDbModule), + typeof(AbpEventBusRebusModule), + typeof(DistDemoAppSharedModule) + )] + public class DistDemoAppMongoDbRebusModule : AbpModule + { + public override void PreConfigureServices(ServiceConfigurationContext context) + { + PreConfigure(options => + { + options.InputQueueName = "eventbus"; + options.Configurer = rebusConfigurer => + { + rebusConfigurer.Transport(t => t.UseInMemoryTransport(new InMemNetwork(), "eventbus")); + rebusConfigurer.Subscriptions(s => s.StoreInMemory()); + }; + }); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddMongoDbContext(options => + { + options.AddDefaultRepositories(); + }); + + Configure(options => + { + options.Outboxes.Configure(config => + { + config.UseMongoDbContext(); + }); + + options.Inboxes.Configure(config => + { + config.UseMongoDbContext(); + }); + }); + } + } +} diff --git a/test/DistEvents/DistDemoApp.MongoDbRebus/Program.cs b/test/DistEvents/DistDemoApp.MongoDbRebus/Program.cs new file mode 100644 index 0000000000..a79ad1b1bf --- /dev/null +++ b/test/DistEvents/DistDemoApp.MongoDbRebus/Program.cs @@ -0,0 +1,57 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Serilog; +using Serilog.Events; + +namespace DistDemoApp +{ + public class Program + { + public static async Task Main(string[] args) + { + Log.Logger = new LoggerConfiguration() +#if DEBUG + .MinimumLevel.Debug() +#else + .MinimumLevel.Information() +#endif + .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) + .Enrich.FromLogContext() + .WriteTo.Async(c => c.File("Logs/logs.txt")) + .WriteTo.Async(c => c.Console()) + .CreateLogger(); + + try + { + Log.Information("Starting console host."); + await CreateHostBuilder(args).RunConsoleAsync(); + return 0; + } + catch (Exception ex) + { + Log.Fatal(ex, "Host terminated unexpectedly!"); + return 1; + } + finally + { + Log.CloseAndFlush(); + } + + } + + internal static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .UseAutofac() + .UseSerilog() + .ConfigureAppConfiguration((context, config) => + { + //setup your additional configuration sources + }) + .ConfigureServices((hostContext, services) => + { + services.AddApplication(); + }); + } +} diff --git a/test/DistEvents/DistDemoApp.MongoDbRebus/TodoMongoDbContext.cs b/test/DistEvents/DistDemoApp.MongoDbRebus/TodoMongoDbContext.cs new file mode 100644 index 0000000000..a7f1b78f86 --- /dev/null +++ b/test/DistEvents/DistDemoApp.MongoDbRebus/TodoMongoDbContext.cs @@ -0,0 +1,26 @@ +using MongoDB.Driver; +using Volo.Abp.Data; +using Volo.Abp.MongoDB; +using Volo.Abp.MongoDB.DistributedEvents; + +namespace DistDemoApp +{ + [ConnectionStringName("Default")] + public class TodoMongoDbContext : AbpMongoDbContext, IHasEventOutbox, IHasEventInbox + { + public IMongoCollection TodoItems => Collection(); + public IMongoCollection TodoSummaries => Collection(); + + public IMongoCollection OutgoingEvents + { + get => Collection(); + set {} + } + public IMongoCollection IncomingEvents + { + get => Collection(); + set {} + } + } + +} diff --git a/test/DistEvents/DistDemoApp.MongoDbRebus/appsettings.json b/test/DistEvents/DistDemoApp.MongoDbRebus/appsettings.json new file mode 100644 index 0000000000..d8c528fe87 --- /dev/null +++ b/test/DistEvents/DistDemoApp.MongoDbRebus/appsettings.json @@ -0,0 +1,19 @@ +{ + "ConnectionStrings": { + "Default": "mongodb://localhost:27018,localhost:27019,localhost:27020/DistEventsDemo" + }, + "Kafka": { + "Connections": { + "Default": { + "BootstrapServers": "localhost:9092" + } + }, + "EventBus": { + "GroupId": "DistDemoApp", + "TopicName": "DistDemoTopic" + } + }, + "Redis": { + "Configuration": "127.0.0.1" + } +} diff --git a/test/DistEvents/DistEventsDemo.sln b/test/DistEvents/DistEventsDemo.sln index 4e53ba6367..e6c3348a5f 100644 --- a/test/DistEvents/DistEventsDemo.sln +++ b/test/DistEvents/DistEventsDemo.sln @@ -6,6 +6,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DistDemoApp.MongoDbKafka", EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DistDemoApp.Shared", "DistDemoApp.Shared\DistDemoApp.Shared.csproj", "{C515F4E2-0ED3-4561-BC58-FC633B50E2EB}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DistDemoApp.MongoDbRebus", "DistDemoApp.MongoDbRebus\DistDemoApp.MongoDbRebus.csproj", "{4FB63540-4CC5-4A7B-900B-F5FCD907456E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -24,5 +26,9 @@ Global {C515F4E2-0ED3-4561-BC58-FC633B50E2EB}.Debug|Any CPU.Build.0 = Debug|Any CPU {C515F4E2-0ED3-4561-BC58-FC633B50E2EB}.Release|Any CPU.ActiveCfg = Release|Any CPU {C515F4E2-0ED3-4561-BC58-FC633B50E2EB}.Release|Any CPU.Build.0 = Release|Any CPU + {4FB63540-4CC5-4A7B-900B-F5FCD907456E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4FB63540-4CC5-4A7B-900B-F5FCD907456E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4FB63540-4CC5-4A7B-900B-F5FCD907456E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4FB63540-4CC5-4A7B-900B-F5FCD907456E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal From f0f61884b76a1c6d3e44c194912bf8e052a1be15 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Tue, 28 Sep 2021 23:43:48 +0800 Subject: [PATCH 30/36] Improve performance --- .../DistributedEvents/DbContextEventInbox.cs | 26 ++++++++--------- .../DistributedEvents/DbContextEventOutbox.cs | 10 +++---- .../MongoDbContextEventInbox.cs | 28 +++++++++---------- .../MongoDbContextEventOutbox.cs | 6 ++-- 4 files changed, 31 insertions(+), 39 deletions(-) diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventInbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventInbox.cs index 86fc78cab3..5bee24d754 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventInbox.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventInbox.cs @@ -57,35 +57,31 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents } [UnitOfWork] - public async Task MarkAsProcessedAsync(Guid id) + public virtual async Task MarkAsProcessedAsync(Guid id) { - //TODO: Optimize? var dbContext = await DbContextProvider.GetDbContextAsync(); - var incomingEvent = await dbContext.IncomingEvents.FindAsync(id); - if (incomingEvent != null) - { - incomingEvent.MarkAsProcessed(Clock.Now); - } + var tableName = dbContext.IncomingEvents.EntityType.GetSchemaQualifiedTableName(); + + var sql = $"UPDATE {tableName} SET Processed = 1, ProcessedTime = '{Clock.Now}' WHERE Id = '{id}'"; + await dbContext.Database.ExecuteSqlRawAsync(sql); } [UnitOfWork] - public async Task ExistsByMessageIdAsync(string messageId) + public virtual async Task ExistsByMessageIdAsync(string messageId) { - //TODO: Optimize var dbContext = await DbContextProvider.GetDbContextAsync(); return await dbContext.IncomingEvents.AnyAsync(x => x.MessageId == messageId); } [UnitOfWork] - public async Task DeleteOldEventsAsync() + public virtual async Task DeleteOldEventsAsync() { - //TODO: Optimize var dbContext = await DbContextProvider.GetDbContextAsync(); + var tableName = dbContext.IncomingEvents.EntityType.GetSchemaQualifiedTableName(); var timeToKeepEvents = Clock.Now.Add(DistributedEventsOptions.InboxKeepEventTimeSpan); - var oldEvents = await dbContext.IncomingEvents - .Where(x => x.Processed && x.CreationTime < timeToKeepEvents) - .ToListAsync(); - dbContext.IncomingEvents.RemoveRange(oldEvents); + + var sql = $"DELETE FROM {tableName} WHERE Processed = 1 AND CreationTime < '{timeToKeepEvents}'"; + await dbContext.Database.ExecuteSqlRawAsync(sql); } } } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventOutbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventOutbox.cs index 435bc70398..f0b4d3b98c 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventOutbox.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventOutbox.cs @@ -49,13 +49,11 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents [UnitOfWork] public virtual async Task DeleteAsync(Guid id) { - //TODO: Optimize? var dbContext = (IHasEventOutbox) await DbContextProvider.GetDbContextAsync(); - var outgoingEvent = await dbContext.OutgoingEvents.FindAsync(id); - if (outgoingEvent != null) - { - dbContext.Remove(outgoingEvent); - } + var tableName = dbContext.OutgoingEvents.EntityType.GetSchemaQualifiedTableName(); + + var sql = $"DELETE FROM {tableName} WHERE Id = '{id}'"; + await dbContext.Database.ExecuteSqlRawAsync(sql); } } } diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventInbox.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventInbox.cs index 886a7744d1..62927d2279 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventInbox.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventInbox.cs @@ -68,34 +68,32 @@ namespace Volo.Abp.MongoDB.DistributedEvents } [UnitOfWork] - public async Task MarkAsProcessedAsync(Guid id) + public virtual async Task MarkAsProcessedAsync(Guid id) { var dbContext = await DbContextProvider.GetDbContextAsync(); - var incomingEvent = await dbContext.IncomingEvents.Find(x => x.Id.Equals(id)).FirstOrDefaultAsync(); - if (incomingEvent != null) - { - incomingEvent.MarkAsProcessed(Clock.Now); - if (dbContext.SessionHandle != null) - { - await dbContext.IncomingEvents.ReplaceOneAsync(dbContext.SessionHandle, Builders.Filter.Eq(e => e.Id, incomingEvent.Id), incomingEvent); - } - else - { - await dbContext.IncomingEvents.ReplaceOneAsync(Builders.Filter.Eq(e => e.Id, incomingEvent.Id), incomingEvent); - } + var filter = Builders.Filter.Eq(x => x.Id, id); + var update = Builders.Update.Set(x => x.Processed, true).Set(x => x.ProcessedTime, Clock.Now); + + if (dbContext.SessionHandle != null) + { + await dbContext.IncomingEvents.UpdateOneAsync(dbContext.SessionHandle, filter, update); + } + else + { + await dbContext.IncomingEvents.UpdateOneAsync(filter, update); } } [UnitOfWork] - public async Task ExistsByMessageIdAsync(string messageId) + public virtual async Task ExistsByMessageIdAsync(string messageId) { var dbContext = await DbContextProvider.GetDbContextAsync(); return await dbContext.IncomingEvents.AsQueryable().AnyAsync(x => x.MessageId == messageId); } [UnitOfWork] - public async Task DeleteOldEventsAsync() + public virtual async Task DeleteOldEventsAsync() { var dbContext = await DbContextProvider.GetDbContextAsync(); var timeToKeepEvents = Clock.Now.Add(DistributedEventsOptions.InboxKeepEventTimeSpan); diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventOutbox.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventOutbox.cs index df8aa108ee..dad0294d1c 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventOutbox.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventOutbox.cs @@ -21,7 +21,7 @@ namespace Volo.Abp.MongoDB.DistributedEvents } [UnitOfWork] - public async Task EnqueueAsync(OutgoingEventInfo outgoingEvent) + public virtual async Task EnqueueAsync(OutgoingEventInfo outgoingEvent) { var dbContext = (IHasEventOutbox) await MongoDbContextProvider.GetDbContextAsync(); if (dbContext.SessionHandle != null) @@ -40,7 +40,7 @@ namespace Volo.Abp.MongoDB.DistributedEvents } [UnitOfWork] - public async Task> GetWaitingEventsAsync(int maxCount, CancellationToken cancellationToken = default) + public virtual async Task> GetWaitingEventsAsync(int maxCount, CancellationToken cancellationToken = default) { var dbContext = (IHasEventOutbox) await MongoDbContextProvider.GetDbContextAsync(cancellationToken); @@ -56,7 +56,7 @@ namespace Volo.Abp.MongoDB.DistributedEvents } [UnitOfWork] - public async Task DeleteAsync(Guid id) + public virtual async Task DeleteAsync(Guid id) { var dbContext = (IHasEventOutbox) await MongoDbContextProvider.GetDbContextAsync(); if (dbContext.SessionHandle != null) From bc4944c19d3612a6087bbdb8e901fb584f3a9e43 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Wed, 29 Sep 2021 17:06:59 +0800 Subject: [PATCH 31/36] Add ISqlAdapter --- .../DistributedEvents/PostgreSqlAdapter.cs | 25 +++++++++++++++++ .../AbpEntityFrameworkCorePostgreSqlModule.cs | 9 ++++++- .../AbpEntityFrameworkCoreModule.cs | 5 ++++ .../AbpEfCoreDistributedEventBusOptions.cs | 19 +++++++++++++ .../DistributedEvents/DbContextEventInbox.cs | 20 +++++++++++--- .../DistributedEvents/DbContextEventOutbox.cs | 12 +++++++-- .../DistributedEvents/DefaultSqlAdapter.cs | 27 +++++++++++++++++++ .../DistributedEvents/ISqlAdapter.cs | 13 +++++++++ 8 files changed, 124 insertions(+), 6 deletions(-) create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/PostgreSqlAdapter.cs create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/AbpEfCoreDistributedEventBusOptions.cs create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DefaultSqlAdapter.cs create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/ISqlAdapter.cs diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/PostgreSqlAdapter.cs b/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/PostgreSqlAdapter.cs new file mode 100644 index 0000000000..0c84ec929e --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/PostgreSqlAdapter.cs @@ -0,0 +1,25 @@ +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public class PostgreSqlAdapter : ISqlAdapter + { + public string NormalizeTableName(string tableName) + { + return $"\"{tableName}\""; + } + + public string NormalizeColumnName(string columnName) + { + return $"\"{columnName}\""; + } + + public string NormalizeColumnNameEqualsValue(string columnName, object value) + { + return $"\"{columnName}\" = '{value}'"; + } + + public string NormalizeValue(object value) + { + return $"'{value}'"; + } + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/PostgreSql/AbpEntityFrameworkCorePostgreSqlModule.cs b/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/PostgreSql/AbpEntityFrameworkCorePostgreSqlModule.cs index 4e76b89113..7d8c87c63a 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/PostgreSql/AbpEntityFrameworkCorePostgreSqlModule.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/PostgreSql/AbpEntityFrameworkCorePostgreSqlModule.cs @@ -1,4 +1,6 @@ -using Volo.Abp.Guids; +using Npgsql; +using Volo.Abp.EntityFrameworkCore.DistributedEvents; +using Volo.Abp.Guids; using Volo.Abp.Modularity; namespace Volo.Abp.EntityFrameworkCore.PostgreSql @@ -17,6 +19,11 @@ namespace Volo.Abp.EntityFrameworkCore.PostgreSql options.DefaultSequentialGuidType = SequentialGuidType.SequentialAsString; } }); + + Configure(options => + { + options.SqlAdapters.TryAdd(nameof(NpgsqlConnection).ToLower(), new PostgreSqlAdapter()); + }); } } } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreModule.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreModule.cs index 90b541bc73..349116d6eb 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreModule.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreModule.cs @@ -26,6 +26,11 @@ namespace Volo.Abp.EntityFrameworkCore }); }); + Configure(options => + { + options.SqlAdapters.Add(DefaultSqlAdapter.Name, new DefaultSqlAdapter()); + }); + context.Services.TryAddTransient(typeof(IDbContextProvider<>), typeof(UnitOfWorkDbContextProvider<>)); context.Services.AddTransient(typeof(IDbContextEventOutbox<>), typeof(DbContextEventOutbox<>)); context.Services.AddTransient(typeof(IDbContextEventInbox<>), typeof(DbContextEventInbox<>)); diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/AbpEfCoreDistributedEventBusOptions.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/AbpEfCoreDistributedEventBusOptions.cs new file mode 100644 index 0000000000..9497552a09 --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/AbpEfCoreDistributedEventBusOptions.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; + +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public class AbpEfCoreDistributedEventBusOptions + { + public Dictionary SqlAdapters { get; set; } + + public ISqlAdapter GetSqlAdapter(string connectionType) + { + return SqlAdapters.TryGetValue(connectionType, out var sqlAdapter) ? sqlAdapter : SqlAdapters[DefaultSqlAdapter.Name]; + } + + public AbpEfCoreDistributedEventBusOptions() + { + SqlAdapters = new Dictionary(); + } + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventInbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventInbox.cs index 5bee24d754..d8f18c6f32 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventInbox.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventInbox.cs @@ -16,15 +16,18 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents { protected IDbContextProvider DbContextProvider { get; } protected AbpDistributedEventBusOptions DistributedEventsOptions { get; } + protected AbpEfCoreDistributedEventBusOptions EfCoreDistributedEventBusOptions { get; } protected IClock Clock { get; } public DbContextEventInbox( IDbContextProvider dbContextProvider, IClock clock, - IOptions distributedEventsOptions) + IOptions distributedEventsOptions, + IOptions efCoreDistributedEventBusOptions) { DbContextProvider = dbContextProvider; Clock = clock; + EfCoreDistributedEventBusOptions = efCoreDistributedEventBusOptions.Value; DistributedEventsOptions = distributedEventsOptions.Value; } @@ -61,8 +64,14 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents { var dbContext = await DbContextProvider.GetDbContextAsync(); var tableName = dbContext.IncomingEvents.EntityType.GetSchemaQualifiedTableName(); + var connectionName = dbContext.Database.GetDbConnection().GetType().Name.ToLower(); + var sqlAdapter = EfCoreDistributedEventBusOptions.GetSqlAdapter(connectionName); + + var sql = $"UPDATE {sqlAdapter.NormalizeTableName(tableName)} SET " + + $"{sqlAdapter.NormalizeColumnNameEqualsValue("Processed", 1)}, " + + $"{sqlAdapter.NormalizeColumnNameEqualsValue("ProcessedTime", Clock.Now)} WHERE " + + $"{sqlAdapter.NormalizeColumnNameEqualsValue("Id", id)}"; - var sql = $"UPDATE {tableName} SET Processed = 1, ProcessedTime = '{Clock.Now}' WHERE Id = '{id}'"; await dbContext.Database.ExecuteSqlRawAsync(sql); } @@ -79,8 +88,13 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents var dbContext = await DbContextProvider.GetDbContextAsync(); var tableName = dbContext.IncomingEvents.EntityType.GetSchemaQualifiedTableName(); var timeToKeepEvents = Clock.Now.Add(DistributedEventsOptions.InboxKeepEventTimeSpan); + var connectionName = dbContext.Database.GetDbConnection().GetType().Name.ToLower(); + var sqlAdapter = EfCoreDistributedEventBusOptions.GetSqlAdapter(connectionName); + + var sql = $"DELETE FROM {sqlAdapter.NormalizeTableName(tableName)} WHERE " + + $"{sqlAdapter.NormalizeColumnNameEqualsValue("Processed", 1)} AND " + + $"{sqlAdapter.NormalizeColumnName("CreationTime")} < {sqlAdapter.NormalizeValue(timeToKeepEvents)}"; - var sql = $"DELETE FROM {tableName} WHERE Processed = 1 AND CreationTime < '{timeToKeepEvents}'"; await dbContext.Database.ExecuteSqlRawAsync(sql); } } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventOutbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventOutbox.cs index f0b4d3b98c..5451a0a30a 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventOutbox.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventOutbox.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Options; using Volo.Abp.EventBus.Distributed; using Volo.Abp.Uow; @@ -13,11 +14,14 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents where TDbContext : IHasEventOutbox { protected IDbContextProvider DbContextProvider { get; } + protected AbpEfCoreDistributedEventBusOptions EfCoreDistributedEventBusOptions { get; } public DbContextEventOutbox( - IDbContextProvider dbContextProvider) + IDbContextProvider dbContextProvider, + IOptions efCoreDistributedEventBusOptions) { DbContextProvider = dbContextProvider; + EfCoreDistributedEventBusOptions = efCoreDistributedEventBusOptions.Value; } [UnitOfWork] @@ -51,8 +55,12 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents { var dbContext = (IHasEventOutbox) await DbContextProvider.GetDbContextAsync(); var tableName = dbContext.OutgoingEvents.EntityType.GetSchemaQualifiedTableName(); + var connectionName = dbContext.Database.GetDbConnection().GetType().Name.ToLower(); + var sqlAdapter = EfCoreDistributedEventBusOptions.GetSqlAdapter(connectionName); + + var sql = $"DELETE FROM {sqlAdapter.NormalizeTableName(tableName)} WHERE " + + $"{sqlAdapter.NormalizeColumnNameEqualsValue("Id", id)}"; - var sql = $"DELETE FROM {tableName} WHERE Id = '{id}'"; await dbContext.Database.ExecuteSqlRawAsync(sql); } } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DefaultSqlAdapter.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DefaultSqlAdapter.cs new file mode 100644 index 0000000000..8a86af7434 --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DefaultSqlAdapter.cs @@ -0,0 +1,27 @@ +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public class DefaultSqlAdapter : ISqlAdapter + { + public const string Name = "default"; + + public string NormalizeTableName(string tableName) + { + return tableName; + } + + public string NormalizeColumnName(string columnName) + { + return columnName; + } + + public string NormalizeColumnNameEqualsValue(string columnName, object value) + { + return $"{columnName} = '{value}'"; + } + + public string NormalizeValue(object value) + { + return $"'{value}'"; + } + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/ISqlAdapter.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/ISqlAdapter.cs new file mode 100644 index 0000000000..9b366f00ab --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/ISqlAdapter.cs @@ -0,0 +1,13 @@ +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public interface ISqlAdapter + { + string NormalizeTableName(string tableName); + + string NormalizeColumnName(string columnName); + + string NormalizeColumnNameEqualsValue(string columnName, object value); + + string NormalizeValue(object value); + } +} From b809ee50e329d341f64f271c3d0eb05568d56379 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Thu, 30 Sep 2021 00:01:57 +0800 Subject: [PATCH 32/36] Refactor --- .../MySQLInboxConfigExtensions.cs | 13 +++++ .../MySQLOutboxConfigExtensions.cs | 13 +++++ .../IOracleDbContextEventInbox.cs | 8 ++++ .../IOracleDbContextEventOutbox.cs | 7 +++ .../OracleDbContextEventInbox.cs | 47 +++++++++++++++++++ .../OracleDbContextEventOutbox.cs | 31 ++++++++++++ .../OracleInboxConfigExtensions.cs | 13 +++++ .../OracleOutboxConfigExtensions.cs | 13 +++++ ...bpEntityFrameworkCoreOracleDevartModule.cs | 7 ++- .../IOracleDbContextEventInbox.cs | 8 ++++ .../IOracleDbContextEventOutbox.cs | 7 +++ .../OracleDbContextEventInbox.cs | 47 +++++++++++++++++++ .../OracleDbContextEventOutbox.cs | 31 ++++++++++++ .../OracleInboxConfigExtensions.cs | 13 +++++ .../OracleOutboxConfigExtensions.cs | 13 +++++ .../AbpEntityFrameworkCoreOracleModule.cs | 7 ++- .../IPostgreSqlDbContextEventInbox.cs | 8 ++++ .../IPostgreSqlDbContextEventOutbox.cs | 7 +++ .../DistributedEvents/PostgreSqlAdapter.cs | 25 ---------- .../PostgreSqlDbContextEventInbox.cs | 43 +++++++++++++++++ .../PostgreSqlDbContextEventOutbox.cs | 25 ++++++++++ .../PostgreSqlInboxConfigExtensions.cs | 13 +++++ .../PostgreSqlOutboxConfigExtensions.cs | 13 +++++ .../AbpEntityFrameworkCorePostgreSqlModule.cs | 8 ++-- .../SqlServerInboxConfigExtensions.cs | 13 +++++ .../SqlServerOutboxConfigExtensions.cs | 13 +++++ .../SqliteInboxConfigExtensions.cs | 13 +++++ .../SqliteOutboxConfigExtensions.cs | 13 +++++ .../AbpEntityFrameworkCoreModule.cs | 9 ++-- .../AbpEfCoreDistributedEventBusOptions.cs | 19 -------- .../DistributedEvents/DbContextEventInbox.cs | 33 ++++--------- .../DistributedEvents/DbContextEventOutbox.cs | 19 +++----- .../DistributedEvents/DefaultSqlAdapter.cs | 27 ----------- .../DistributedEvents/ISqlAdapter.cs | 13 ----- .../ISqlRawDbContextEventInbox.cs | 7 +++ .../ISqlRawDbContextEventOutbox.cs | 7 +++ .../SqlRawDbContextEventInbox.cs | 43 +++++++++++++++++ .../SqlRawDbContextEventOutbox.cs | 26 ++++++++++ 38 files changed, 543 insertions(+), 132 deletions(-) create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore.MySQL/Volo/Abp/EntityFrameworkCore/DistributedEvents/MySQLInboxConfigExtensions.cs create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore.MySQL/Volo/Abp/EntityFrameworkCore/DistributedEvents/MySQLOutboxConfigExtensions.cs create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/DistributedEvents/IOracleDbContextEventInbox.cs create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/DistributedEvents/IOracleDbContextEventOutbox.cs create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleDbContextEventInbox.cs create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleDbContextEventOutbox.cs create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleInboxConfigExtensions.cs create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleOutboxConfigExtensions.cs create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore.Oracle/Volo/Abp/EntityFrameworkCore/DistributedEvents/IOracleDbContextEventInbox.cs create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore.Oracle/Volo/Abp/EntityFrameworkCore/DistributedEvents/IOracleDbContextEventOutbox.cs create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore.Oracle/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleDbContextEventInbox.cs create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore.Oracle/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleDbContextEventOutbox.cs create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore.Oracle/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleInboxConfigExtensions.cs create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore.Oracle/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleOutboxConfigExtensions.cs create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/IPostgreSqlDbContextEventInbox.cs create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/IPostgreSqlDbContextEventOutbox.cs delete mode 100644 framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/PostgreSqlAdapter.cs create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/PostgreSqlDbContextEventInbox.cs create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/PostgreSqlDbContextEventOutbox.cs create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/PostgreSqlInboxConfigExtensions.cs create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/PostgreSqlOutboxConfigExtensions.cs create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore.SqlServer/Volo/Abp/EntityFrameworkCore/DistributedEvents/SqlServerInboxConfigExtensions.cs create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore.SqlServer/Volo/Abp/EntityFrameworkCore/DistributedEvents/SqlServerOutboxConfigExtensions.cs create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore.Sqlite/Volo/Abp/EntityFrameworkCore/DistributedEvents/SqliteInboxConfigExtensions.cs create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore.Sqlite/Volo/Abp/EntityFrameworkCore/DistributedEvents/SqliteOutboxConfigExtensions.cs delete mode 100644 framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/AbpEfCoreDistributedEventBusOptions.cs delete mode 100644 framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DefaultSqlAdapter.cs delete mode 100644 framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/ISqlAdapter.cs create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/ISqlRawDbContextEventInbox.cs create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/ISqlRawDbContextEventOutbox.cs create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/SqlRawDbContextEventInbox.cs create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/SqlRawDbContextEventOutbox.cs diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.MySQL/Volo/Abp/EntityFrameworkCore/DistributedEvents/MySQLInboxConfigExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore.MySQL/Volo/Abp/EntityFrameworkCore/DistributedEvents/MySQLInboxConfigExtensions.cs new file mode 100644 index 0000000000..ecda92702b --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore.MySQL/Volo/Abp/EntityFrameworkCore/DistributedEvents/MySQLInboxConfigExtensions.cs @@ -0,0 +1,13 @@ +using Volo.Abp.EventBus.Distributed; + +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public static class MySQLInboxConfigExtensions + { + public static void UseMySQL(this InboxConfig outboxConfig) + where TDbContext : IHasEventInbox + { + outboxConfig.ImplementationType = typeof(ISqlRawDbContextEventInbox); + } + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.MySQL/Volo/Abp/EntityFrameworkCore/DistributedEvents/MySQLOutboxConfigExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore.MySQL/Volo/Abp/EntityFrameworkCore/DistributedEvents/MySQLOutboxConfigExtensions.cs new file mode 100644 index 0000000000..8657ba92ab --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore.MySQL/Volo/Abp/EntityFrameworkCore/DistributedEvents/MySQLOutboxConfigExtensions.cs @@ -0,0 +1,13 @@ +using Volo.Abp.EventBus.Distributed; + +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public static class MySQLOutboxConfigExtensions + { + public static void UseMySQL(this OutboxConfig outboxConfig) + where TDbContext : IHasEventOutbox + { + outboxConfig.ImplementationType = typeof(ISqlRawDbContextEventOutbox); + } + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/DistributedEvents/IOracleDbContextEventInbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/DistributedEvents/IOracleDbContextEventInbox.cs new file mode 100644 index 0000000000..0cc7ae5531 --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/DistributedEvents/IOracleDbContextEventInbox.cs @@ -0,0 +1,8 @@ +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public interface IOracleDbContextEventInbox : IDbContextEventInbox + where TDbContext : IHasEventInbox + { + + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/DistributedEvents/IOracleDbContextEventOutbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/DistributedEvents/IOracleDbContextEventOutbox.cs new file mode 100644 index 0000000000..a588f36e43 --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/DistributedEvents/IOracleDbContextEventOutbox.cs @@ -0,0 +1,7 @@ +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public interface IOracleDbContextEventOutbox : IDbContextEventOutbox + where TDbContext : IHasEventOutbox + { + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleDbContextEventInbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleDbContextEventInbox.cs new file mode 100644 index 0000000000..d5f1b7afcc --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleDbContextEventInbox.cs @@ -0,0 +1,47 @@ +using System; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Options; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.Timing; +using Volo.Abp.Uow; + +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public class OracleDbContextEventInbox : DbContextEventInbox , IOracleDbContextEventInbox + where TDbContext : IHasEventInbox + { + public OracleDbContextEventInbox( + IDbContextProvider dbContextProvider, + IClock clock, + IOptions distributedEventsOptions) : base(dbContextProvider, clock, distributedEventsOptions) + { + } + + [UnitOfWork] + public override async Task MarkAsProcessedAsync(Guid id) + { + var dbContext = await DbContextProvider.GetDbContextAsync(); + var tableName = dbContext.IncomingEvents.EntityType.GetSchemaQualifiedTableName(); + + var sql = $"UPDATE \"{tableName}\" SET \"Processed\" = '1', \"ProcessedTime\" = TO_DATE('{Clock.Now}', 'yyyy-mm-dd hh24:mi:ss') WHERE \"Id\" = HEXTORAW('{GuidToOracleType(id)}')"; + await dbContext.Database.ExecuteSqlRawAsync(sql); + } + + [UnitOfWork] + public override async Task DeleteOldEventsAsync() + { + var dbContext = await DbContextProvider.GetDbContextAsync(); + var tableName = dbContext.IncomingEvents.EntityType.GetSchemaQualifiedTableName(); + var timeToKeepEvents = Clock.Now.Add(DistributedEventsOptions.InboxKeepEventTimeSpan); + + var sql = $"DELETE FROM \"{tableName}\" WHERE \"Processed\" = '1' AND \"CreationTime\" < TO_DATE('{timeToKeepEvents}', 'yyyy-mm-dd hh24:mi:ss')"; + await dbContext.Database.ExecuteSqlRawAsync(sql); + } + + protected virtual string GuidToOracleType(Guid id) + { + return BitConverter.ToString(id.ToByteArray()).Replace("-", "").ToUpper(); + } + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleDbContextEventOutbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleDbContextEventOutbox.cs new file mode 100644 index 0000000000..a5c4566ced --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleDbContextEventOutbox.cs @@ -0,0 +1,31 @@ +using System; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Volo.Abp.Uow; + +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public class OracleDbContextEventOutbox : DbContextEventOutbox , IOracleDbContextEventOutbox + where TDbContext : IHasEventOutbox + { + public OracleDbContextEventOutbox(IDbContextProvider dbContextProvider) + : base(dbContextProvider) + { + } + + [UnitOfWork] + public override async Task DeleteAsync(Guid id) + { + var dbContext = (IHasEventOutbox) await DbContextProvider.GetDbContextAsync(); + var tableName = dbContext.OutgoingEvents.EntityType.GetSchemaQualifiedTableName(); + + var sql = $"DELETE FROM \"{tableName}\" WHERE \"Id\" = HEXTORAW('{GuidToOracleType(id)}')"; + await dbContext.Database.ExecuteSqlRawAsync(sql); + } + + protected virtual string GuidToOracleType(Guid id) + { + return BitConverter.ToString(id.ToByteArray()).Replace("-", "").ToUpper(); + } + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleInboxConfigExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleInboxConfigExtensions.cs new file mode 100644 index 0000000000..ca79019e28 --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleInboxConfigExtensions.cs @@ -0,0 +1,13 @@ +using Volo.Abp.EventBus.Distributed; + +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public static class OracleInboxConfigExtensions + { + public static void UseOracle(this InboxConfig outboxConfig) + where TDbContext : IHasEventInbox + { + outboxConfig.ImplementationType = typeof(IOracleDbContextEventInbox); + } + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleOutboxConfigExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleOutboxConfigExtensions.cs new file mode 100644 index 0000000000..e2d7d33761 --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleOutboxConfigExtensions.cs @@ -0,0 +1,13 @@ +using Volo.Abp.EventBus.Distributed; + +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public static class OracleOutboxConfigExtensions + { + public static void UseOracle(this OutboxConfig outboxConfig) + where TDbContext : IHasEventOutbox + { + outboxConfig.ImplementationType = typeof(IOracleDbContextEventOutbox); + } + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/Oracle/Devart/AbpEntityFrameworkCoreOracleDevartModule.cs b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/Oracle/Devart/AbpEntityFrameworkCoreOracleDevartModule.cs index 9580219cfc..76d0ecdd21 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/Oracle/Devart/AbpEntityFrameworkCoreOracleDevartModule.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/Oracle/Devart/AbpEntityFrameworkCoreOracleDevartModule.cs @@ -1,4 +1,6 @@ -using Volo.Abp.Guids; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.EntityFrameworkCore.DistributedEvents; +using Volo.Abp.Guids; using Volo.Abp.Modularity; namespace Volo.Abp.EntityFrameworkCore.Oracle.Devart @@ -17,6 +19,9 @@ namespace Volo.Abp.EntityFrameworkCore.Oracle.Devart options.DefaultSequentialGuidType = SequentialGuidType.SequentialAsBinary; } }); + + context.Services.AddTransient(typeof(IOracleDbContextEventOutbox<>), typeof(OracleDbContextEventOutbox<>)); + context.Services.AddTransient(typeof(IOracleDbContextEventInbox<>), typeof(OracleDbContextEventInbox<>)); } } } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle/Volo/Abp/EntityFrameworkCore/DistributedEvents/IOracleDbContextEventInbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle/Volo/Abp/EntityFrameworkCore/DistributedEvents/IOracleDbContextEventInbox.cs new file mode 100644 index 0000000000..0cc7ae5531 --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle/Volo/Abp/EntityFrameworkCore/DistributedEvents/IOracleDbContextEventInbox.cs @@ -0,0 +1,8 @@ +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public interface IOracleDbContextEventInbox : IDbContextEventInbox + where TDbContext : IHasEventInbox + { + + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle/Volo/Abp/EntityFrameworkCore/DistributedEvents/IOracleDbContextEventOutbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle/Volo/Abp/EntityFrameworkCore/DistributedEvents/IOracleDbContextEventOutbox.cs new file mode 100644 index 0000000000..a588f36e43 --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle/Volo/Abp/EntityFrameworkCore/DistributedEvents/IOracleDbContextEventOutbox.cs @@ -0,0 +1,7 @@ +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public interface IOracleDbContextEventOutbox : IDbContextEventOutbox + where TDbContext : IHasEventOutbox + { + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleDbContextEventInbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleDbContextEventInbox.cs new file mode 100644 index 0000000000..d5f1b7afcc --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleDbContextEventInbox.cs @@ -0,0 +1,47 @@ +using System; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Options; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.Timing; +using Volo.Abp.Uow; + +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public class OracleDbContextEventInbox : DbContextEventInbox , IOracleDbContextEventInbox + where TDbContext : IHasEventInbox + { + public OracleDbContextEventInbox( + IDbContextProvider dbContextProvider, + IClock clock, + IOptions distributedEventsOptions) : base(dbContextProvider, clock, distributedEventsOptions) + { + } + + [UnitOfWork] + public override async Task MarkAsProcessedAsync(Guid id) + { + var dbContext = await DbContextProvider.GetDbContextAsync(); + var tableName = dbContext.IncomingEvents.EntityType.GetSchemaQualifiedTableName(); + + var sql = $"UPDATE \"{tableName}\" SET \"Processed\" = '1', \"ProcessedTime\" = TO_DATE('{Clock.Now}', 'yyyy-mm-dd hh24:mi:ss') WHERE \"Id\" = HEXTORAW('{GuidToOracleType(id)}')"; + await dbContext.Database.ExecuteSqlRawAsync(sql); + } + + [UnitOfWork] + public override async Task DeleteOldEventsAsync() + { + var dbContext = await DbContextProvider.GetDbContextAsync(); + var tableName = dbContext.IncomingEvents.EntityType.GetSchemaQualifiedTableName(); + var timeToKeepEvents = Clock.Now.Add(DistributedEventsOptions.InboxKeepEventTimeSpan); + + var sql = $"DELETE FROM \"{tableName}\" WHERE \"Processed\" = '1' AND \"CreationTime\" < TO_DATE('{timeToKeepEvents}', 'yyyy-mm-dd hh24:mi:ss')"; + await dbContext.Database.ExecuteSqlRawAsync(sql); + } + + protected virtual string GuidToOracleType(Guid id) + { + return BitConverter.ToString(id.ToByteArray()).Replace("-", "").ToUpper(); + } + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleDbContextEventOutbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleDbContextEventOutbox.cs new file mode 100644 index 0000000000..a5c4566ced --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleDbContextEventOutbox.cs @@ -0,0 +1,31 @@ +using System; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Volo.Abp.Uow; + +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public class OracleDbContextEventOutbox : DbContextEventOutbox , IOracleDbContextEventOutbox + where TDbContext : IHasEventOutbox + { + public OracleDbContextEventOutbox(IDbContextProvider dbContextProvider) + : base(dbContextProvider) + { + } + + [UnitOfWork] + public override async Task DeleteAsync(Guid id) + { + var dbContext = (IHasEventOutbox) await DbContextProvider.GetDbContextAsync(); + var tableName = dbContext.OutgoingEvents.EntityType.GetSchemaQualifiedTableName(); + + var sql = $"DELETE FROM \"{tableName}\" WHERE \"Id\" = HEXTORAW('{GuidToOracleType(id)}')"; + await dbContext.Database.ExecuteSqlRawAsync(sql); + } + + protected virtual string GuidToOracleType(Guid id) + { + return BitConverter.ToString(id.ToByteArray()).Replace("-", "").ToUpper(); + } + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleInboxConfigExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleInboxConfigExtensions.cs new file mode 100644 index 0000000000..ca79019e28 --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleInboxConfigExtensions.cs @@ -0,0 +1,13 @@ +using Volo.Abp.EventBus.Distributed; + +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public static class OracleInboxConfigExtensions + { + public static void UseOracle(this InboxConfig outboxConfig) + where TDbContext : IHasEventInbox + { + outboxConfig.ImplementationType = typeof(IOracleDbContextEventInbox); + } + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleOutboxConfigExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleOutboxConfigExtensions.cs new file mode 100644 index 0000000000..e2d7d33761 --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleOutboxConfigExtensions.cs @@ -0,0 +1,13 @@ +using Volo.Abp.EventBus.Distributed; + +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public static class OracleOutboxConfigExtensions + { + public static void UseOracle(this OutboxConfig outboxConfig) + where TDbContext : IHasEventOutbox + { + outboxConfig.ImplementationType = typeof(IOracleDbContextEventOutbox); + } + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle/Volo/Abp/EntityFrameworkCore/Oracle/AbpEntityFrameworkCoreOracleModule.cs b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle/Volo/Abp/EntityFrameworkCore/Oracle/AbpEntityFrameworkCoreOracleModule.cs index b7cbaec1a1..7716ae6150 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle/Volo/Abp/EntityFrameworkCore/Oracle/AbpEntityFrameworkCoreOracleModule.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle/Volo/Abp/EntityFrameworkCore/Oracle/AbpEntityFrameworkCoreOracleModule.cs @@ -1,4 +1,6 @@ -using Volo.Abp.Guids; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.EntityFrameworkCore.DistributedEvents; +using Volo.Abp.Guids; using Volo.Abp.Modularity; namespace Volo.Abp.EntityFrameworkCore.Oracle @@ -15,6 +17,9 @@ namespace Volo.Abp.EntityFrameworkCore.Oracle options.DefaultSequentialGuidType = SequentialGuidType.SequentialAsBinary; } }); + + context.Services.AddTransient(typeof(IOracleDbContextEventOutbox<>), typeof(OracleDbContextEventOutbox<>)); + context.Services.AddTransient(typeof(IOracleDbContextEventInbox<>), typeof(OracleDbContextEventInbox<>)); } } } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/IPostgreSqlDbContextEventInbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/IPostgreSqlDbContextEventInbox.cs new file mode 100644 index 0000000000..5c24d79f88 --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/IPostgreSqlDbContextEventInbox.cs @@ -0,0 +1,8 @@ +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public interface IPostgreSqlDbContextEventInbox : IDbContextEventInbox + where TDbContext : IHasEventInbox + { + + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/IPostgreSqlDbContextEventOutbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/IPostgreSqlDbContextEventOutbox.cs new file mode 100644 index 0000000000..7e6bc4bd59 --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/IPostgreSqlDbContextEventOutbox.cs @@ -0,0 +1,7 @@ +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public interface IPostgreSqlDbContextEventOutbox : IDbContextEventOutbox + where TDbContext : IHasEventOutbox + { + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/PostgreSqlAdapter.cs b/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/PostgreSqlAdapter.cs deleted file mode 100644 index 0c84ec929e..0000000000 --- a/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/PostgreSqlAdapter.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace Volo.Abp.EntityFrameworkCore.DistributedEvents -{ - public class PostgreSqlAdapter : ISqlAdapter - { - public string NormalizeTableName(string tableName) - { - return $"\"{tableName}\""; - } - - public string NormalizeColumnName(string columnName) - { - return $"\"{columnName}\""; - } - - public string NormalizeColumnNameEqualsValue(string columnName, object value) - { - return $"\"{columnName}\" = '{value}'"; - } - - public string NormalizeValue(object value) - { - return $"'{value}'"; - } - } -} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/PostgreSqlDbContextEventInbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/PostgreSqlDbContextEventInbox.cs new file mode 100644 index 0000000000..4560bdb2c4 --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/PostgreSqlDbContextEventInbox.cs @@ -0,0 +1,43 @@ +using System; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Options; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.Timing; +using Volo.Abp.Uow; + +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public class PostgreSqlDbContextEventInbox : DbContextEventInbox, IPostgreSqlDbContextEventInbox + where TDbContext : IHasEventInbox + { + public PostgreSqlDbContextEventInbox( + IDbContextProvider dbContextProvider, + IClock clock, + IOptions distributedEventsOptions) + : base(dbContextProvider, clock, distributedEventsOptions) + { + } + + [UnitOfWork] + public override async Task MarkAsProcessedAsync(Guid id) + { + var dbContext = await DbContextProvider.GetDbContextAsync(); + var tableName = dbContext.IncomingEvents.EntityType.GetSchemaQualifiedTableName(); + + var sql = $"UPDATE \"{tableName}\" SET \"Processed\" = '1', \"ProcessedTime\" = '{Clock.Now}' WHERE \"Id\" = '{id}'"; + await dbContext.Database.ExecuteSqlRawAsync(sql); + } + + [UnitOfWork] + public override async Task DeleteOldEventsAsync() + { + var dbContext = await DbContextProvider.GetDbContextAsync(); + var tableName = dbContext.IncomingEvents.EntityType.GetSchemaQualifiedTableName(); + var timeToKeepEvents = Clock.Now.Add(DistributedEventsOptions.InboxKeepEventTimeSpan); + + var sql = $"DELETE FROM \"{tableName}\" WHERE \"Processed\" = '1' AND \"CreationTime\" < '{timeToKeepEvents}'"; + await dbContext.Database.ExecuteSqlRawAsync(sql); + } + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/PostgreSqlDbContextEventOutbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/PostgreSqlDbContextEventOutbox.cs new file mode 100644 index 0000000000..c5e79a0014 --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/PostgreSqlDbContextEventOutbox.cs @@ -0,0 +1,25 @@ +using System; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Volo.Abp.Uow; + +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public class PostgreSqlDbContextEventOutbox : DbContextEventOutbox , IPostgreSqlDbContextEventOutbox + where TDbContext : IHasEventOutbox + { + public PostgreSqlDbContextEventOutbox(IDbContextProvider dbContextProvider) : base(dbContextProvider) + { + } + + [UnitOfWork] + public override async Task DeleteAsync(Guid id) + { + var dbContext = (IHasEventOutbox) await DbContextProvider.GetDbContextAsync(); + var tableName = dbContext.OutgoingEvents.EntityType.GetSchemaQualifiedTableName(); + + var sql = $"DELETE FROM \"{tableName}\" WHERE \"Id\" = '{id}'"; + await dbContext.Database.ExecuteSqlRawAsync(sql); + } + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/PostgreSqlInboxConfigExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/PostgreSqlInboxConfigExtensions.cs new file mode 100644 index 0000000000..55afc4794d --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/PostgreSqlInboxConfigExtensions.cs @@ -0,0 +1,13 @@ +using Volo.Abp.EventBus.Distributed; + +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public static class PostgreSqlInboxConfigExtensions + { + public static void UsePostgreSql(this InboxConfig outboxConfig) + where TDbContext : IHasEventInbox + { + outboxConfig.ImplementationType = typeof(IPostgreSqlDbContextEventInbox); + } + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/PostgreSqlOutboxConfigExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/PostgreSqlOutboxConfigExtensions.cs new file mode 100644 index 0000000000..5a65d15c90 --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/PostgreSqlOutboxConfigExtensions.cs @@ -0,0 +1,13 @@ +using Volo.Abp.EventBus.Distributed; + +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public static class PostgreSqlOutboxConfigExtensions + { + public static void UsePostgreSql(this OutboxConfig outboxConfig) + where TDbContext : IHasEventOutbox + { + outboxConfig.ImplementationType = typeof(IPostgreSqlDbContextEventOutbox); + } + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/PostgreSql/AbpEntityFrameworkCorePostgreSqlModule.cs b/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/PostgreSql/AbpEntityFrameworkCorePostgreSqlModule.cs index 7d8c87c63a..55c1a4af42 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/PostgreSql/AbpEntityFrameworkCorePostgreSqlModule.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/PostgreSql/AbpEntityFrameworkCorePostgreSqlModule.cs @@ -1,4 +1,4 @@ -using Npgsql; +using Microsoft.Extensions.DependencyInjection; using Volo.Abp.EntityFrameworkCore.DistributedEvents; using Volo.Abp.Guids; using Volo.Abp.Modularity; @@ -20,10 +20,8 @@ namespace Volo.Abp.EntityFrameworkCore.PostgreSql } }); - Configure(options => - { - options.SqlAdapters.TryAdd(nameof(NpgsqlConnection).ToLower(), new PostgreSqlAdapter()); - }); + context.Services.AddTransient(typeof(IPostgreSqlDbContextEventOutbox<>), typeof(PostgreSqlDbContextEventOutbox<>)); + context.Services.AddTransient(typeof(IPostgreSqlDbContextEventInbox<>), typeof(PostgreSqlDbContextEventInbox<>)); } } } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.SqlServer/Volo/Abp/EntityFrameworkCore/DistributedEvents/SqlServerInboxConfigExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore.SqlServer/Volo/Abp/EntityFrameworkCore/DistributedEvents/SqlServerInboxConfigExtensions.cs new file mode 100644 index 0000000000..60adf600c7 --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore.SqlServer/Volo/Abp/EntityFrameworkCore/DistributedEvents/SqlServerInboxConfigExtensions.cs @@ -0,0 +1,13 @@ +using Volo.Abp.EventBus.Distributed; + +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public static class SqlServerInboxConfigExtensions + { + public static void UseSqlServer(this InboxConfig outboxConfig) + where TDbContext : IHasEventInbox + { + outboxConfig.ImplementationType = typeof(ISqlRawDbContextEventInbox); + } + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.SqlServer/Volo/Abp/EntityFrameworkCore/DistributedEvents/SqlServerOutboxConfigExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore.SqlServer/Volo/Abp/EntityFrameworkCore/DistributedEvents/SqlServerOutboxConfigExtensions.cs new file mode 100644 index 0000000000..9022d5c7e6 --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore.SqlServer/Volo/Abp/EntityFrameworkCore/DistributedEvents/SqlServerOutboxConfigExtensions.cs @@ -0,0 +1,13 @@ +using Volo.Abp.EventBus.Distributed; + +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public static class SqlServerOutboxConfigExtensions + { + public static void UseSqlServer(this OutboxConfig outboxConfig) + where TDbContext : IHasEventOutbox + { + outboxConfig.ImplementationType = typeof(ISqlRawDbContextEventOutbox); + } + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.Sqlite/Volo/Abp/EntityFrameworkCore/DistributedEvents/SqliteInboxConfigExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore.Sqlite/Volo/Abp/EntityFrameworkCore/DistributedEvents/SqliteInboxConfigExtensions.cs new file mode 100644 index 0000000000..ccc92d4eb1 --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore.Sqlite/Volo/Abp/EntityFrameworkCore/DistributedEvents/SqliteInboxConfigExtensions.cs @@ -0,0 +1,13 @@ +using Volo.Abp.EventBus.Distributed; + +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public static class SqliteInboxConfigExtensions + { + public static void UseSqlite(this InboxConfig outboxConfig) + where TDbContext : IHasEventInbox + { + outboxConfig.ImplementationType = typeof(ISqlRawDbContextEventInbox); + } + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.Sqlite/Volo/Abp/EntityFrameworkCore/DistributedEvents/SqliteOutboxConfigExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore.Sqlite/Volo/Abp/EntityFrameworkCore/DistributedEvents/SqliteOutboxConfigExtensions.cs new file mode 100644 index 0000000000..c1d9949c19 --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore.Sqlite/Volo/Abp/EntityFrameworkCore/DistributedEvents/SqliteOutboxConfigExtensions.cs @@ -0,0 +1,13 @@ +using Volo.Abp.EventBus.Distributed; + +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public static class SqliteOutboxConfigExtensions + { + public static void UseSqlite(this OutboxConfig outboxConfig) + where TDbContext : IHasEventOutbox + { + outboxConfig.ImplementationType = typeof(ISqlRawDbContextEventOutbox); + } + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreModule.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreModule.cs index 349116d6eb..f7834c1835 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreModule.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreModule.cs @@ -5,6 +5,7 @@ using Volo.Abp.Domain; using Volo.Abp.EntityFrameworkCore.DependencyInjection; using Volo.Abp.EntityFrameworkCore.DistributedEvents; using Volo.Abp.Modularity; +using Volo.Abp.Uow; using Volo.Abp.Uow.EntityFrameworkCore; namespace Volo.Abp.EntityFrameworkCore @@ -26,14 +27,12 @@ namespace Volo.Abp.EntityFrameworkCore }); }); - Configure(options => - { - options.SqlAdapters.Add(DefaultSqlAdapter.Name, new DefaultSqlAdapter()); - }); - context.Services.TryAddTransient(typeof(IDbContextProvider<>), typeof(UnitOfWorkDbContextProvider<>)); context.Services.AddTransient(typeof(IDbContextEventOutbox<>), typeof(DbContextEventOutbox<>)); context.Services.AddTransient(typeof(IDbContextEventInbox<>), typeof(DbContextEventInbox<>)); + + context.Services.AddTransient(typeof(ISqlRawDbContextEventOutbox<>), typeof(SqlRawDbContextEventOutbox<>)); + context.Services.AddTransient(typeof(ISqlRawDbContextEventInbox<>), typeof(SqlRawDbContextEventInbox<>)); } } } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/AbpEfCoreDistributedEventBusOptions.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/AbpEfCoreDistributedEventBusOptions.cs deleted file mode 100644 index 9497552a09..0000000000 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/AbpEfCoreDistributedEventBusOptions.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Collections.Generic; - -namespace Volo.Abp.EntityFrameworkCore.DistributedEvents -{ - public class AbpEfCoreDistributedEventBusOptions - { - public Dictionary SqlAdapters { get; set; } - - public ISqlAdapter GetSqlAdapter(string connectionType) - { - return SqlAdapters.TryGetValue(connectionType, out var sqlAdapter) ? sqlAdapter : SqlAdapters[DefaultSqlAdapter.Name]; - } - - public AbpEfCoreDistributedEventBusOptions() - { - SqlAdapters = new Dictionary(); - } - } -} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventInbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventInbox.cs index d8f18c6f32..982d335d17 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventInbox.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventInbox.cs @@ -16,18 +16,15 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents { protected IDbContextProvider DbContextProvider { get; } protected AbpDistributedEventBusOptions DistributedEventsOptions { get; } - protected AbpEfCoreDistributedEventBusOptions EfCoreDistributedEventBusOptions { get; } protected IClock Clock { get; } public DbContextEventInbox( IDbContextProvider dbContextProvider, IClock clock, - IOptions distributedEventsOptions, - IOptions efCoreDistributedEventBusOptions) + IOptions distributedEventsOptions) { DbContextProvider = dbContextProvider; Clock = clock; - EfCoreDistributedEventBusOptions = efCoreDistributedEventBusOptions.Value; DistributedEventsOptions = distributedEventsOptions.Value; } @@ -63,16 +60,11 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents public virtual async Task MarkAsProcessedAsync(Guid id) { var dbContext = await DbContextProvider.GetDbContextAsync(); - var tableName = dbContext.IncomingEvents.EntityType.GetSchemaQualifiedTableName(); - var connectionName = dbContext.Database.GetDbConnection().GetType().Name.ToLower(); - var sqlAdapter = EfCoreDistributedEventBusOptions.GetSqlAdapter(connectionName); - - var sql = $"UPDATE {sqlAdapter.NormalizeTableName(tableName)} SET " + - $"{sqlAdapter.NormalizeColumnNameEqualsValue("Processed", 1)}, " + - $"{sqlAdapter.NormalizeColumnNameEqualsValue("ProcessedTime", Clock.Now)} WHERE " + - $"{sqlAdapter.NormalizeColumnNameEqualsValue("Id", id)}"; - - await dbContext.Database.ExecuteSqlRawAsync(sql); + var incomingEvent = await dbContext.IncomingEvents.FindAsync(id); + if (incomingEvent != null) + { + incomingEvent.MarkAsProcessed(Clock.Now); + } } [UnitOfWork] @@ -86,16 +78,11 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents public virtual async Task DeleteOldEventsAsync() { var dbContext = await DbContextProvider.GetDbContextAsync(); - var tableName = dbContext.IncomingEvents.EntityType.GetSchemaQualifiedTableName(); var timeToKeepEvents = Clock.Now.Add(DistributedEventsOptions.InboxKeepEventTimeSpan); - var connectionName = dbContext.Database.GetDbConnection().GetType().Name.ToLower(); - var sqlAdapter = EfCoreDistributedEventBusOptions.GetSqlAdapter(connectionName); - - var sql = $"DELETE FROM {sqlAdapter.NormalizeTableName(tableName)} WHERE " + - $"{sqlAdapter.NormalizeColumnNameEqualsValue("Processed", 1)} AND " + - $"{sqlAdapter.NormalizeColumnName("CreationTime")} < {sqlAdapter.NormalizeValue(timeToKeepEvents)}"; - - await dbContext.Database.ExecuteSqlRawAsync(sql); + var oldEvents = await dbContext.IncomingEvents + .Where(x => x.Processed && x.CreationTime < timeToKeepEvents) + .ToListAsync(); + dbContext.IncomingEvents.RemoveRange(oldEvents); } } } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventOutbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventOutbox.cs index 5451a0a30a..0b8909b966 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventOutbox.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventOutbox.cs @@ -4,7 +4,6 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Options; using Volo.Abp.EventBus.Distributed; using Volo.Abp.Uow; @@ -14,14 +13,11 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents where TDbContext : IHasEventOutbox { protected IDbContextProvider DbContextProvider { get; } - protected AbpEfCoreDistributedEventBusOptions EfCoreDistributedEventBusOptions { get; } public DbContextEventOutbox( - IDbContextProvider dbContextProvider, - IOptions efCoreDistributedEventBusOptions) + IDbContextProvider dbContextProvider) { DbContextProvider = dbContextProvider; - EfCoreDistributedEventBusOptions = efCoreDistributedEventBusOptions.Value; } [UnitOfWork] @@ -54,14 +50,11 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents public virtual async Task DeleteAsync(Guid id) { var dbContext = (IHasEventOutbox) await DbContextProvider.GetDbContextAsync(); - var tableName = dbContext.OutgoingEvents.EntityType.GetSchemaQualifiedTableName(); - var connectionName = dbContext.Database.GetDbConnection().GetType().Name.ToLower(); - var sqlAdapter = EfCoreDistributedEventBusOptions.GetSqlAdapter(connectionName); - - var sql = $"DELETE FROM {sqlAdapter.NormalizeTableName(tableName)} WHERE " + - $"{sqlAdapter.NormalizeColumnNameEqualsValue("Id", id)}"; - - await dbContext.Database.ExecuteSqlRawAsync(sql); + var outgoingEvent = await dbContext.OutgoingEvents.FindAsync(id); + if (outgoingEvent != null) + { + dbContext.Remove(outgoingEvent); + } } } } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DefaultSqlAdapter.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DefaultSqlAdapter.cs deleted file mode 100644 index 8a86af7434..0000000000 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DefaultSqlAdapter.cs +++ /dev/null @@ -1,27 +0,0 @@ -namespace Volo.Abp.EntityFrameworkCore.DistributedEvents -{ - public class DefaultSqlAdapter : ISqlAdapter - { - public const string Name = "default"; - - public string NormalizeTableName(string tableName) - { - return tableName; - } - - public string NormalizeColumnName(string columnName) - { - return columnName; - } - - public string NormalizeColumnNameEqualsValue(string columnName, object value) - { - return $"{columnName} = '{value}'"; - } - - public string NormalizeValue(object value) - { - return $"'{value}'"; - } - } -} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/ISqlAdapter.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/ISqlAdapter.cs deleted file mode 100644 index 9b366f00ab..0000000000 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/ISqlAdapter.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Volo.Abp.EntityFrameworkCore.DistributedEvents -{ - public interface ISqlAdapter - { - string NormalizeTableName(string tableName); - - string NormalizeColumnName(string columnName); - - string NormalizeColumnNameEqualsValue(string columnName, object value); - - string NormalizeValue(object value); - } -} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/ISqlRawDbContextEventInbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/ISqlRawDbContextEventInbox.cs new file mode 100644 index 0000000000..d86e3f36ed --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/ISqlRawDbContextEventInbox.cs @@ -0,0 +1,7 @@ +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public interface ISqlRawDbContextEventInbox : IDbContextEventInbox + where TDbContext : IHasEventInbox + { + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/ISqlRawDbContextEventOutbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/ISqlRawDbContextEventOutbox.cs new file mode 100644 index 0000000000..776cc2f93c --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/ISqlRawDbContextEventOutbox.cs @@ -0,0 +1,7 @@ +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public interface ISqlRawDbContextEventOutbox : IDbContextEventOutbox + where TDbContext : IHasEventOutbox + { + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/SqlRawDbContextEventInbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/SqlRawDbContextEventInbox.cs new file mode 100644 index 0000000000..04bef7579d --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/SqlRawDbContextEventInbox.cs @@ -0,0 +1,43 @@ +using System; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Options; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.Timing; +using Volo.Abp.Uow; + +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public class SqlRawDbContextEventInbox : DbContextEventInbox , ISqlRawDbContextEventInbox + where TDbContext : IHasEventInbox + { + public SqlRawDbContextEventInbox( + IDbContextProvider dbContextProvider, + IClock clock, + IOptions distributedEventsOptions) + : base(dbContextProvider, clock, distributedEventsOptions) + { + } + + [UnitOfWork] + public override async Task MarkAsProcessedAsync(Guid id) + { + var dbContext = await DbContextProvider.GetDbContextAsync(); + var tableName = dbContext.IncomingEvents.EntityType.GetSchemaQualifiedTableName(); + + var sql = $"UPDATE {tableName} SET Processed = '1', ProcessedTime = '{Clock.Now}' WHERE Id = '{id}'"; + await dbContext.Database.ExecuteSqlRawAsync(sql); + } + + [UnitOfWork] + public override async Task DeleteOldEventsAsync() + { + var dbContext = await DbContextProvider.GetDbContextAsync(); + var tableName = dbContext.IncomingEvents.EntityType.GetSchemaQualifiedTableName(); + var timeToKeepEvents = Clock.Now.Add(DistributedEventsOptions.InboxKeepEventTimeSpan); + + var sql = $"DELETE FROM {tableName} WHERE Processed = '1' AND CreationTime < '{timeToKeepEvents}'"; + await dbContext.Database.ExecuteSqlRawAsync(sql); + } + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/SqlRawDbContextEventOutbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/SqlRawDbContextEventOutbox.cs new file mode 100644 index 0000000000..6c890ef9f8 --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/SqlRawDbContextEventOutbox.cs @@ -0,0 +1,26 @@ +using System; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Volo.Abp.Uow; + +namespace Volo.Abp.EntityFrameworkCore.DistributedEvents +{ + public class SqlRawDbContextEventOutbox : DbContextEventOutbox , ISqlRawDbContextEventOutbox + where TDbContext : IHasEventOutbox + { + public SqlRawDbContextEventOutbox(IDbContextProvider dbContextProvider) + : base(dbContextProvider) + { + } + + [UnitOfWork] + public override async Task DeleteAsync(Guid id) + { + var dbContext = (IHasEventOutbox) await DbContextProvider.GetDbContextAsync(); + var tableName = dbContext.OutgoingEvents.EntityType.GetSchemaQualifiedTableName(); + + var sql = $"DELETE FROM {tableName} WHERE Id = '{id}'"; + await dbContext.Database.ExecuteSqlRawAsync(sql); + } + } +} From 28da0b837c35184068644dd0b599da79f2d9a098 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Thu, 30 Sep 2021 00:35:31 +0800 Subject: [PATCH 33/36] Improve --- .../DistributedEvents/PostgreSqlInboxConfigExtensions.cs | 2 +- .../DistributedEvents/PostgreSqlOutboxConfigExtensions.cs | 2 +- .../DistributedEvents/SqlRawDbContextEventInbox.cs | 2 +- .../DistributedEvents/SqlRawDbContextEventOutbox.cs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/PostgreSqlInboxConfigExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/PostgreSqlInboxConfigExtensions.cs index 55afc4794d..f4bb462a1c 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/PostgreSqlInboxConfigExtensions.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/PostgreSqlInboxConfigExtensions.cs @@ -4,7 +4,7 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents { public static class PostgreSqlInboxConfigExtensions { - public static void UsePostgreSql(this InboxConfig outboxConfig) + public static void UseNpgsql(this InboxConfig outboxConfig) where TDbContext : IHasEventInbox { outboxConfig.ImplementationType = typeof(IPostgreSqlDbContextEventInbox); diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/PostgreSqlOutboxConfigExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/PostgreSqlOutboxConfigExtensions.cs index 5a65d15c90..853ae9ba59 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/PostgreSqlOutboxConfigExtensions.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/PostgreSqlOutboxConfigExtensions.cs @@ -4,7 +4,7 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents { public static class PostgreSqlOutboxConfigExtensions { - public static void UsePostgreSql(this OutboxConfig outboxConfig) + public static void UseNpgsql(this OutboxConfig outboxConfig) where TDbContext : IHasEventOutbox { outboxConfig.ImplementationType = typeof(IPostgreSqlDbContextEventOutbox); diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/SqlRawDbContextEventInbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/SqlRawDbContextEventInbox.cs index 04bef7579d..ce7302755a 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/SqlRawDbContextEventInbox.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/SqlRawDbContextEventInbox.cs @@ -25,7 +25,7 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents var dbContext = await DbContextProvider.GetDbContextAsync(); var tableName = dbContext.IncomingEvents.EntityType.GetSchemaQualifiedTableName(); - var sql = $"UPDATE {tableName} SET Processed = '1', ProcessedTime = '{Clock.Now}' WHERE Id = '{id}'"; + var sql = $"UPDATE {tableName} SET Processed = '1', ProcessedTime = '{Clock.Now}' WHERE Id = '{id.ToString().ToUpper()}'"; await dbContext.Database.ExecuteSqlRawAsync(sql); } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/SqlRawDbContextEventOutbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/SqlRawDbContextEventOutbox.cs index 6c890ef9f8..8748e6dc09 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/SqlRawDbContextEventOutbox.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/SqlRawDbContextEventOutbox.cs @@ -19,7 +19,7 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents var dbContext = (IHasEventOutbox) await DbContextProvider.GetDbContextAsync(); var tableName = dbContext.OutgoingEvents.EntityType.GetSchemaQualifiedTableName(); - var sql = $"DELETE FROM {tableName} WHERE Id = '{id}'"; + var sql = $"DELETE FROM {tableName} WHERE Id = '{id.ToString().ToUpper()}'"; await dbContext.Database.ExecuteSqlRawAsync(sql); } } From 3ee9f57c9dd50a6ecb77b121cb74808aaae17e47 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Thu, 30 Sep 2021 15:17:19 +0800 Subject: [PATCH 34/36] Improve --- .../Volo.Abp.Ddd.Domain/Volo.Abp.Ddd.Domain.csproj | 2 +- .../Volo/Abp/Domain/AbpDddDomainModule.cs | 3 ++- .../DistributedEvents/OracleDbContextEventInbox.cs | 6 ++++-- .../DistributedEvents/OracleDbContextEventInbox.cs | 7 ++++--- .../PostgreSqlDbContextEventInbox.cs | 7 ++++--- .../AbpEntityFrameworkCoreModule.cs | 2 -- .../DistributedEvents/DbContextEventInbox.cs | 9 +++++---- .../DistributedEvents/SqlRawDbContextEventInbox.cs | 8 ++++---- .../Abp/EventBus/Boxes/AbpEventBusBoxesOptions.cs | 11 ++++++++--- .../Volo/Abp/EventBus/Boxes/InboxProcessor.cs | 8 ++++---- .../Volo/Abp/EventBus/Boxes/OutboxSender.cs | 4 ++-- .../Distributed/AbpDistributedEventBusOptions.cs | 8 -------- .../Abp/MongoDB/DistributedEvents/IHasEventInbox.cs | 4 ++-- .../MongoDB/DistributedEvents/IHasEventOutbox.cs | 4 ++-- .../DistributedEvents/MongoDbContextEventInbox.cs | 9 +++++---- .../DistDemoApp.MongoDbRebus/TodoMongoDbContext.cs | 13 +++---------- 16 files changed, 50 insertions(+), 55 deletions(-) diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo.Abp.Ddd.Domain.csproj b/framework/src/Volo.Abp.Ddd.Domain/Volo.Abp.Ddd.Domain.csproj index 87879334af..68c90489ff 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo.Abp.Ddd.Domain.csproj +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo.Abp.Ddd.Domain.csproj @@ -17,7 +17,7 @@ - + diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/AbpDddDomainModule.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/AbpDddDomainModule.cs index 523a6ee4f2..38e2d9fc84 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/AbpDddDomainModule.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/AbpDddDomainModule.cs @@ -3,6 +3,7 @@ using Volo.Abp.Auditing; using Volo.Abp.Data; using Volo.Abp.Domain.Repositories; using Volo.Abp.EventBus; +using Volo.Abp.EventBus.Boxes; using Volo.Abp.ExceptionHandling; using Volo.Abp.Guids; using Volo.Abp.Modularity; @@ -18,7 +19,7 @@ namespace Volo.Abp.Domain [DependsOn( typeof(AbpAuditingModule), typeof(AbpDataModule), - typeof(AbpEventBusModule), + typeof(AbpEventBusBoxesModule), typeof(AbpGuidsModule), typeof(AbpMultiTenancyModule), typeof(AbpThreadingModule), diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleDbContextEventInbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleDbContextEventInbox.cs index d5f1b7afcc..ee73291e58 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleDbContextEventInbox.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleDbContextEventInbox.cs @@ -2,6 +2,7 @@ using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Options; +using Volo.Abp.EventBus.Boxes; using Volo.Abp.EventBus.Distributed; using Volo.Abp.Timing; using Volo.Abp.Uow; @@ -14,7 +15,8 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents public OracleDbContextEventInbox( IDbContextProvider dbContextProvider, IClock clock, - IOptions distributedEventsOptions) : base(dbContextProvider, clock, distributedEventsOptions) + IOptions eventBusBoxesOptions) + : base(dbContextProvider, clock, eventBusBoxesOptions) { } @@ -33,7 +35,7 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents { var dbContext = await DbContextProvider.GetDbContextAsync(); var tableName = dbContext.IncomingEvents.EntityType.GetSchemaQualifiedTableName(); - var timeToKeepEvents = Clock.Now.Add(DistributedEventsOptions.InboxKeepEventTimeSpan); + var timeToKeepEvents = Clock.Now.Add(- EventBusBoxesOptions.WaitTimeToDeleteProcessedInboxEvents); var sql = $"DELETE FROM \"{tableName}\" WHERE \"Processed\" = '1' AND \"CreationTime\" < TO_DATE('{timeToKeepEvents}', 'yyyy-mm-dd hh24:mi:ss')"; await dbContext.Database.ExecuteSqlRawAsync(sql); diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleDbContextEventInbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleDbContextEventInbox.cs index d5f1b7afcc..6d6d04d267 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleDbContextEventInbox.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleDbContextEventInbox.cs @@ -2,7 +2,7 @@ using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Options; -using Volo.Abp.EventBus.Distributed; +using Volo.Abp.EventBus.Boxes; using Volo.Abp.Timing; using Volo.Abp.Uow; @@ -14,7 +14,8 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents public OracleDbContextEventInbox( IDbContextProvider dbContextProvider, IClock clock, - IOptions distributedEventsOptions) : base(dbContextProvider, clock, distributedEventsOptions) + IOptions eventBusBoxesOptions) + : base(dbContextProvider, clock, eventBusBoxesOptions) { } @@ -33,7 +34,7 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents { var dbContext = await DbContextProvider.GetDbContextAsync(); var tableName = dbContext.IncomingEvents.EntityType.GetSchemaQualifiedTableName(); - var timeToKeepEvents = Clock.Now.Add(DistributedEventsOptions.InboxKeepEventTimeSpan); + var timeToKeepEvents = Clock.Now - EventBusBoxesOptions.WaitTimeToDeleteProcessedInboxEvents; var sql = $"DELETE FROM \"{tableName}\" WHERE \"Processed\" = '1' AND \"CreationTime\" < TO_DATE('{timeToKeepEvents}', 'yyyy-mm-dd hh24:mi:ss')"; await dbContext.Database.ExecuteSqlRawAsync(sql); diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/PostgreSqlDbContextEventInbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/PostgreSqlDbContextEventInbox.cs index 4560bdb2c4..fedff90dec 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/PostgreSqlDbContextEventInbox.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/DistributedEvents/PostgreSqlDbContextEventInbox.cs @@ -2,6 +2,7 @@ using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Options; +using Volo.Abp.EventBus.Boxes; using Volo.Abp.EventBus.Distributed; using Volo.Abp.Timing; using Volo.Abp.Uow; @@ -14,8 +15,8 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents public PostgreSqlDbContextEventInbox( IDbContextProvider dbContextProvider, IClock clock, - IOptions distributedEventsOptions) - : base(dbContextProvider, clock, distributedEventsOptions) + IOptions eventBusBoxesOptions) + : base(dbContextProvider, clock, eventBusBoxesOptions) { } @@ -34,7 +35,7 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents { var dbContext = await DbContextProvider.GetDbContextAsync(); var tableName = dbContext.IncomingEvents.EntityType.GetSchemaQualifiedTableName(); - var timeToKeepEvents = Clock.Now.Add(DistributedEventsOptions.InboxKeepEventTimeSpan); + var timeToKeepEvents = Clock.Now - EventBusBoxesOptions.WaitTimeToDeleteProcessedInboxEvents; var sql = $"DELETE FROM \"{tableName}\" WHERE \"Processed\" = '1' AND \"CreationTime\" < '{timeToKeepEvents}'"; await dbContext.Database.ExecuteSqlRawAsync(sql); diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreModule.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreModule.cs index f7834c1835..96c245be2e 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreModule.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreModule.cs @@ -2,10 +2,8 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Volo.Abp.Domain; -using Volo.Abp.EntityFrameworkCore.DependencyInjection; using Volo.Abp.EntityFrameworkCore.DistributedEvents; using Volo.Abp.Modularity; -using Volo.Abp.Uow; using Volo.Abp.Uow.EntityFrameworkCore; namespace Volo.Abp.EntityFrameworkCore diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventInbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventInbox.cs index 982d335d17..242b601177 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventInbox.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventInbox.cs @@ -5,6 +5,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Options; +using Volo.Abp.EventBus.Boxes; using Volo.Abp.EventBus.Distributed; using Volo.Abp.Timing; using Volo.Abp.Uow; @@ -15,17 +16,17 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents where TDbContext : IHasEventInbox { protected IDbContextProvider DbContextProvider { get; } - protected AbpDistributedEventBusOptions DistributedEventsOptions { get; } + protected AbpEventBusBoxesOptions EventBusBoxesOptions { get; } protected IClock Clock { get; } public DbContextEventInbox( IDbContextProvider dbContextProvider, IClock clock, - IOptions distributedEventsOptions) + IOptions eventBusBoxesOptions) { DbContextProvider = dbContextProvider; Clock = clock; - DistributedEventsOptions = distributedEventsOptions.Value; + EventBusBoxesOptions = eventBusBoxesOptions.Value; } [UnitOfWork] @@ -78,7 +79,7 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents public virtual async Task DeleteOldEventsAsync() { var dbContext = await DbContextProvider.GetDbContextAsync(); - var timeToKeepEvents = Clock.Now.Add(DistributedEventsOptions.InboxKeepEventTimeSpan); + var timeToKeepEvents = Clock.Now - EventBusBoxesOptions.WaitTimeToDeleteProcessedInboxEvents; var oldEvents = await dbContext.IncomingEvents .Where(x => x.Processed && x.CreationTime < timeToKeepEvents) .ToListAsync(); diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/SqlRawDbContextEventInbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/SqlRawDbContextEventInbox.cs index ce7302755a..cb764ede17 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/SqlRawDbContextEventInbox.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/SqlRawDbContextEventInbox.cs @@ -2,7 +2,7 @@ using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Options; -using Volo.Abp.EventBus.Distributed; +using Volo.Abp.EventBus.Boxes; using Volo.Abp.Timing; using Volo.Abp.Uow; @@ -14,8 +14,8 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents public SqlRawDbContextEventInbox( IDbContextProvider dbContextProvider, IClock clock, - IOptions distributedEventsOptions) - : base(dbContextProvider, clock, distributedEventsOptions) + IOptions eventBusBoxesOptions) + : base(dbContextProvider, clock, eventBusBoxesOptions) { } @@ -34,7 +34,7 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents { var dbContext = await DbContextProvider.GetDbContextAsync(); var tableName = dbContext.IncomingEvents.EntityType.GetSchemaQualifiedTableName(); - var timeToKeepEvents = Clock.Now.Add(DistributedEventsOptions.InboxKeepEventTimeSpan); + var timeToKeepEvents = Clock.Now - EventBusBoxesOptions.WaitTimeToDeleteProcessedInboxEvents; var sql = $"DELETE FROM {tableName} WHERE Processed = '1' AND CreationTime < '{timeToKeepEvents}'"; await dbContext.Database.ExecuteSqlRawAsync(sql); diff --git a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/AbpEventBusBoxesOptions.cs b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/AbpEventBusBoxesOptions.cs index da91d672d3..1d72666c42 100644 --- a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/AbpEventBusBoxesOptions.cs +++ b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/AbpEventBusBoxesOptions.cs @@ -26,10 +26,14 @@ namespace Volo.Abp.EventBus.Boxes public TimeSpan PeriodTimeSpan { get; set; } /// - /// Delay time of and /// Default: 15 seconds /// - public TimeSpan DelayTimeSpan { get; set; } + public TimeSpan DistributedLockWaitDuration { get; set; } + + /// + /// Default: 2 hours + /// + public TimeSpan WaitTimeToDeleteProcessedInboxEvents { get; set; } public AbpEventBusBoxesOptions() { @@ -37,7 +41,8 @@ namespace Volo.Abp.EventBus.Boxes InboxWaitingEventMaxCount = 1000; OutboxWaitingEventMaxCount = 1000; PeriodTimeSpan = TimeSpan.FromSeconds(2); - DelayTimeSpan = TimeSpan.FromSeconds(15); + DistributedLockWaitDuration = TimeSpan.FromSeconds(15); + WaitTimeToDeleteProcessedInboxEvents = TimeSpan.FromHours(2); } } } diff --git a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/InboxProcessor.cs b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/InboxProcessor.cs index 29cca3d624..e3c71771ad 100644 --- a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/InboxProcessor.cs +++ b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/InboxProcessor.cs @@ -49,7 +49,7 @@ namespace Volo.Abp.EventBus.Boxes UnitOfWorkManager = unitOfWorkManager; Clock = clock; EventBusBoxesOptions = eventBusBoxesOptions.Value; - Timer.Period = EventBusBoxesOptions.PeriodTimeSpan.Seconds; + Timer.Period = EventBusBoxesOptions.PeriodTimeSpan.Milliseconds; Timer.Elapsed += TimerOnElapsed; Logger = NullLogger.Instance; StoppingTokenSource = new CancellationTokenSource(); @@ -120,21 +120,21 @@ namespace Volo.Abp.EventBus.Boxes else { Logger.LogDebug("Could not obtain the distributed lock: " + DistributedLockName); - await TaskDelayHelper.DelayAsync(EventBusBoxesOptions.DelayTimeSpan.Milliseconds, StoppingToken); + await TaskDelayHelper.DelayAsync(EventBusBoxesOptions.DistributedLockWaitDuration.Milliseconds, StoppingToken); } } } protected virtual async Task DeleteOldEventsAsync() { - if (LastCleanTime != null && LastCleanTime > Clock.Now.Add(EventBusBoxesOptions.CleanOldEventTimeIntervalSpan)) + if (LastCleanTime != null && LastCleanTime + EventBusBoxesOptions.CleanOldEventTimeIntervalSpan > Clock.Now) { return; } await Inbox.DeleteOldEventsAsync(); - LastCleanTime = DateTime.Now; + LastCleanTime = Clock.Now; } } } diff --git a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs index e8a05c60ba..32545227c3 100644 --- a/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs +++ b/framework/src/Volo.Abp.EventBus.Boxes/Volo/Abp/EventBus/Boxes/OutboxSender.cs @@ -39,7 +39,7 @@ namespace Volo.Abp.EventBus.Boxes DistributedEventBus = distributedEventBus; DistributedLockProvider = distributedLockProvider; EventBusBoxesOptions = eventBusBoxesOptions.Value; - Timer.Period = EventBusBoxesOptions.PeriodTimeSpan.Seconds; + Timer.Period = EventBusBoxesOptions.PeriodTimeSpan.Milliseconds; Timer.Elapsed += TimerOnElapsed; Logger = NullLogger.Instance; StoppingTokenSource = new CancellationTokenSource(); @@ -100,7 +100,7 @@ namespace Volo.Abp.EventBus.Boxes else { Logger.LogDebug("Could not obtain the distributed lock: " + DistributedLockName); - await TaskDelayHelper.DelayAsync(EventBusBoxesOptions.DelayTimeSpan.Milliseconds, StoppingToken); + await TaskDelayHelper.DelayAsync(EventBusBoxesOptions.DistributedLockWaitDuration.Milliseconds, StoppingToken); } } } diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/AbpDistributedEventBusOptions.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/AbpDistributedEventBusOptions.cs index 5b71542665..ab8fe6823b 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/AbpDistributedEventBusOptions.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/AbpDistributedEventBusOptions.cs @@ -1,4 +1,3 @@ -using System; using Volo.Abp.Collections; namespace Volo.Abp.EventBus.Distributed @@ -10,18 +9,11 @@ namespace Volo.Abp.EventBus.Distributed public OutboxConfigDictionary Outboxes { get; } public InboxConfigDictionary Inboxes { get; } - - /// - /// Default: -2 hours - /// - public TimeSpan InboxKeepEventTimeSpan { get; set; } - public AbpDistributedEventBusOptions() { Handlers = new TypeList(); Outboxes = new OutboxConfigDictionary(); Inboxes = new InboxConfigDictionary(); - InboxKeepEventTimeSpan = TimeSpan.FromHours(-2); } } } diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IHasEventInbox.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IHasEventInbox.cs index 387e860bce..792a85e124 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IHasEventInbox.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IHasEventInbox.cs @@ -4,6 +4,6 @@ namespace Volo.Abp.MongoDB.DistributedEvents { public interface IHasEventInbox : IAbpMongoDbContext { - IMongoCollection IncomingEvents { get; set; } + IMongoCollection IncomingEvents { get; } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IHasEventOutbox.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IHasEventOutbox.cs index cf57aaa699..ab4bc10f35 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IHasEventOutbox.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IHasEventOutbox.cs @@ -4,6 +4,6 @@ namespace Volo.Abp.MongoDB.DistributedEvents { public interface IHasEventOutbox : IAbpMongoDbContext { - IMongoCollection OutgoingEvents { get; set; } + IMongoCollection OutgoingEvents { get; } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventInbox.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventInbox.cs index 62927d2279..3cf5485512 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventInbox.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventInbox.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using Microsoft.Extensions.Options; using MongoDB.Driver; using MongoDB.Driver.Linq; +using Volo.Abp.EventBus.Boxes; using Volo.Abp.EventBus.Distributed; using Volo.Abp.Timing; using Volo.Abp.Uow; @@ -16,17 +17,17 @@ namespace Volo.Abp.MongoDB.DistributedEvents where TMongoDbContext : IHasEventInbox { protected IMongoDbContextProvider DbContextProvider { get; } - protected AbpDistributedEventBusOptions DistributedEventsOptions { get; } + protected AbpEventBusBoxesOptions EventBusBoxesOptions { get; } protected IClock Clock { get; } public MongoDbContextEventInbox( IMongoDbContextProvider dbContextProvider, IClock clock, - IOptions distributedEventsOptions) + IOptions eventBusBoxesOptions) { DbContextProvider = dbContextProvider; Clock = clock; - DistributedEventsOptions = distributedEventsOptions.Value; + EventBusBoxesOptions = eventBusBoxesOptions.Value; } @@ -96,7 +97,7 @@ namespace Volo.Abp.MongoDB.DistributedEvents public virtual async Task DeleteOldEventsAsync() { var dbContext = await DbContextProvider.GetDbContextAsync(); - var timeToKeepEvents = Clock.Now.Add(DistributedEventsOptions.InboxKeepEventTimeSpan); + var timeToKeepEvents = Clock.Now - EventBusBoxesOptions.WaitTimeToDeleteProcessedInboxEvents; if (dbContext.SessionHandle != null) { diff --git a/test/DistEvents/DistDemoApp.MongoDbRebus/TodoMongoDbContext.cs b/test/DistEvents/DistDemoApp.MongoDbRebus/TodoMongoDbContext.cs index a7f1b78f86..95370bb4d2 100644 --- a/test/DistEvents/DistDemoApp.MongoDbRebus/TodoMongoDbContext.cs +++ b/test/DistEvents/DistDemoApp.MongoDbRebus/TodoMongoDbContext.cs @@ -11,16 +11,9 @@ namespace DistDemoApp public IMongoCollection TodoItems => Collection(); public IMongoCollection TodoSummaries => Collection(); - public IMongoCollection OutgoingEvents - { - get => Collection(); - set {} - } - public IMongoCollection IncomingEvents - { - get => Collection(); - set {} - } + public IMongoCollection OutgoingEvents => Collection(); + + public IMongoCollection IncomingEvents => Collection(); } } From 5291b97738c8e972d1491641e431eab4ba6dfdef Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Thu, 30 Sep 2021 15:20:50 +0800 Subject: [PATCH 35/36] Update OracleDbContextEventInbox.cs --- .../DistributedEvents/OracleDbContextEventInbox.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleDbContextEventInbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleDbContextEventInbox.cs index ee73291e58..c19ca6746a 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleDbContextEventInbox.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/DistributedEvents/OracleDbContextEventInbox.cs @@ -35,7 +35,7 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents { var dbContext = await DbContextProvider.GetDbContextAsync(); var tableName = dbContext.IncomingEvents.EntityType.GetSchemaQualifiedTableName(); - var timeToKeepEvents = Clock.Now.Add(- EventBusBoxesOptions.WaitTimeToDeleteProcessedInboxEvents); + var timeToKeepEvents = Clock.Now - EventBusBoxesOptions.WaitTimeToDeleteProcessedInboxEvents; var sql = $"DELETE FROM \"{tableName}\" WHERE \"Processed\" = '1' AND \"CreationTime\" < TO_DATE('{timeToKeepEvents}', 'yyyy-mm-dd hh24:mi:ss')"; await dbContext.Database.ExecuteSqlRawAsync(sql); From 99a45164fdd7b296912b2bc63979696fab80b52d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Thu, 30 Sep 2021 11:03:09 +0300 Subject: [PATCH 36/36] Remove ApplyAbpConcepts usage --- .../Volo/Abp/EntityFrameworkCore/AbpDbContext.cs | 4 ---- 1 file changed, 4 deletions(-) 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 508da4801f..8e7926f9ae 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs @@ -155,10 +155,6 @@ namespace Volo.Abp.EntityFrameworkCore { try { - ApplyAbpConcepts(); - - var eventReport = CreateEventReport(); - var auditLog = AuditingManager?.Current?.Log; List entityChangeList = null; if (auditLog != null)