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/49] 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/49] 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/49] 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/49] 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/49] 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/49] 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/49] 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/49] 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/49] 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/49] 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 6177e5d6b54fba0d39b4b19b2ec8c8c6b0328f0e Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 9 Sep 2021 13:07:37 +0800 Subject: [PATCH 11/49] Add `IsActive` property to IdentityUser. --- .../Account/Localization/Resources/ar.json | 2 +- .../Account/Localization/Resources/cs.json | 2 +- .../Account/Localization/Resources/de-DE.json | 2 +- .../Account/Localization/Resources/de.json | 2 +- .../Account/Localization/Resources/en-GB.json | 2 +- .../Account/Localization/Resources/en.json | 2 +- .../Account/Localization/Resources/es-mx.json | 2 +- .../Account/Localization/Resources/es.json | 2 +- .../Account/Localization/Resources/fi.json | 2 +- .../Account/Localization/Resources/fr.json | 2 +- .../Account/Localization/Resources/hi.json | 2 +- .../Account/Localization/Resources/hu.json | 2 +- .../Account/Localization/Resources/it.json | 2 +- .../Account/Localization/Resources/nl.json | 2 +- .../Account/Localization/Resources/pl-PL.json | 2 +- .../Account/Localization/Resources/pt-BR.json | 2 +- .../Account/Localization/Resources/ro-RO.json | 2 +- .../Account/Localization/Resources/ru.json | 2 +- .../Account/Localization/Resources/sk.json | 2 +- .../Account/Localization/Resources/sl.json | 2 +- .../Account/Localization/Resources/tr.json | 2 +- .../Account/Localization/Resources/vi.json | 2 +- .../Localization/Resources/zh-Hans.json | 2 +- .../Localization/Resources/zh-Hant.json | 2 +- .../IdentityUserCreateOrUpdateDtoBase.cs | 2 ++ .../Volo/Abp/Identity/IdentityUserDto.cs | 2 ++ .../Abp/Identity/IdentityUserAppService.cs | 2 +- .../Identity/AspNetCore/AbpSignInManager.cs | 13 +++++++++++- .../Pages/Identity/UserManagement.razor | 8 ++++++- .../Volo/Abp/Identity/Localization/en.json | 1 + .../Volo/Abp/Identity/Localization/tr.json | 1 + .../Abp/Identity/Localization/zh-Hans.json | 1 + .../Abp/Identity/Localization/zh-Hant.json | 1 + .../Volo/Abp/Identity/IdentityUser.cs | 21 ++++++++++++++----- .../Abp/Identity/IdentityUserDtoExtensions.cs | 3 ++- .../Pages/Identity/Users/CreateModal.cshtml | 1 + .../Identity/Users/CreateModal.cshtml.cs | 2 ++ .../Pages/Identity/Users/EditModal.cshtml | 1 + .../Pages/Identity/Users/EditModal.cshtml.cs | 2 ++ .../AspNetCore/AbpSignInManager_Tests.cs | 10 +++++++++ .../Identity/AbpIdentityTestDataBuilder.cs | 7 +++++++ .../Volo/Abp/Identity/IdentityTestData.cs | 1 + .../Localization/Resources/FR.json | 2 +- .../Localization/Resources/ar.json | 2 +- .../Localization/Resources/cs.json | 2 +- .../Localization/Resources/de-DE.json | 2 +- .../Localization/Resources/de.json | 2 +- .../Localization/Resources/en-GB.json | 2 +- .../Localization/Resources/en.json | 2 +- .../Localization/Resources/es.json | 2 +- .../Localization/Resources/fi.json | 2 +- .../Localization/Resources/hi.json | 2 +- .../Localization/Resources/hu.json | 2 +- .../Localization/Resources/it.json | 2 +- .../Localization/Resources/nl.json | 2 +- .../Localization/Resources/ro-RO.json | 2 +- .../Localization/Resources/ru.json | 2 +- .../Localization/Resources/sk.json | 2 +- .../Localization/Resources/sl.json | 2 +- .../Localization/Resources/tr.json | 2 +- .../Localization/Resources/zh-Hans.json | 2 +- .../Localization/Resources/zh-Hant.json | 2 +- .../AspNetIdentity/AbpProfileService.cs | 6 ++++++ 63 files changed, 120 insertions(+), 53 deletions(-) diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/ar.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/ar.json index e3701c9b69..b80c6c7f05 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/ar.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/ar.json @@ -9,7 +9,7 @@ "UseAnotherServiceToLogin": "استخدم خدمة أخرى لتسجيل الدخول", "UserLockedOutMessage": "تم قفل حساب المستخدم بسبب محاولات تسجيل الدخول غير الصالحة. يرجى الانتظار بعض الوقت والمحاولة مرة أخرى.", "InvalidUserNameOrPassword": "اسم مستخدم أو كلمة مرور غير صالحة!", - "LoginIsNotAllowed": "غير مسموح لك بتسجيل الدخول! أنت بحاجة إلى تأكيد بريدك الإلكتروني / رقم هاتفك.", + "LoginIsNotAllowed": "لا يسمح لك بتسجيل الدخول! حسابك غير نشط أو يحتاج إلى تأكيد بريدك الإلكتروني / رقم هاتفك.", "SelfRegistrationDisabledMessage": "تم تعطيل التسجيل الذاتي لهذا التطبيق. يرجى الاتصال بمسؤول التطبيق لتسجيل مستخدم جديد.", "LocalLoginDisabledMessage": "تسجيل الدخول المحلي معطّل لهذا التطبيق.", "Login": "دخول", diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/cs.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/cs.json index 98efb29ed6..d170187231 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/cs.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/cs.json @@ -9,7 +9,7 @@ "UseAnotherServiceToLogin": "Použít jinou službu k přihlášení", "UserLockedOutMessage": "Tento účet byl uzamčen z důvodu neúspěšných přihlášení. Přihlaste se prosím později.", "InvalidUserNameOrPassword": "Neplatné uživatelské jméno nebo heslo!", - "LoginIsNotAllowed": "Není vám dovoleno se přihlásit! Musíte první potvrdit email/telefonní číslo.", + "LoginIsNotAllowed": "Nemáte oprávnění se přihlásit! Váš účet je neaktivní nebo potřebuje potvrdit váš e -mail/telefonní číslo.", "SelfRegistrationDisabledMessage": "Vlastní registrace uživatele není povolena. K vytvoření účtu kontaktujte správce.", "LocalLoginDisabledMessage": "Místní přihlášení je pro tuto aplikaci zakázáno.", "Login": "Přihlásit", diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/de-DE.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/de-DE.json index 2e8b1f4eb4..f2dc47ccbc 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/de-DE.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/de-DE.json @@ -9,7 +9,7 @@ "UseAnotherServiceToLogin": "Verwenden Sie einen anderen Dienst, um sich anzumelden", "UserLockedOutMessage": "Das Benutzerkonto wurde aufgrund ungültiger Anmeldeversuche gesperrt. Bitte warten Sie eine Weile und versuchen Sie es erneut.", "InvalidUserNameOrPassword": "Ungültiger Benutzername oder Passwort!", - "LoginIsNotAllowed": "Sie dürfen sich nicht anmelden! Sie müssen Ihre E-Mail-Adresse / Telefonnummer bestätigen.", + "LoginIsNotAllowed": "Sie dürfen sich nicht anmelden! Ihr Konto ist inaktiv oder muss Ihre E-Mail-/Telefonnummer bestätigen.", "SelfRegistrationDisabledMessage": "Die Selbstregistrierung ist für diese Anwendung deaktiviert. Bitte wenden Sie sich an den Anwendungsadministrator, um einen neuen Benutzer zu registrieren.", "LocalLoginDisabledMessage": "Die lokale Anmeldung ist für diese Anwendung deaktiviert.", "Login": "Anmelden", diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/de.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/de.json index 99854771e8..f66217156b 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/de.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/de.json @@ -9,7 +9,7 @@ "UseAnotherServiceToLogin": "Einen anderen Dienst zum Anmelden verwenden", "UserLockedOutMessage": "Das Benutzerkonto wurde aufgrund fehlgeschlagener Anmeldeversuche gesperrt. Bitte warten Sie eine Weile und versuchen Sie es erneut.", "InvalidUserNameOrPassword": "Ungültiger Benutzername oder Passwort!", - "LoginIsNotAllowed": "Sie dürfen sich nicht anmelden! Sie müssen Ihre E-Mail/Telefonnummer bestätigen.", + "LoginIsNotAllowed": "Sie dürfen sich nicht anmelden! Ihr Konto ist inaktiv oder muss Ihre E-Mail-/Telefonnummer bestätigen.", "SelfRegistrationDisabledMessage": "Die Selbstregistrierung ist für diese Anwendung deaktiviert. Bitte wenden Sie sich an den Anwendungsadministrator, um einen neuen Benutzer zu registrieren.", "LocalLoginDisabledMessage": "Die lokale Anmeldung ist für diese Anwendung deaktiviert.", "Login": "Anmelden", diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en-GB.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en-GB.json index cbc5643a53..7bfcdccec7 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en-GB.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en-GB.json @@ -9,7 +9,7 @@ "UseAnotherServiceToLogin": "Use another service to log in", "UserLockedOutMessage": "The user account has been locked out due to invalid login attempts. Please wait a while and try again.", "InvalidUserNameOrPassword": "Invalid username or password!", - "LoginIsNotAllowed": "You are not allowed to login! You need to confirm your email/phone number.", + "LoginIsNotAllowed": "You are not allowed to login! Your account is inactive or needs to confirm your email/phone number.", "SelfRegistrationDisabledMessage": "Self-registration is disabled for this application. Please contact the application administrator to register a new user.", "LocalLoginDisabledMessage": "Local login is disabled for this application.", "Login": "Login", diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en.json index 48b2ebb4ee..246466193e 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en.json @@ -9,7 +9,7 @@ "UseAnotherServiceToLogin": "Use another service to log in", "UserLockedOutMessage": "The user account has been locked out due to invalid login attempts. Please wait a while and try again.", "InvalidUserNameOrPassword": "Invalid username or password!", - "LoginIsNotAllowed": "You are not allowed to login! You need to confirm your email/phone number.", + "LoginIsNotAllowed": "You are not allowed to login! Your account is inactive or needs to confirm your email/phone number.", "SelfRegistrationDisabledMessage": "Self-registration is disabled for this application. Please contact the application administrator to register a new user.", "LocalLoginDisabledMessage": "Local login is disabled for this application.", "Login": "Login", diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/es-mx.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/es-mx.json index 68a38c96de..d8c50231a5 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/es-mx.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/es-mx.json @@ -9,7 +9,7 @@ "UseAnotherServiceToLogin": "Usar otro servicio para iniciar sesión", "UserLockedOutMessage": "La cuenta de usuario ha sido bloqueada debido a los intentos de inicio de sesión no válido. Por favor, espere un rato y vuelve a intentarlo.", "InvalidUserNameOrPassword": "No válido nombre de usuario o la contraseña!", - "LoginIsNotAllowed": "No está permitido el inicio de sesión! Usted tendrá que confirmar su correo electrónico\/número de teléfono.", + "LoginIsNotAllowed": "¡No está permitido iniciar sesión! Su cuenta está inactiva o necesita confirmar su correo electrónico / número de teléfono.", "SelfRegistrationDisabledMessage": "El autoregistro de usuario está deshabilitado para esta aplicación. Póngase en contacto con el administrador de la aplicación para registrar un nuevo usuario.", "Login": "Iniciar sesión", "Cancel": "Cancelar", diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/es.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/es.json index 9c1d8b6b3a..894cb709ed 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/es.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/es.json @@ -9,7 +9,7 @@ "UseAnotherServiceToLogin": "Usar otro servicio para iniciar sesión", "UserLockedOutMessage": "La cuenta de usuario ha sido bloqueada debido a los intentos de inicio de sesión no válidos. Por favor, espere unos minutos y vuelve a intentarlo.", "InvalidUserNameOrPassword": "El nombre de usuario o la contraseña no son válidos", - "LoginIsNotAllowed": "No está permitido el inicio de sesión! Usted tendrá que confirmar su correo electrónico o número de teléfono.", + "LoginIsNotAllowed": "¡No está permitido iniciar sesión! Su cuenta está inactiva o necesita confirmar su correo electrónico / número de teléfono.", "SelfRegistrationDisabledMessage": "El autoregistro de usuario está deshabilitado para esta aplicación. Póngase en contacto con el administrador de la aplicación para registrar un nuevo usuario.", "LocalLoginDisabledMessage": "Inicio de sesión local ha sido deshabilitado para esta aplicación", "Login": "Iniciar sesión", diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/fi.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/fi.json index 5c938a9480..a4e55494eb 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/fi.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/fi.json @@ -9,7 +9,7 @@ "UseAnotherServiceToLogin": "Käytä toista palvelua kirjautumiseen", "UserLockedOutMessage": "Käyttäjätili on lukittu virheellisten kirjautumisyritysten vuoksi. Odota hetki ja yritä uudelleen.", "InvalidUserNameOrPassword": "Väärä käyttäjänimi tai salasana!", - "LoginIsNotAllowed": "Et saa kirjautua sisään! Sinun on vahvistettava sähköpostiosoitteesi / puhelinnumerosi.", + "LoginIsNotAllowed": "Et saa kirjautua sisään! Tilisi on passiivinen tai sinun on vahvistettava sähköpostiosoitteesi/puhelinnumerosi.", "SelfRegistrationDisabledMessage": "Itserekisteröinti on poistettu käytöstä tälle sovellukselle. Rekisteröi uusi käyttäjä ottamalla yhteyttä sovelluksen järjestelmänvalvojaan.", "LocalLoginDisabledMessage": "Paikallinen sisäänkirjautuminen on poistettu käytöstä tälle sovellukselle.", "Login": "Kirjaudu sisään", diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/fr.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/fr.json index 84e0ac85fd..5cbff3b5a0 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/fr.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/fr.json @@ -9,7 +9,7 @@ "UseAnotherServiceToLogin": "Utilisez un autre service pour vous connecter", "UserLockedOutMessage": "Le compte utilisateur a été verrouillé en raison de tentatives de connexion non valides. Veuillez patienter un instant et réessayer.", "InvalidUserNameOrPassword": "Nom d'utilisateur ou mot de passe invalide!", - "LoginIsNotAllowed": "Vous n'êtes pas autorisé à vous connecter! Vous devez confirmer votre e-mail / numéro de téléphone.", + "LoginIsNotAllowed": "Vous n'êtes pas autorisé à vous connecter ! Votre compte est inactif ou doit confirmer votre e-mail/numéro de téléphone.", "SelfRegistrationDisabledMessage": "L'auto-inscription est désactivée pour cette application. Veuillez contacter l'administrateur de l'application pour enregistrer un nouvel utilisateur.", "LocalLoginDisabledMessage": "La connexion locale est désactivée pour cette application.", "Login": "Connectez-vous", diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/hi.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/hi.json index d9a2bccd85..e1605b14e2 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/hi.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/hi.json @@ -9,7 +9,7 @@ "UseAnotherServiceToLogin": "लॉग इन करने के लिए किसी अन्य सेवा का उपयोग करें", "UserLockedOutMessage": "अमान्य लॉगिन प्रयासों के कारण उपयोगकर्ता खाता बंद कर दिया गया है। कृपया थोड़ी देर प्रतीक्षा करें और पुन: प्रयास करें।", "InvalidUserNameOrPassword": "अमान्य उपयोगकर्ता नाम या पासवर्ड!", - "LoginIsNotAllowed": "आपको लॉगिन करने की अनुमति नहीं है! आपको अपने ईमेल / फोन नंबर की पुष्टि करनी होगी।", + "LoginIsNotAllowed": "आपको लॉगिन करने की अनुमति नहीं है! आपका खाता निष्क्रिय है या आपके ईमेल/फ़ोन नंबर की पुष्टि करने की आवश्यकता है।", "SelfRegistrationDisabledMessage": "इस आवेदन के लिए स्व-पंजीकरण अक्षम है। नया उपयोगकर्ता पंजीकृत करने के लिए कृपया एप्लिकेशन व्यवस्थापक से संपर्क करें।", "LocalLoginDisabledMessage": "इस एप्लिकेशन के लिए स्थानीय लॉगिन अक्षम है।", "Login": "लॉग इन करें", diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/hu.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/hu.json index d1d774e7cb..dc95c1b3cb 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/hu.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/hu.json @@ -9,7 +9,7 @@ "UseAnotherServiceToLogin": "Használjon másik szolgáltatást a bejelentkezéshez", "UserLockedOutMessage": "A felhasználói fiókot érvénytelen bejelentkezési kísérletek miatt zároltuk. Kérjük, várjon egy kicsit, és próbálja újra.", "InvalidUserNameOrPassword": "Érvénytelen felhasználónév vagy jelszó!", - "LoginIsNotAllowed": "Ön nem léphet be! Meg kell erősítenie e-mail címét / telefonszámát.", + "LoginIsNotAllowed": "A bejelentkezés nem engedélyezett! Fiókja inaktív, vagy meg kell erősítenie e -mail címét/telefonszámát.", "SelfRegistrationDisabledMessage": "Ennél az alkalmazásnál az önregisztráció le van tiltva. Új felhasználó regisztrálásához vegye fel a kapcsolatot az alkalmazás rendszergazdájával.", "LocalLoginDisabledMessage": "A helyi bejelentkezés le van tiltva ennél az alkalmazásnál.", "Login": "Bejelntkezés", diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/it.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/it.json index b3a4dc4fef..71d40aabed 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/it.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/it.json @@ -9,7 +9,7 @@ "UseAnotherServiceToLogin": "Usa un altro servizio per accedere", "UserLockedOutMessage": "L'account utente è stato bloccato a causa di tentativi di accesso non validi. Attendi qualche istante e riprova.", "InvalidUserNameOrPassword": "Username o password non validi!", - "LoginIsNotAllowed": "Non sei autorizzato ad accedere! Devi confermare la tua email / numero di telefono.", + "LoginIsNotAllowed": "Non sei autorizzato ad accedere! Il tuo account non è attivo o deve confermare la tua email/numero di telefono.", "SelfRegistrationDisabledMessage": "L'auto-registrazione è disabilitata per questa applicazione. Contatta l'amministratore dell'applicazione per registrare un nuovo utente.", "LocalLoginDisabledMessage": "L'accesso locale è disabilitato per questa applicazione.", "Login": "Login", diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/nl.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/nl.json index 548d4a4f02..19bc055db9 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/nl.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/nl.json @@ -9,7 +9,7 @@ "UseAnotherServiceToLogin": "Gebruik een andere dienst om in te loggen", "UserLockedOutMessage": "Het gebruikersaccount is geblokkeerd vanwege ongeldige inlogpogingen. Wacht even en probeer het opnieuw.", "InvalidUserNameOrPassword": "Ongeldige gebruikersnaam of wachtwoord!", - "LoginIsNotAllowed": "U mag niet inloggen! U moet uw e-mailadres / telefoonnummer bevestigen.", + "LoginIsNotAllowed": "U mag niet inloggen! Uw account is inactief of moet uw e-mailadres/telefoonnummer bevestigen.", "SelfRegistrationDisabledMessage": "Zelfregistratie is uitgeschakeld voor deze applicatie. Neem contact op met de applicatiebeheerder om een nieuwe gebruiker te registreren.", "LocalLoginDisabledMessage": "Lokale aanmelding is uitgeschakeld voor deze applicatie.", "Login": "Log in", diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/pl-PL.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/pl-PL.json index 032ac41cfa..05927f1efa 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/pl-PL.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/pl-PL.json @@ -9,7 +9,7 @@ "UseAnotherServiceToLogin": "Użyj innej usługi do zalogowania się", "UserLockedOutMessage": "Konto użytkownika zostało zablokowane po nieudanych próbach zalogowania. Odczekaj chwilę i spróbuj ponownie.", "InvalidUserNameOrPassword": "Niepoprawna nazwa użytkownika lub hasło!", - "LoginIsNotAllowed": "Nie jesteś uprawniony do logowania! Musisz potwierdzić swój email/numer telefonu.", + "LoginIsNotAllowed": "Nie możesz się zalogować! Twoje konto jest nieaktywne lub wymaga potwierdzenia adresu e-mail/numeru telefonu.", "SelfRegistrationDisabledMessage": "Rejestracja użytkowników jest wyłączona dla tej aplikacji. Skontaktuj się z administratorem aplikacji w celu rejestracji nowego użytkownika.", "Login": "Zaloguj", "Cancel": "Anuluj", diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/pt-BR.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/pt-BR.json index 9efbc95faa..f1a08b3d90 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/pt-BR.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/pt-BR.json @@ -9,7 +9,7 @@ "UseAnotherServiceToLogin": "Usar outro serviço para entrar", "UserLockedOutMessage": "Esta conta de usuário está bloqueada devido a muitas tentativas de acesso. Por favor, espero alguns instantes e tente novamente.", "InvalidUserNameOrPassword": "Usuário ou senha estão incorretos!", - "LoginIsNotAllowed": "Você não possui permissão para entrar! Você deve confirmar seu e-mail ou número de telefone.", + "LoginIsNotAllowed": "Você não tem permissão para fazer o login! Sua conta está inativa ou precisa confirmar seu e-mail / número de telefone.", "SelfRegistrationDisabledMessage": "Não é permitido que você crie uma nova conta neste site. Contate um administrador para que ele crie uma conta para você.", "Login": "Entrar", "Cancel": "Cancelar", diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/ro-RO.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/ro-RO.json index 909d09f211..71c9fbcdd1 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/ro-RO.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/ro-RO.json @@ -9,7 +9,7 @@ "UseAnotherServiceToLogin": "Folisiţi alt serviciu pentru a vă autentifica", "UserLockedOutMessage": "Contul a fost blocat din cauza incercărilor eşuate de autentificare. Vă rugăm să aşteptaţi şi să încercaţi din nou.", "InvalidUserNameOrPassword": "Nume de utilizator sau parolă invalide!", - "LoginIsNotAllowed": "Nu vă este permis să vă autentificaţi! Trebuie să vă confirmaţi email-ul/numărul de telefon.", + "LoginIsNotAllowed": "Nu ai voie să te autentifici! Contul dvs. este inactiv sau trebuie să vă confirme numărul de e-mail / telefon.", "SelfRegistrationDisabledMessage": "Înregistrarea personală este dezactivată pentru această aplicaţie. Vă rugăm să contactaţi administratorul aplicaţiei pentru a înregistra un nou utilizator.", "LocalLoginDisabledMessage": "Autentificarea locală este dezactivată pentru această aplicaţie.", "Login": "Autentificare", diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/ru.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/ru.json index b278f7fbbc..2722c472ef 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/ru.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/ru.json @@ -9,7 +9,7 @@ "UseAnotherServiceToLogin": "Использовать сторонний сервис для входа", "UserLockedOutMessage": "Пользователь заблокирован из-за большого количества попыток входа. Пожалуйста, попробуйте позднее.", "InvalidUserNameOrPassword": "Неправильные имя пользователя и/или пароль!", - "LoginIsNotAllowed": "Вы не можете войти. Вам необходимо подтвердить электронную почту или телефон.", + "LoginIsNotAllowed": "Вам не разрешено входить в систему! Ваша учетная запись неактивна или вам необходимо подтвердить адрес электронной почты / номер телефона.", "SelfRegistrationDisabledMessage": "Самостоятельная регистрация не предусмотрена. Пожалуйста, свяжитесь с администраром для получения доступа.", "LocalLoginDisabledMessage": "Локальный вход отключен.", "Login": "Войти", diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/sk.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/sk.json index 43846a225a..8ac5e62980 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/sk.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/sk.json @@ -9,7 +9,7 @@ "UseAnotherServiceToLogin": "Použitie inej služby na prihlásenie", "UserLockedOutMessage": "Používateľské konto bolo uzamknuté z dôvodu neplatných pokusov o prihlásenie. Chvíľu počkajte a skúste to znova.", "InvalidUserNameOrPassword": "Neplatné používateľské meno alebo heslo!", - "LoginIsNotAllowed": "Nemáte povolené prihlásiť sa! Musíte potvrdiť svoj email/telefónne číslo.", + "LoginIsNotAllowed": "Nemáte povolenie sa prihlásiť! Váš účet je neaktívny alebo potrebuje potvrdiť váš e -mail/telefónne číslo.", "SelfRegistrationDisabledMessage": "Samostatná registrácia je pre túto aplikáciu vypnutá. Ak chcete zaregistrovať nového používateľa, obráťte sa na správcu aplikácie.", "LocalLoginDisabledMessage": "Lokálne prihlásenie je pre túto aplikáciu zakázané.", "Login": "Prihlásiť", diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/sl.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/sl.json index 7d8457c5a8..6db74f6184 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/sl.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/sl.json @@ -9,7 +9,7 @@ "UseAnotherServiceToLogin": "Uporabi drugo storitev za prijavo", "UserLockedOutMessage": "Uporabniški račun je bil zaklenjen zaradi neveljavnih poskusov prijave. Počakajte nekaj časa in poskusite znova.", "InvalidUserNameOrPassword": "Napačno uporabniško ime ali geslo!", - "LoginIsNotAllowed": "Nimate dovoljenja za prijavo! Potrditi morate e-poštni naslov/telefonsko številko.", + "LoginIsNotAllowed": "Ne smete se prijaviti! Vaš račun je neaktiven ali mora potrditi vaš e -poštni naslov/telefonsko številko.", "SelfRegistrationDisabledMessage": "Možnost lastne registracije uporabnika je onemogočena za to aplikacijo. Kontaktirajte skrbnika aplikacije, da registrirate novega uporabnika.", "LocalLoginDisabledMessage": "Lokalna prijava za to aplikacijo je onemogočena.", "Login": "Prijava", diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/tr.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/tr.json index 2dc74572c9..f9b545b021 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/tr.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/tr.json @@ -9,7 +9,7 @@ "UseAnotherServiceToLogin": "Başka bir servisle giriş yap", "UserLockedOutMessage": "Kullanıcı hesabı hatalı giriş denemeleri nedeniyle kilitlenmiştir. Lütfen bir süre bekleyip tekrar deneyin.", "InvalidUserNameOrPassword": "Kullanıcı adı ya da şifre geçersiz!", - "LoginIsNotAllowed": "Giriş yapamazsınız! E-posta adresinizi ya da telefon numaranızı doğrulamanız gerekiyor.", + "LoginIsNotAllowed": "Giriş yapmanıza izin verilmiyor! Hesabınız etkin değil veya e-postanızı/telefon numaranızı onaylamanız gerekiyor.", "SelfRegistrationDisabledMessage": "Bu uygulama için kullanıcıların kendi kendilerine kaydolmaları engellenmiştir. Yeni bir kullanıcı kaydetmek için lütfen uygulama yöneticisi ile iletişime geçin.", "LocalLoginDisabledMessage": "Bu uygulama için local login devre dışı bırakılmıştır.", "Login": "Giriş yap", diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/vi.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/vi.json index 56d436c1cd..9b5c9b5c42 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/vi.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/vi.json @@ -9,7 +9,7 @@ "UseAnotherServiceToLogin": "Sử dụng dịch vụ khác để đăng nhập", "UserLockedOutMessage": "Tài khoản người dùng đã bị khóa do các nỗ lực đăng nhập không hợp lệ. Xin vui lòng chờ một lúc và thử lại.", "InvalidUserNameOrPassword": "Sai tên tài khoản hoặc mật khẩu!", - "LoginIsNotAllowed": "Bạn không được phép đăng nhập! Bạn cần xác nhận email/số điện thoại của bạn.", + "LoginIsNotAllowed": "Bạn không được phép đăng nhập! Tài khoản của bạn không hoạt động hoặc cần xác nhận email / số điện thoại của bạn.", "SelfRegistrationDisabledMessage": "Tự đăng ký người dùng bị vô hiệu hóa cho ứng dụng này. Liên hệ với quản trị viên ứng dụng để đăng ký người dùng mới.", "Login": "Đăng nhập", "Cancel": "Hủy bỏ", diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/zh-Hans.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/zh-Hans.json index 7f3939c502..ffb6730e22 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/zh-Hans.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/zh-Hans.json @@ -9,7 +9,7 @@ "UseAnotherServiceToLogin": "使用另一个服务登录", "UserLockedOutMessage": "登录失败,用户账户已被锁定.请稍后再试.", "InvalidUserNameOrPassword": "用户名或密码错误!", - "LoginIsNotAllowed": "无法登录!你需要验证邮箱地址/手机号.", + "LoginIsNotAllowed": "无法登录!你的账号未激活或者需要验证邮箱地址/手机号.", "SelfRegistrationDisabledMessage": "应用程序未开放注册,请联系管理员添加新用户.", "LocalLoginDisabledMessage": "应用程序未开放本地账户登录.", "Login": "登录", diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/zh-Hant.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/zh-Hant.json index 36e84e1b9c..6e69fc9093 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/zh-Hant.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/zh-Hant.json @@ -9,7 +9,7 @@ "UseAnotherServiceToLogin": "使用另一個服務登入", "UserLockedOutMessage": "登入失敗,使用者帳號已被鎖定.請稍後再試.", "InvalidUserNameOrPassword": "使用者名稱或密碼錯誤!", - "LoginIsNotAllowed": "無法登入!你需要驗證電子信箱地址/手機號碼.", + "LoginIsNotAllowed": "無法登入!你的賬號未激活或者需要驗證郵箱地址/手機號碼.", "SelfRegistrationDisabledMessage": "應用程式未開放註冊,請聯絡管理員以加入新使用者.", "LocalLoginDisabledMessage": "應用程序未開放本地賬戶登錄.", "Login": "登入", diff --git a/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityUserCreateOrUpdateDtoBase.cs b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityUserCreateOrUpdateDtoBase.cs index e2fe874dbd..3b6959b60c 100644 --- a/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityUserCreateOrUpdateDtoBase.cs +++ b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityUserCreateOrUpdateDtoBase.cs @@ -26,6 +26,8 @@ namespace Volo.Abp.Identity [DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxPhoneNumberLength))] public string PhoneNumber { get; set; } + public bool IsActive { get; set; } + public bool LockoutEnabled { get; set; } [CanBeNull] diff --git a/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityUserDto.cs b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityUserDto.cs index f7291a4e82..f3b03ab8dc 100644 --- a/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityUserDto.cs +++ b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityUserDto.cs @@ -23,6 +23,8 @@ namespace Volo.Abp.Identity public bool PhoneNumberConfirmed { get; set; } + public bool IsActive { get; set; } + public bool LockoutEnabled { get; set; } public DateTimeOffset? LockoutEnd { get; set; } diff --git a/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/IdentityUserAppService.cs b/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/IdentityUserAppService.cs index 351059a305..e380ffa0d0 100644 --- a/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/IdentityUserAppService.cs +++ b/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/IdentityUserAppService.cs @@ -178,7 +178,7 @@ namespace Volo.Abp.Identity user.Name = input.Name; user.Surname = input.Surname; (await UserManager.UpdateAsync(user)).CheckErrors(); - + user.SetIsActive(input.IsActive); if (input.RoleNames != null) { (await UserManager.SetRolesAsync(user, input.RoleNames)).CheckErrors(); diff --git a/modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpSignInManager.cs b/modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpSignInManager.cs index 8de9014cbe..fc88c33363 100644 --- a/modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpSignInManager.cs +++ b/modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpSignInManager.cs @@ -33,7 +33,7 @@ namespace Volo.Abp.Identity.AspNetCore AbpOptions = options.Value; } - public async override Task PasswordSignInAsync( + public override async Task PasswordSignInAsync( string userName, string password, bool isPersistent, @@ -62,5 +62,16 @@ namespace Volo.Abp.Identity.AspNetCore return await base.PasswordSignInAsync(userName, password, isPersistent, lockoutOnFailure); } + + protected override async Task PreSignInCheck(IdentityUser user) + { + if (!user.IsActive) + { + Logger.LogWarning("User is currently inactive."); + return SignInResult.NotAllowed; + } + + return await base.PreSignInCheck(user); + } } } diff --git a/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/UserManagement.razor b/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/UserManagement.razor index 17d24c1d9b..2f632422c1 100644 --- a/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/UserManagement.razor +++ b/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/UserManagement.razor @@ -110,6 +110,9 @@ + + @L["DisplayName:IsActive"] + @L["DisplayName:LockoutEnabled"] @@ -221,6 +224,9 @@ + + @L["DisplayName:IsActive"] + @L["DisplayName:LockoutEnabled"] @@ -254,4 +260,4 @@ @if ( HasManagePermissionsPermission ) { -} \ No newline at end of file +} diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en.json index 68f4318991..642bede8d6 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en.json @@ -25,6 +25,7 @@ "DisplayName:Email": "Email address", "DisplayName:PhoneNumber": "Phone number", "DisplayName:TwoFactorEnabled": "Two factor verification", + "DisplayName:IsActive": "Active", "DisplayName:LockoutEnabled": "Lock account after failed login attempts", "NewRole": "New role", "RoleName": "Role name", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/tr.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/tr.json index 2ad19c80f4..177e696bab 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/tr.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/tr.json @@ -25,6 +25,7 @@ "DisplayName:Email": "E-posta adresi", "DisplayName:PhoneNumber": "Telefon numarası", "DisplayName:TwoFactorEnabled": "İki aşamalı doğrulama", + "DisplayName:IsActive": "Aktif", "DisplayName:LockoutEnabled": "Başarısız giriş denemeleri sonrası hesabı kilitleme", "NewRole": "Yeni rol", "RoleName": "Rol adı", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/zh-Hans.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/zh-Hans.json index ec3c4dbbb8..35fae96839 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/zh-Hans.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/zh-Hans.json @@ -25,6 +25,7 @@ "DisplayName:Email": "邮箱地址", "DisplayName:PhoneNumber": "手机号码", "DisplayName:TwoFactorEnabled": "二次认证", + "DisplayName:IsActive": "启用", "DisplayName:LockoutEnabled": "登录失败,账户被锁定", "NewRole": "新角色", "RoleName": "角色名称", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/zh-Hant.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/zh-Hant.json index 54298f530d..06f72cd5d0 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/zh-Hant.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/zh-Hant.json @@ -25,6 +25,7 @@ "DisplayName:Email": "電子信箱地址", "DisplayName:PhoneNumber": "手機號碼", "DisplayName:TwoFactorEnabled": "二次認證", + "DisplayName:IsActive": "啟用", "DisplayName:LockoutEnabled": "登入失敗,帳號被鎖定", "NewRole": "新角色", "RoleName": "角色名稱", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs index f48553681c..befa288fda 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs @@ -82,6 +82,11 @@ namespace Volo.Abp.Identity /// True if the telephone number has been confirmed, otherwise false. public virtual bool PhoneNumberConfirmed { get; protected internal set; } + /// + /// Gets or sets a flag indicating if the user is active. + /// + public virtual bool IsActive { get; protected internal set; } + /// /// Gets or sets a flag indicating if two factor authentication is enabled for this user. /// @@ -155,6 +160,7 @@ namespace Volo.Abp.Identity NormalizedEmail = email.ToUpperInvariant(); ConcurrencyStamp = Guid.NewGuid().ToString(); SecurityStamp = Guid.NewGuid().ToString(); + IsActive = true; Roles = new Collection(); Claims = new Collection(); @@ -338,11 +344,6 @@ namespace Volo.Abp.Identity PhoneNumberConfirmed = confirmed; } - public override string ToString() - { - return $"{base.ToString()}, UserName = {UserName}"; - } - /// /// Normally use to change the phone number /// in the application code. @@ -356,5 +357,15 @@ namespace Volo.Abp.Identity PhoneNumber = phoneNumber; PhoneNumberConfirmed = !phoneNumber.IsNullOrWhiteSpace() && confirmed; } + + public virtual void SetIsActive(bool isActive) + { + IsActive = isActive; + } + + public override string ToString() + { + return $"{base.ToString()}, UserName = {UserName}"; + } } } diff --git a/modules/identity/src/Volo.Abp.Identity.HttpApi.Client/Volo/Abp/Identity/IdentityUserDtoExtensions.cs b/modules/identity/src/Volo.Abp.Identity.HttpApi.Client/Volo/Abp/Identity/IdentityUserDtoExtensions.cs index bdb1e9044e..8c90fe5f73 100644 --- a/modules/identity/src/Volo.Abp.Identity.HttpApi.Client/Volo/Abp/Identity/IdentityUserDtoExtensions.cs +++ b/modules/identity/src/Volo.Abp.Identity.HttpApi.Client/Volo/Abp/Identity/IdentityUserDtoExtensions.cs @@ -15,7 +15,8 @@ namespace Volo.Abp.Identity user.EmailConfirmed, user.PhoneNumber, user.PhoneNumberConfirmed, - user.TenantId + user.TenantId, + user.IsActive ); } } diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/CreateModal.cshtml b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/CreateModal.cshtml index 1aa5669b0c..2deaf0a9da 100644 --- a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/CreateModal.cshtml +++ b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/CreateModal.cshtml @@ -27,6 +27,7 @@ + @foreach (var propertyInfo in ObjectExtensionManager.Instance.GetProperties()) diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/CreateModal.cshtml.cs b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/CreateModal.cshtml.cs index 03bbd859cc..c239ac2e48 100644 --- a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/CreateModal.cshtml.cs +++ b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/CreateModal.cshtml.cs @@ -79,6 +79,8 @@ namespace Volo.Abp.Identity.Web.Pages.Identity.Users [DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxPhoneNumberLength))] public string PhoneNumber { get; set; } + public bool IsActive { get; set; } = true; + public bool LockoutEnabled { get; set; } = true; } diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/EditModal.cshtml b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/EditModal.cshtml index 5bac90712e..b95068cd20 100644 --- a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/EditModal.cshtml +++ b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/EditModal.cshtml @@ -27,6 +27,7 @@ + @foreach (var propertyInfo in ObjectExtensionManager.Instance.GetProperties()) diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/EditModal.cshtml.cs b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/EditModal.cshtml.cs index 29d044f9da..25affb88a3 100644 --- a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/EditModal.cshtml.cs +++ b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/EditModal.cshtml.cs @@ -87,6 +87,8 @@ namespace Volo.Abp.Identity.Web.Pages.Identity.Users [DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxPhoneNumberLength))] public string PhoneNumber { get; set; } + public bool IsActive { get; set; } + public bool LockoutEnabled { get; set; } } diff --git a/modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/AbpSignInManager_Tests.cs b/modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/AbpSignInManager_Tests.cs index dc5d961f9a..b1b3368e5b 100644 --- a/modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/AbpSignInManager_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/AbpSignInManager_Tests.cs @@ -35,5 +35,15 @@ namespace Volo.Abp.Identity.AspNetCore result.ShouldBe("Failed"); } + + [Fact] + public async Task Should_Not_SignIn_If_User_Not_Active() + { + var result = await GetResponseAsStringAsync( + "api/signin-test/password?userName=bob&password=1q2w3E*" + ); + + result.ShouldBe("NotAllowed"); + } } } diff --git a/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/AbpIdentityTestDataBuilder.cs b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/AbpIdentityTestDataBuilder.cs index 708deaa68e..a6e0f0c310 100644 --- a/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/AbpIdentityTestDataBuilder.cs +++ b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/AbpIdentityTestDataBuilder.cs @@ -12,6 +12,7 @@ namespace Volo.Abp.Identity { private readonly IGuidGenerator _guidGenerator; private readonly IIdentityUserRepository _userRepository; + private readonly IdentityUserManager _userManager; private readonly IIdentityClaimTypeRepository _identityClaimTypeRepository; private readonly IIdentityRoleRepository _roleRepository; private readonly IOrganizationUnitRepository _organizationUnitRepository; @@ -32,6 +33,7 @@ namespace Volo.Abp.Identity public AbpIdentityTestDataBuilder( IGuidGenerator guidGenerator, IIdentityUserRepository userRepository, + IdentityUserManager userManager, IIdentityClaimTypeRepository identityClaimTypeRepository, IIdentityRoleRepository roleRepository, IOrganizationUnitRepository organizationUnitRepository, @@ -44,6 +46,7 @@ namespace Volo.Abp.Identity { _guidGenerator = guidGenerator; _userRepository = userRepository; + _userManager = userManager; _identityClaimTypeRepository = identityClaimTypeRepository; _roleRepository = roleRepository; _lookupNormalizer = lookupNormalizer; @@ -133,6 +136,10 @@ namespace Volo.Abp.Identity neo.AddClaim(_guidGenerator, new Claim("TestClaimType", "43")); neo.AddOrganizationUnit(_ou111.Id); await _userRepository.InsertAsync(neo); + + var bob = new IdentityUser(_testData.UserBobId, "bob", "bob@abp.io"); + bob.SetIsActive(false); + await _userManager.CreateAsync(bob, "1q2w3E*"); } private async Task AddLinkUsers() diff --git a/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/IdentityTestData.cs b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/IdentityTestData.cs index 10fcce89af..d2cb0f19b4 100644 --- a/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/IdentityTestData.cs +++ b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/IdentityTestData.cs @@ -10,6 +10,7 @@ namespace Volo.Abp.Identity public Guid UserJohnId { get; } = Guid.NewGuid(); public Guid UserDavidId { get; } = Guid.NewGuid(); public Guid UserNeoId { get; } = Guid.NewGuid(); + public Guid UserBobId { get; } = Guid.NewGuid(); public Guid AgeClaimId { get; } = Guid.NewGuid(); public Guid EducationClaimId { get; } = Guid.NewGuid(); } diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/FR.json b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/FR.json index 77ad4b10b5..406094d58a 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/FR.json +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/FR.json @@ -7,7 +7,7 @@ "Volo.IdentityServer:DuplicateClientId": "ClientId existe déjà: {ClientId}", "UserLockedOut": "Le compte utilisateur a été verrouillé en raison de tentatives de connexion non valides. Veuillez patienter un instant et réessayer.", "InvalidUserNameOrPassword": "Nom d'utilisateur ou mot de passe invalide!", - "LoginIsNotAllowed": "Vous n'êtes pas autorisé à vous connecter! Vous devez confirmer votre adresse e-mail / numéro de téléphone.", + "LoginIsNotAllowed": "Vous n'êtes pas autorisé à vous connecter ! Votre compte est inactif ou doit confirmer votre e-mail/numéro de téléphone.", "InvalidUsername": "Nom d'utilisateur ou mot de passe invalide!", "TheTargetUserIsNotLinkedToYou": "L'utilisateur cible n'est pas lié à vous!" } diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/ar.json b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/ar.json index b228280c52..85eb99bc1d 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/ar.json +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/ar.json @@ -6,7 +6,7 @@ "Volo.IdentityServer:DuplicateClientId": "موجود بالفعل: {ClientId}", "UserLockedOut": "تم قفل حساب المستخدم بسبب محاولات تسجيل الدخول غير الصالحة. يرجى الانتظار بعض الوقت والمحاولة مرة أخرى.", "InvalidUserNameOrPassword": "اسم مستخدم أو كلمة مرور غير صالحة!", - "LoginIsNotAllowed": "غير مسموح لك بتسجيل الدخول! أنت بحاجة إلى تأكيد بريدك الإلكتروني / رقم هاتفك.", + "LoginIsNotAllowed": "لا يسمح لك بتسجيل الدخول! حسابك غير نشط أو يحتاج إلى تأكيد بريدك الإلكتروني / رقم هاتفك.", "InvalidUsername": "اسم المستخدم أو كلمة المرور غير صالحة!" } } \ No newline at end of file diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/cs.json b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/cs.json index bee3e74fd9..97f3661f39 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/cs.json +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/cs.json @@ -6,7 +6,7 @@ "Volo.IdentityServer:DuplicateClientId": "ClientId již existuje: {ClientId}", "UserLockedOut": "Tento uživatelský účet byl zablokován kvůli neplatným pokusům o přihlášení. Chvilku počkejte a zkuste to znovu.", "InvalidUserNameOrPassword": "Neplatné uživatelské jméno či heslo!", - "LoginIsNotAllowed": "Nemáte oprávnění se přihlásit! Musíte potvrdit svůj email/telefonní číslo.", + "LoginIsNotAllowed": "Nemáte oprávnění se přihlásit! Váš účet je neaktivní nebo potřebuje potvrdit váš e -mail/telefonní číslo.", "InvalidUsername": "Neplatné uživatelské jméno či heslo!" } } diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/de-DE.json b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/de-DE.json index bbb835af15..2d419907cc 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/de-DE.json +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/de-DE.json @@ -7,7 +7,7 @@ "Volo.IdentityServer:DuplicateClientId": "ClientId existiert bereits: {ClientId}", "UserLockedOut": "Das Benutzerkonto wurde aufgrund ungültiger Anmeldeversuche gesperrt. Bitte warten Sie eine Weile und versuchen Sie es erneut.", "InvalidUserNameOrPassword": "Ungültiger Benutzername oder Passwort!", - "LoginIsNotAllowed": "Sie dürfen sich nicht anmelden! Sie müssen Ihre E-Mail-Adresse / Telefonnummer bestätigen.", + "LoginIsNotAllowed": "Sie dürfen sich nicht anmelden! Ihr Konto ist inaktiv oder muss Ihre E-Mail-/Telefonnummer bestätigen.", "InvalidUsername": "Ungültiger Benutzername oder Passwort!", "TheTargetUserIsNotLinkedToYou": "Der Zielbenutzer ist nicht mit Ihnen verknüpft!" } diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/de.json b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/de.json index 68e2cde8b8..8154b4375a 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/de.json +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/de.json @@ -6,7 +6,7 @@ "Volo.IdentityServer:DuplicateClientId": "ClientId bereits vorhanden: {ClientId}", "UserLockedOut": "Das Benutzerkonto wurde aufgrund ungültiger Anmeldeversuche ausgesperrt. Bitte warten Sie eine Weile und versuchen Sie es erneut.", "InvalidUserNameOrPassword": "Ungültiger Benutzername oder Passwort!", - "LoginIsNotAllowed": "Sie dürfen sich nicht anmelden! Sie müssen Ihre E-Mail/Telefonnummer bestätigen.", + "LoginIsNotAllowed": "Sie dürfen sich nicht anmelden! Ihr Konto ist inaktiv oder muss Ihre E-Mail-/Telefonnummer bestätigen.", "InvalidUsername": "Ungültiger Benutzername oder Passwort!" } } \ No newline at end of file diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/en-GB.json b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/en-GB.json index 7c3c87b884..173379249c 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/en-GB.json +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/en-GB.json @@ -7,7 +7,7 @@ "Volo.IdentityServer:DuplicateClientId": "ClientId already exist: {ClientId}", "UserLockedOut": "The user account has been locked out due to invalid login attempts. Please wait a while and try again.", "InvalidUserNameOrPassword": "Invalid username or password!", - "LoginIsNotAllowed": "You are not allowed to login! You need to confirm your email/phone number.", + "LoginIsNotAllowed": "You are not allowed to login! Your account is inactive or needs to confirm your email/phone number.", "InvalidUsername": "Invalid username or password!", "TheTargetUserIsNotLinkedToYou": "The target user is not linked to you!" } diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/en.json b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/en.json index 31a8ebad04..e756db2877 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/en.json +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/en.json @@ -7,7 +7,7 @@ "Volo.IdentityServer:DuplicateClientId": "ClientId already exist: {ClientId}", "UserLockedOut": "The user account has been locked out due to invalid login attempts. Please wait a while and try again.", "InvalidUserNameOrPassword": "Invalid username or password!", - "LoginIsNotAllowed": "You are not allowed to login! You need to confirm your email/phone number.", + "LoginIsNotAllowed": "You are not allowed to login! Your account is inactive or needs to confirm your email/phone number.", "InvalidUsername": "Invalid username or password!", "InvalidAuthenticatorCode": "Invalid authenticator code!", "TheTargetUserIsNotLinkedToYou": "The target user is not linked to you!" diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/es.json b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/es.json index 7a21c35184..2a2515bd97 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/es.json +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/es.json @@ -7,7 +7,7 @@ "Volo.IdentityServer:DuplicateClientId": "ClientId ya existe: {ClientId}", "UserLockedOut": "La cuenta de usuario ha sido bloqueada debido a inicios de sesión no validos. Por favor, espera un momento e intentalo de nuevo.", "InvalidUserNameOrPassword": "Nombre de usuario o contraseña incorrecto!", - "LoginIsNotAllowed": "No puedes iniciar sesión!, necesitas confirmar tu e-mail/ número de teléfono.", + "LoginIsNotAllowed": "¡No está permitido iniciar sesión! Su cuenta está inactiva o necesita confirmar su correo electrónico / número de teléfono.", "InvalidUsername": "Nombre de usuario icorrecto", "TheTargetUserIsNotLinkedToYou": "El usuario de destino no está asociado a usted." } diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/fi.json b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/fi.json index 21687921a9..bfb746e632 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/fi.json +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/fi.json @@ -7,7 +7,7 @@ "Volo.IdentityServer:DuplicateClientId": "ClientId on jo olemassa: {ClientId}", "UserLockedOut": "Käyttäjätili on lukittu virheellisten kirjautumisyritysten vuoksi. Odota hetki ja yritä uudelleen.", "InvalidUserNameOrPassword": "Väärä käyttäjänimi tai salasana!", - "LoginIsNotAllowed": "Et saa kirjautua sisään! Sinun on vahvistettava sähköpostiosoitteesi / puhelinnumerosi.", + "LoginIsNotAllowed": "Et saa kirjautua sisään! Tilisi on passiivinen tai sinun on vahvistettava sähköpostiosoitteesi/puhelinnumerosi.", "InvalidUsername": "Väärä käyttäjänimi tai salasana!", "TheTargetUserIsNotLinkedToYou": "Kohdekäyttäjä ei ole linkitetty sinuun!" } diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/hi.json b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/hi.json index 2daea29000..cf612a909b 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/hi.json +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/hi.json @@ -7,7 +7,7 @@ "Volo.IdentityServer:DuplicateClientId": "ClientId पहले से मौजूद है: {ClientId}", "UserLockedOut": "अमान्य लॉगिन प्रयासों के कारण उपयोगकर्ता खाता बंद कर दिया गया है। कृपया थोड़ी देर प्रतीक्षा करें और पुन: प्रयास करें।", "InvalidUserNameOrPassword": "अमान्य उपयोगकर्ता नाम या पासवर्ड!", - "LoginIsNotAllowed": "आपको लॉगिन करने की अनुमति नहीं है! आपको अपने ईमेल / फोन नंबर की पुष्टि करनी होगी।", + "LoginIsNotAllowed": "आपको लॉगिन करने की अनुमति नहीं है! आपका खाता निष्क्रिय है या आपके ईमेल/फ़ोन नंबर की पुष्टि करने की आवश्यकता है।", "InvalidUsername": "अमान्य उपयोगकर्ता नाम या पासवर्ड!", "TheTargetUserIsNotLinkedToYou": "लक्ष्य उपयोगकर्ता आपसे जुड़ा नहीं है!" } diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/hu.json b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/hu.json index e4109a2ba7..5bd3a2676a 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/hu.json +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/hu.json @@ -6,7 +6,7 @@ "Volo.IdentityServer:DuplicateClientId": "ClientId már létezik: {ClientId}", "UserLockedOut": "A felhasználói fiókot érvénytelen bejelentkezési kísérletek miatt zároltuk. Kérjük, várjon egy kicsit, és próbálja újra.", "InvalidUserNameOrPassword": "Érvénytelen felhasználónév vagy jelszó!", - "LoginIsNotAllowed": "Ön nem léphet be! Meg kell erősítenie e-mail címét / telefonszámát.", + "LoginIsNotAllowed": "A bejelentkezés nem engedélyezett! Fiókja inaktív, vagy meg kell erősítenie e -mail címét/telefonszámát.", "InvalidUsername": "Érvénytelen felhasználónév vagy jelszó!", "TheTargetUserIsNotLinkedToYou": "A célfelhasználó nincs hozzád kapcsolódva!" } diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/it.json b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/it.json index 2b564f3af7..cde4f688f4 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/it.json +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/it.json @@ -7,7 +7,7 @@ "Volo.IdentityServer:DuplicateClientId": "ClientId già esistente: {ClientId}", "UserLockedOut": "L'account utente è stato bloccato a causa di tentativi di accesso non validi. Attendi qualche istante e riprova.", "InvalidUserNameOrPassword": "Username o password non validi!", - "LoginIsNotAllowed": "Non sei autorizzato ad accedere! Devi confermare la tua email/numero di telefono.", + "LoginIsNotAllowed": "Non sei autorizzato ad accedere! Il tuo account non è attivo o deve confermare la tua email/numero di telefono.", "InvalidUsername": "Username o password non validi!", "InvalidAuthenticatorCode": "Codice autenticatore non valido!", "TheTargetUserIsNotLinkedToYou": "L'utente di destinazione non è collegato a te!" diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/nl.json b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/nl.json index 9b6943c54f..bcce8f1e55 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/nl.json +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/nl.json @@ -7,7 +7,7 @@ "Volo.IdentityServer:DuplicateClientId": "ClientId bestaat al: {ClientId}", "UserLockedOut": "Het gebruikersaccount is geblokkeerd vanwege ongeldige inlogpogingen. Wacht even en probeer het opnieuw.", "InvalidUserNameOrPassword": "ongeldige gebruikersnaam of wachtwoord!", - "LoginIsNotAllowed": "U mag niet inloggen! U moet uw e-mailadres / telefoonnummer bevestigen.", + "LoginIsNotAllowed": "U mag niet inloggen! Uw account is inactief of moet uw e-mailadres/telefoonnummer bevestigen.", "InvalidUsername": "Ongeldige gebruikersnaam of wachtwoord!", "TheTargetUserIsNotLinkedToYou": "De beoogde gebruiker is niet aan jou gekoppeld!" } diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/ro-RO.json b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/ro-RO.json index 7917e7118c..7841a1df8a 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/ro-RO.json +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/ro-RO.json @@ -7,7 +7,7 @@ "Volo.IdentityServer:DuplicateClientId": "Id-ul de client există deja: {ClientId}", "UserLockedOut": "Contul de utilizator a fost blocat din cauza încercărilor de autentificare eşuate. Vă rugăm să aşteptaţi puţin şi după să încercaţi din nou.", "InvalidUserNameOrPassword": "Nume de utilizator sau parolă invalidă!", - "LoginIsNotAllowed": "Nu vă este permisă autentificarea! Trebuie să vă confirmaţi emailul/numărul de telefon.", + "LoginIsNotAllowed": "Nu ai voie să te autentifici! Contul dvs. este inactiv sau trebuie să vă confirme numărul de e-mail / telefon.", "InvalidUsername": "Nume de utilizator sau parolă invalidă!", "InvalidAuthenticatorCode": "Cod de autentificare invalid!", "TheTargetUserIsNotLinkedToYou": "Utilizatorul ţintă nu este conectat la dumneavoastră!" diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/ru.json b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/ru.json index 808962d8e5..5710bc16e3 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/ru.json +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/ru.json @@ -6,7 +6,7 @@ "Volo.IdentityServer:DuplicateClientId": "Параметр ClientID уже существует: {ClientId}", "UserLockedOut": "Учетная запись пользователя была заблокирована из-за неудачных попыток входа в систему. Пожалуйста, попробуйте позже.", "InvalidUserNameOrPassword": "Неверное имя пользователя или пароль!", - "LoginIsNotAllowed": "У вас нет разрешения на вход в систему. Необходимо подтвердить свой адрес электронной почты/номер телефона.", + "LoginIsNotAllowed": "Вам не разрешено входить в систему! Ваша учетная запись неактивна или вам необходимо подтвердить адрес электронной почты / номер телефона.", "InvalidUsername": "Неверное имя пользователя или пароль!" } } diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/sk.json b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/sk.json index 744a92ac1d..18435aaae8 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/sk.json +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/sk.json @@ -7,7 +7,7 @@ "Volo.IdentityServer:DuplicateClientId": "ClientId už existuje: {ClientId}", "UserLockedOut": "Používateľské konto bolo uzamknuté z dôvodu viacerých neplatných pokusov o prihlásenie. Chvíľu počkajte a skúste sa prihlásiť znova.", "InvalidUserNameOrPassword": "Nesprávne používateľské meno alebo heslo!", - "LoginIsNotAllowed": "Nemáte povolené prihlásiť sa! Musíte potvrdiť svoj email/telefónne číslo.", + "LoginIsNotAllowed": "Nemáte povolenie sa prihlásiť! Váš účet je neaktívny alebo potrebuje potvrdiť váš e -mail/telefónne číslo.", "InvalidUsername": "Nesprávne používateľské meno alebo heslo!", "TheTargetUserIsNotLinkedToYou": "Cieľový používateľ nie je s vami prepojený!" } diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/sl.json b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/sl.json index b73f64b00e..c5f2dc73de 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/sl.json +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/sl.json @@ -6,7 +6,7 @@ "Volo.IdentityServer:DuplicateClientId": "ClientId že obstaja: {ClientId}", "UserLockedOut": "Uporabniški račun je bil blokiran zaradi neveljavnih poskusov prijave. Počakajte nekaj časa in poskusite znova.", "InvalidUserNameOrPassword": "Napačno uporabniško ime ali geslo!", - "LoginIsNotAllowed": "Nimate dovoljenja za prijavo! Potrditi morate svojo e-pošto / telefonsko številko.", + "LoginIsNotAllowed": "Ne smete se prijaviti! Vaš račun je neaktiven ali mora potrditi vaš e -poštni naslov/telefonsko številko.", "InvalidUsername": "Napačno uporabniško ime ali geslo!" } } \ No newline at end of file diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/tr.json b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/tr.json index b5c072c7e6..08178cd306 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/tr.json +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/tr.json @@ -6,7 +6,7 @@ "Volo.IdentityServer:DuplicateClientId": "ClientId already zaten mevcut: {ClientId}", "UserLockedOut": "Kullanıcı hesabı hatalı giriş denemeleri nedeniyle kilitlenmiştir. Lütfen bir süre bekleyip tekrar deneyin.", "InvalidUserNameOrPassword": "Kullanıcı adı ya da şifre geçersiz!", - "LoginIsNotAllowed": "Giriş yapamazsınız! E-posta adresinizi ya da telefon numaranızı doğrulamanız gerekiyor.", + "LoginIsNotAllowed": "Giriş yapmanıza izin verilmiyor! Hesabınız etkin değil veya e-postanızı/telefon numaranızı onaylamanız gerekiyor.", "InvalidUsername": "Kullanıcı adı ya da şifre geçersiz!", "InvalidAuthenticatorCode": "Geçersiz kimlik doğrulama kodu!", "TheTargetUserIsNotLinkedToYou": "Hedef kullanıcı sizinle bağlantılı değil!" diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/zh-Hans.json b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/zh-Hans.json index 7b90b802e7..20bc8b43f0 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/zh-Hans.json +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/zh-Hans.json @@ -7,7 +7,7 @@ "Volo.IdentityServer:DuplicateClientId": "ClientId已经存在: {ClientId}", "UserLockedOut": "登录失败,用户账户已被锁定.请稍后再试.", "InvalidUserNameOrPassword": "用户名或密码错误!", - "LoginIsNotAllowed": "无法登录!你需要验证邮箱地址/手机号.", + "LoginIsNotAllowed": "无法登录!你的账号未激活或者需要验证邮箱地址/手机号.", "InvalidUsername": "用户名或密码错误!", "InvalidAuthenticatorCode": "验证码无效!", "TheTargetUserIsNotLinkedToYou": "目标用户未和你有关联!" diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/zh-Hant.json b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/zh-Hant.json index 0ffeae8f81..bf4341055e 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/zh-Hant.json +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/zh-Hant.json @@ -6,7 +6,7 @@ "Volo.IdentityServer:DuplicateClientId": "ClientId已經存在: {ClientId}", "UserLockedOut": "登錄失敗,用戶賬戶已被鎖定.請稍後再試.", "InvalidUserNameOrPassword": "用戶名或密碼錯誤!", - "LoginIsNotAllowed": "無法登錄!妳需要驗證郵箱地址/手機號.", + "LoginIsNotAllowed": "無法登入!你的賬號未激活或者需要驗證郵箱地址/手機號碼.", "InvalidUsername": "用戶名或密碼錯誤!" } } \ No newline at end of file diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpProfileService.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpProfileService.cs index 224abc6c10..e09315c69f 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpProfileService.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpProfileService.cs @@ -40,5 +40,11 @@ namespace Volo.Abp.IdentityServer.AspNetIdentity await base.IsActiveAsync(context); } } + + [UnitOfWork] + public override Task IsUserActiveAsync(IdentityUser user) + { + return Task.FromResult(user.IsActive); + } } } From 439b4ec2d25de0d22ce244874ef9cc6385dea62a Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 9 Sep 2021 13:28:05 +0800 Subject: [PATCH 12/49] Update migrations for templates. --- ...igner.cs => 20210909052638_Initial.Designer.cs} | 14 +++++--------- ...091011_Initial.cs => 20210909052638_Initial.cs} | 1 + .../MyProjectNameDbContextModelSnapshot.cs | 12 ++++-------- ...igner.cs => 20210909052730_Initial.Designer.cs} | 7 +++++-- ...093547_Initial.cs => 20210909052730_Initial.cs} | 1 + .../Migrations/UnifiedDbContextModelSnapshot.cs | 5 ++++- ...igner.cs => 20210909052712_Initial.Designer.cs} | 7 +++++-- ...093513_Initial.cs => 20210909052712_Initial.cs} | 1 + ...tyServerHostMigrationsDbContextModelSnapshot.cs | 5 ++++- ...igner.cs => 20210909052706_Initial.Designer.cs} | 7 +++++-- ...093522_Initial.cs => 20210909052706_Initial.cs} | 1 + .../Migrations/UnifiedDbContextModelSnapshot.cs | 5 ++++- 12 files changed, 40 insertions(+), 26 deletions(-) rename templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/{20210615091011_Initial.Designer.cs => 20210909052638_Initial.Designer.cs} (99%) rename templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/{20210615091011_Initial.cs => 20210909052638_Initial.cs} (99%) rename templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/{20210528093547_Initial.Designer.cs => 20210909052730_Initial.Designer.cs} (99%) rename templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/{20210528093547_Initial.cs => 20210909052730_Initial.cs} (99%) rename templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/Migrations/{20210528093513_Initial.Designer.cs => 20210909052712_Initial.Designer.cs} (99%) rename templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/Migrations/{20210528093513_Initial.cs => 20210909052712_Initial.cs} (99%) rename templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/{20210528093522_Initial.Designer.cs => 20210909052706_Initial.Designer.cs} (99%) rename templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/{20210528093522_Initial.cs => 20210909052706_Initial.cs} (99%) diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20210615091011_Initial.Designer.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20210909052638_Initial.Designer.cs similarity index 99% rename from templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20210615091011_Initial.Designer.cs rename to templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20210909052638_Initial.Designer.cs index 060cb48e8a..1c6326a5b6 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20210615091011_Initial.Designer.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20210909052638_Initial.Designer.cs @@ -11,7 +11,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Migrations { [DbContext(typeof(MyProjectNameDbContext))] - [Migration("20210615091011_Initial")] + [Migration("20210909052638_Initial")] partial class Initial { protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -20,7 +20,7 @@ namespace MyCompanyName.MyProjectName.Migrations modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("ProductVersion", "5.0.7") + .HasAnnotation("ProductVersion", "5.0.9") .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => @@ -365,7 +365,6 @@ namespace MyCompanyName.MyProjectName.Migrations modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => { b.Property("Id") - .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); b.Property("ConcurrencyStamp") @@ -412,7 +411,6 @@ namespace MyCompanyName.MyProjectName.Migrations modelBuilder.Entity("Volo.Abp.Identity.IdentityLinkUser", b => { b.Property("Id") - .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); b.Property("SourceTenantId") @@ -439,7 +437,6 @@ namespace MyCompanyName.MyProjectName.Migrations modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => { b.Property("Id") - .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); b.Property("ConcurrencyStamp") @@ -516,7 +513,6 @@ namespace MyCompanyName.MyProjectName.Migrations modelBuilder.Entity("Volo.Abp.Identity.IdentitySecurityLog", b => { b.Property("Id") - .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); b.Property("Action") @@ -591,7 +587,6 @@ namespace MyCompanyName.MyProjectName.Migrations modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => { b.Property("Id") - .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); b.Property("AccessFailedCount") @@ -638,6 +633,9 @@ namespace MyCompanyName.MyProjectName.Migrations .HasColumnType("nvarchar(max)") .HasColumnName("ExtraProperties"); + b.Property("IsActive") + .HasColumnType("bit"); + b.Property("IsDeleted") .ValueGeneratedOnAdd() .HasColumnType("bit") @@ -871,7 +869,6 @@ namespace MyCompanyName.MyProjectName.Migrations modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => { b.Property("Id") - .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); b.Property("Code") @@ -1863,7 +1860,6 @@ namespace MyCompanyName.MyProjectName.Migrations modelBuilder.Entity("Volo.Abp.TenantManagement.Tenant", b => { b.Property("Id") - .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); b.Property("ConcurrencyStamp") diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20210615091011_Initial.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20210909052638_Initial.cs similarity index 99% rename from templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20210615091011_Initial.cs rename to templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20210909052638_Initial.cs index 8a02b53ba3..8e2d7527d5 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20210615091011_Initial.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20210909052638_Initial.cs @@ -253,6 +253,7 @@ namespace MyCompanyName.MyProjectName.Migrations IsExternal = table.Column(type: "bit", nullable: false, defaultValue: false), PhoneNumber = table.Column(type: "nvarchar(16)", maxLength: 16, nullable: true), PhoneNumberConfirmed = table.Column(type: "bit", nullable: false, defaultValue: false), + IsActive = table.Column(type: "bit", nullable: false), TwoFactorEnabled = table.Column(type: "bit", nullable: false, defaultValue: false), LockoutEnd = table.Column(type: "datetimeoffset", nullable: true), LockoutEnabled = table.Column(type: "bit", nullable: false, defaultValue: false), diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs index 56ac0762cc..1812b59627 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs @@ -18,7 +18,7 @@ namespace MyCompanyName.MyProjectName.Migrations modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("ProductVersion", "5.0.7") + .HasAnnotation("ProductVersion", "5.0.9") .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => @@ -363,7 +363,6 @@ namespace MyCompanyName.MyProjectName.Migrations modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => { b.Property("Id") - .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); b.Property("ConcurrencyStamp") @@ -410,7 +409,6 @@ namespace MyCompanyName.MyProjectName.Migrations modelBuilder.Entity("Volo.Abp.Identity.IdentityLinkUser", b => { b.Property("Id") - .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); b.Property("SourceTenantId") @@ -437,7 +435,6 @@ namespace MyCompanyName.MyProjectName.Migrations modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => { b.Property("Id") - .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); b.Property("ConcurrencyStamp") @@ -514,7 +511,6 @@ namespace MyCompanyName.MyProjectName.Migrations modelBuilder.Entity("Volo.Abp.Identity.IdentitySecurityLog", b => { b.Property("Id") - .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); b.Property("Action") @@ -589,7 +585,6 @@ namespace MyCompanyName.MyProjectName.Migrations modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => { b.Property("Id") - .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); b.Property("AccessFailedCount") @@ -636,6 +631,9 @@ namespace MyCompanyName.MyProjectName.Migrations .HasColumnType("nvarchar(max)") .HasColumnName("ExtraProperties"); + b.Property("IsActive") + .HasColumnType("bit"); + b.Property("IsDeleted") .ValueGeneratedOnAdd() .HasColumnType("bit") @@ -869,7 +867,6 @@ namespace MyCompanyName.MyProjectName.Migrations modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => { b.Property("Id") - .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); b.Property("Code") @@ -1861,7 +1858,6 @@ namespace MyCompanyName.MyProjectName.Migrations modelBuilder.Entity("Volo.Abp.TenantManagement.Tenant", b => { b.Property("Id") - .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); b.Property("ConcurrencyStamp") diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20210528093547_Initial.Designer.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20210909052730_Initial.Designer.cs similarity index 99% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20210528093547_Initial.Designer.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20210909052730_Initial.Designer.cs index 3188e8f984..8107c2dcbe 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20210528093547_Initial.Designer.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20210909052730_Initial.Designer.cs @@ -11,7 +11,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Blazor.Server.Host.Migrations { [DbContext(typeof(UnifiedDbContext))] - [Migration("20210528093547_Initial")] + [Migration("20210909052730_Initial")] partial class Initial { protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -20,7 +20,7 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Host.Migrations modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("ProductVersion", "5.0.6") + .HasAnnotation("ProductVersion", "5.0.9") .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => @@ -580,6 +580,9 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Host.Migrations .HasColumnType("nvarchar(max)") .HasColumnName("ExtraProperties"); + b.Property("IsActive") + .HasColumnType("bit"); + b.Property("IsDeleted") .ValueGeneratedOnAdd() .HasColumnType("bit") diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20210528093547_Initial.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20210909052730_Initial.cs similarity index 99% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20210528093547_Initial.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20210909052730_Initial.cs index c982c31c32..0d9af49008 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20210528093547_Initial.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20210909052730_Initial.cs @@ -232,6 +232,7 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Host.Migrations IsExternal = table.Column(type: "bit", nullable: false, defaultValue: false), PhoneNumber = table.Column(type: "nvarchar(16)", maxLength: 16, nullable: true), PhoneNumberConfirmed = table.Column(type: "bit", nullable: false, defaultValue: false), + IsActive = table.Column(type: "bit", nullable: false), TwoFactorEnabled = table.Column(type: "bit", nullable: false, defaultValue: false), LockoutEnd = table.Column(type: "datetimeoffset", nullable: true), LockoutEnabled = table.Column(type: "bit", nullable: false, defaultValue: false), diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/UnifiedDbContextModelSnapshot.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/UnifiedDbContextModelSnapshot.cs index 2d2e6dafd5..c394d8c737 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/UnifiedDbContextModelSnapshot.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/UnifiedDbContextModelSnapshot.cs @@ -18,7 +18,7 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Host.Migrations modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("ProductVersion", "5.0.6") + .HasAnnotation("ProductVersion", "5.0.9") .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => @@ -578,6 +578,9 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Host.Migrations .HasColumnType("nvarchar(max)") .HasColumnName("ExtraProperties"); + b.Property("IsActive") + .HasColumnType("bit"); + b.Property("IsDeleted") .ValueGeneratedOnAdd() .HasColumnType("bit") diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/Migrations/20210528093513_Initial.Designer.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/Migrations/20210909052712_Initial.Designer.cs similarity index 99% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/Migrations/20210528093513_Initial.Designer.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/Migrations/20210909052712_Initial.Designer.cs index 2a8dcb3b75..b9edb3b1a7 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/Migrations/20210528093513_Initial.Designer.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/Migrations/20210909052712_Initial.Designer.cs @@ -11,7 +11,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Migrations { [DbContext(typeof(IdentityServerHostMigrationsDbContext))] - [Migration("20210528093513_Initial")] + [Migration("20210909052712_Initial")] partial class Initial { protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -20,7 +20,7 @@ namespace MyCompanyName.MyProjectName.Migrations modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("ProductVersion", "5.0.6") + .HasAnnotation("ProductVersion", "5.0.9") .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => @@ -580,6 +580,9 @@ namespace MyCompanyName.MyProjectName.Migrations .HasColumnType("nvarchar(max)") .HasColumnName("ExtraProperties"); + b.Property("IsActive") + .HasColumnType("bit"); + b.Property("IsDeleted") .ValueGeneratedOnAdd() .HasColumnType("bit") diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/Migrations/20210528093513_Initial.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/Migrations/20210909052712_Initial.cs similarity index 99% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/Migrations/20210528093513_Initial.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/Migrations/20210909052712_Initial.cs index bf39015d0f..5333a6a34e 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/Migrations/20210528093513_Initial.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/Migrations/20210909052712_Initial.cs @@ -232,6 +232,7 @@ namespace MyCompanyName.MyProjectName.Migrations IsExternal = table.Column(type: "bit", nullable: false, defaultValue: false), PhoneNumber = table.Column(type: "nvarchar(16)", maxLength: 16, nullable: true), PhoneNumberConfirmed = table.Column(type: "bit", nullable: false, defaultValue: false), + IsActive = table.Column(type: "bit", nullable: false), TwoFactorEnabled = table.Column(type: "bit", nullable: false, defaultValue: false), LockoutEnd = table.Column(type: "datetimeoffset", nullable: true), LockoutEnabled = table.Column(type: "bit", nullable: false, defaultValue: false), diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/Migrations/IdentityServerHostMigrationsDbContextModelSnapshot.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/Migrations/IdentityServerHostMigrationsDbContextModelSnapshot.cs index 35ad1df358..aa156c5d53 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/Migrations/IdentityServerHostMigrationsDbContextModelSnapshot.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/Migrations/IdentityServerHostMigrationsDbContextModelSnapshot.cs @@ -18,7 +18,7 @@ namespace MyCompanyName.MyProjectName.Migrations modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("ProductVersion", "5.0.6") + .HasAnnotation("ProductVersion", "5.0.9") .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => @@ -578,6 +578,9 @@ namespace MyCompanyName.MyProjectName.Migrations .HasColumnType("nvarchar(max)") .HasColumnName("ExtraProperties"); + b.Property("IsActive") + .HasColumnType("bit"); + b.Property("IsDeleted") .ValueGeneratedOnAdd() .HasColumnType("bit") diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20210528093522_Initial.Designer.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20210909052706_Initial.Designer.cs similarity index 99% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20210528093522_Initial.Designer.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20210909052706_Initial.Designer.cs index 43912d5e1a..993934aedb 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20210528093522_Initial.Designer.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20210909052706_Initial.Designer.cs @@ -11,7 +11,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Migrations { [DbContext(typeof(UnifiedDbContext))] - [Migration("20210528093522_Initial")] + [Migration("20210909052706_Initial")] partial class Initial { protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -20,7 +20,7 @@ namespace MyCompanyName.MyProjectName.Migrations modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("ProductVersion", "5.0.6") + .HasAnnotation("ProductVersion", "5.0.9") .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => @@ -580,6 +580,9 @@ namespace MyCompanyName.MyProjectName.Migrations .HasColumnType("nvarchar(max)") .HasColumnName("ExtraProperties"); + b.Property("IsActive") + .HasColumnType("bit"); + b.Property("IsDeleted") .ValueGeneratedOnAdd() .HasColumnType("bit") diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20210528093522_Initial.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20210909052706_Initial.cs similarity index 99% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20210528093522_Initial.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20210909052706_Initial.cs index b5e7c7492e..b7465b0dcb 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20210528093522_Initial.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20210909052706_Initial.cs @@ -232,6 +232,7 @@ namespace MyCompanyName.MyProjectName.Migrations IsExternal = table.Column(type: "bit", nullable: false, defaultValue: false), PhoneNumber = table.Column(type: "nvarchar(16)", maxLength: 16, nullable: true), PhoneNumberConfirmed = table.Column(type: "bit", nullable: false, defaultValue: false), + IsActive = table.Column(type: "bit", nullable: false), TwoFactorEnabled = table.Column(type: "bit", nullable: false, defaultValue: false), LockoutEnd = table.Column(type: "datetimeoffset", nullable: true), LockoutEnabled = table.Column(type: "bit", nullable: false, defaultValue: false), diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs index bc4abaa1af..472749a2a0 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs @@ -18,7 +18,7 @@ namespace MyCompanyName.MyProjectName.Migrations modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("ProductVersion", "5.0.6") + .HasAnnotation("ProductVersion", "5.0.9") .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => @@ -578,6 +578,9 @@ namespace MyCompanyName.MyProjectName.Migrations .HasColumnType("nvarchar(max)") .HasColumnName("ExtraProperties"); + b.Property("IsActive") + .HasColumnType("bit"); + b.Property("IsDeleted") .ValueGeneratedOnAdd() .HasColumnType("bit") From fcf7ba667310db0ea482c6a2a640772628938612 Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 9 Sep 2021 13:40:55 +0800 Subject: [PATCH 13/49] Update IdentityUserDtoExtensions.cs --- .../Volo/Abp/Identity/IdentityUserDtoExtensions.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/identity/src/Volo.Abp.Identity.HttpApi.Client/Volo/Abp/Identity/IdentityUserDtoExtensions.cs b/modules/identity/src/Volo.Abp.Identity.HttpApi.Client/Volo/Abp/Identity/IdentityUserDtoExtensions.cs index 8c90fe5f73..bdb1e9044e 100644 --- a/modules/identity/src/Volo.Abp.Identity.HttpApi.Client/Volo/Abp/Identity/IdentityUserDtoExtensions.cs +++ b/modules/identity/src/Volo.Abp.Identity.HttpApi.Client/Volo/Abp/Identity/IdentityUserDtoExtensions.cs @@ -15,8 +15,7 @@ namespace Volo.Abp.Identity user.EmailConfirmed, user.PhoneNumber, user.PhoneNumberConfirmed, - user.TenantId, - user.IsActive + user.TenantId ); } } 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 14/49] 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 15/49] 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 16/49] 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 17/49] 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 18/49] 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 19/49] 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 20/49] 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 21/49] 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 22/49] 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 23/49] 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 24/49] 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 25/49] 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 26/49] 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 27/49] 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 28/49] 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 29/49] 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 30/49] 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 41adcd251d93b87bbe9f2ee5c261c8b81a4d829a Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Fri, 24 Sep 2021 13:26:09 +0800 Subject: [PATCH 31/49] Make IRepository not inherit from IQueryable --- .../Services/AbstractKeyReadOnlyAppService.cs | 24 ---------------- .../Repositories/IReadOnlyRepository.cs | 4 +-- .../Abp/Domain/Repositories/RepositoryBase.cs | 22 --------------- .../EntityFrameworkCore/EfCoreRepository.cs | 8 +----- .../Repositories/MongoDB/MongoDbRepository.cs | 22 ++------------- .../EfCoreAsyncQueryableProvider_Tests.cs | 21 ++++++++------ .../Repositories/Repository_Basic_Tests.cs | 1 + .../Repository_Queryable_Tests.cs | 12 ++++---- .../EntityFrameworkCore/CityRepository.cs | 1 + .../MongoDbAsyncQueryableProvider_Tests.cs | 16 +++++------ .../MongoDbAsyncQueryableProvider_Tests.cs | 10 +++---- .../Repositories/Repository_Basic_Tests.cs | 16 +++++------ .../TestApp/Application/DistrictAppService.cs | 4 +-- .../Abp/TestApp/Testing/DomainEvents_Tests.cs | 28 +++++++++---------- .../Testing/MultiTenant_Filter_Tests.cs | 16 +++++------ .../Repository_Basic_Tests_With_Int_Pk.cs | 4 +-- .../Testing/Repository_Queryable_Tests.cs | 8 +++--- .../Repository_Specifications_Tests.cs | 6 ++-- .../Testing/SoftDelete_Filter_Tests.cs | 22 +++++++-------- .../EfCoreTenantRepository.cs | 2 +- .../EfCoreAbpUserRepositoryBase.cs | 2 +- 21 files changed, 92 insertions(+), 157 deletions(-) diff --git a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AbstractKeyReadOnlyAppService.cs b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AbstractKeyReadOnlyAppService.cs index 54123bc843..528a8c67a1 100644 --- a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AbstractKeyReadOnlyAppService.cs +++ b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AbstractKeyReadOnlyAppService.cs @@ -153,19 +153,6 @@ namespace Volo.Abp.Application.Services return query; } - /// - /// This method should create based on given input. - /// It should filter query if needed, but should not do sorting or paging. - /// Sorting should be done in and paging should be done in - /// methods. - /// - /// The input. - [Obsolete("Override the CreateFilteredQueryAsync method instead.")] - protected virtual IQueryable CreateFilteredQuery(TGetListInput input) - { - return ReadOnlyRepository; - } - /// /// This method should create based on given input. /// It should filter query if needed, but should not do sorting or paging. @@ -175,17 +162,6 @@ namespace Volo.Abp.Application.Services /// The input. protected virtual async Task> CreateFilteredQueryAsync(TGetListInput input) { - /* If user has overridden the CreateFilteredQuery method, - * we don't want to make breaking change in this point. - */ -#pragma warning disable 618 - var query = CreateFilteredQuery(input); -#pragma warning restore 618 - if (!ReferenceEquals(query, ReadOnlyRepository)) - { - return query; - } - return await ReadOnlyRepository.GetQueryableAsync(); } diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IReadOnlyRepository.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IReadOnlyRepository.cs index 7aeffdad12..bf0704f085 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IReadOnlyRepository.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IReadOnlyRepository.cs @@ -10,7 +10,7 @@ using Volo.Abp.Linq; namespace Volo.Abp.Domain.Repositories { - public interface IReadOnlyRepository : IQueryable, IReadOnlyBasicRepository + public interface IReadOnlyRepository: IReadOnlyBasicRepository where TEntity : class, IEntity { IAsyncQueryableExecuter AsyncExecuter { get; } @@ -26,7 +26,7 @@ namespace Volo.Abp.Domain.Repositories Task> WithDetailsAsync(params Expression>[] propertySelectors); //TODO: CancellationToken Task> GetQueryableAsync(); //TODO: CancellationToken - + /// /// Gets a list of entities by the given . /// diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/RepositoryBase.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/RepositoryBase.cs index 0b32d54d45..da10901420 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/RepositoryBase.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/RepositoryBase.cs @@ -1,6 +1,5 @@ using JetBrains.Annotations; using System; -using System.Collections; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; @@ -15,15 +14,6 @@ namespace Volo.Abp.Domain.Repositories public abstract class RepositoryBase : BasicRepositoryBase, IRepository, IUnitOfWorkManagerAccessor where TEntity : class, IEntity { - [Obsolete("This method will be removed in future versions.")] - public virtual Type ElementType => GetQueryable().ElementType; - - [Obsolete("This method will be removed in future versions.")] - public virtual Expression Expression => GetQueryable().Expression; - - [Obsolete("This method will be removed in future versions.")] - public virtual IQueryProvider Provider => GetQueryable().Provider; - [Obsolete("Use WithDetailsAsync method.")] public virtual IQueryable WithDetails() { @@ -46,18 +36,6 @@ namespace Volo.Abp.Domain.Repositories return GetQueryableAsync(); } - [Obsolete("This method will be removed in future versions.")] - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - - [Obsolete("This method will be removed in future versions.")] - public IEnumerator GetEnumerator() - { - return GetQueryable().GetEnumerator(); - } - [Obsolete("Use GetQueryableAsync method.")] protected abstract IQueryable GetQueryable(); diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/EfCoreRepository.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/EfCoreRepository.cs index c330beb281..fb32e5a21d 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/EfCoreRepository.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/EfCoreRepository.cs @@ -17,7 +17,7 @@ using Volo.Abp.MultiTenancy; namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore { - public class EfCoreRepository : RepositoryBase, IEfCoreRepository, IAsyncEnumerable + public class EfCoreRepository : RepositoryBase, IEfCoreRepository where TDbContext : IEfCoreDbContext where TEntity : class, IEntity { @@ -381,12 +381,6 @@ namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore return query; } - [Obsolete("This method will be deleted in future versions.")] - public IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) - { - return DbSet.AsAsyncEnumerable().GetAsyncEnumerator(cancellationToken); - } - protected virtual void CheckAndSetId(TEntity entity) { if (entity is IEntity entityWithGuidId) 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..696e7846c5 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 @@ -2,6 +2,7 @@ using JetBrains.Annotations; using MongoDB.Driver; using MongoDB.Driver.Linq; using System; +using System.Collections; using System.Collections.Generic; using System.Linq; using System.Linq.Dynamic.Core; @@ -23,8 +24,7 @@ namespace Volo.Abp.Domain.Repositories.MongoDB { public class MongoDbRepository : RepositoryBase, - IMongoDbRepository, - IMongoQueryable + IMongoDbRepository where TMongoDbContext : IAbpMongoDbContext where TEntity : class, IEntity { @@ -720,24 +720,6 @@ namespace Volo.Abp.Domain.Repositories.MongoDB return aggregate; } - - [Obsolete("This method will be removed in future versions.")] - public QueryableExecutionModel GetExecutionModel() - { - return GetMongoQueryable().GetExecutionModel(); - } - - [Obsolete("This method will be removed in future versions.")] - public IAsyncCursor ToCursor(CancellationToken cancellationToken = new CancellationToken()) - { - return GetMongoQueryable().ToCursor(GetCancellationToken(cancellationToken)); - } - - [Obsolete("This method will be removed in future versions.")] - public Task> ToCursorAsync(CancellationToken cancellationToken = new CancellationToken()) - { - return GetMongoQueryable().ToCursorAsync(GetCancellationToken(cancellationToken)); - } } public class MongoDbRepository diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/EfCoreAsyncQueryableProvider_Tests.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/EfCoreAsyncQueryableProvider_Tests.cs index 9a6c0817f2..93e0de6639 100644 --- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/EfCoreAsyncQueryableProvider_Tests.cs +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/EfCoreAsyncQueryableProvider_Tests.cs @@ -24,28 +24,31 @@ namespace Volo.Abp.EntityFrameworkCore } [Fact] - public void Should_Accept_EfCore_Related_Queries() + public async Task Should_Accept_EfCore_Related_Queries() { - var query = _personRepository.Where(p => p.Age > 0); - - _efCoreAsyncQueryableProvider.CanExecute(query).ShouldBeTrue(); + using ( _ = _unitOfWorkManager.Begin()) + { + var query = (await _personRepository.GetQueryableAsync()).Where(p => p.Age > 0); + + _efCoreAsyncQueryableProvider.CanExecute(query).ShouldBeTrue(); + } } [Fact] public void Should_Not_Accept_Other_Providers() { var query = new[] {1, 2, 3}.AsQueryable().Where(x => x > 0); - + _efCoreAsyncQueryableProvider.CanExecute(query).ShouldBeFalse(); } - + [Fact] public async Task Should_Execute_Queries() { using (var uow = _unitOfWorkManager.Begin()) { - var query = _personRepository.Where(p => p.Age > 0); - + var query = (await _personRepository.GetQueryableAsync()).Where(p => p.Age > 0); + (await _efCoreAsyncQueryableProvider.CountAsync(query) > 0).ShouldBeTrue(); (await _efCoreAsyncQueryableProvider.FirstOrDefaultAsync(query)).ShouldNotBeNull(); (await _efCoreAsyncQueryableProvider.ToListAsync(query)).Count.ShouldBeGreaterThan(0); @@ -54,4 +57,4 @@ namespace Volo.Abp.EntityFrameworkCore } } } -} \ No newline at end of file +} diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Repositories/Repository_Basic_Tests.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Repositories/Repository_Basic_Tests.cs index 3d5d7b656b..ab3217b9f3 100644 --- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Repositories/Repository_Basic_Tests.cs +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Repositories/Repository_Basic_Tests.cs @@ -1,6 +1,7 @@ using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Shouldly; +using Volo.Abp.Domain.Repositories; using Volo.Abp.TestApp.Testing; using Xunit; diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Repositories/Repository_Queryable_Tests.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Repositories/Repository_Queryable_Tests.cs index a5b8aa0577..8149cdbe32 100644 --- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Repositories/Repository_Queryable_Tests.cs +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Repositories/Repository_Queryable_Tests.cs @@ -26,9 +26,9 @@ namespace Volo.Abp.EntityFrameworkCore.Repositories [Fact] public async Task GetBookList() { - await WithUnitOfWorkAsync(() => + await WithUnitOfWorkAsync(async () => { - _bookRepository.Any().ShouldBeTrue(); + (await _bookRepository.AnyAsync()).ShouldBeTrue(); return Task.CompletedTask; }); } @@ -36,9 +36,9 @@ namespace Volo.Abp.EntityFrameworkCore.Repositories [Fact] public async Task GetPhoneInSecondDbContextList() { - await WithUnitOfWorkAsync(() => + await WithUnitOfWorkAsync(async () => { - _phoneInSecondDbContextRepository.Any().ShouldBeTrue(); + (await _phoneInSecondDbContextRepository.AnyAsync()).ShouldBeTrue(); return Task.CompletedTask; }); } @@ -46,9 +46,9 @@ namespace Volo.Abp.EntityFrameworkCore.Repositories [Fact] public async Task EfCore_Include_Extension() { - await WithUnitOfWorkAsync(() => + await WithUnitOfWorkAsync(async () => { - var person = PersonRepository.Include(p => p.Phones).Single(p => p.Id == TestDataBuilder.UserDouglasId); + var person = await (await PersonRepository.GetDbSetAsync()).Include(p => p.Phones).SingleAsync(p => p.Id == TestDataBuilder.UserDouglasId); person.Name.ShouldBe("Douglas"); person.Phones.Count.ShouldBe(2); return Task.CompletedTask; diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/CityRepository.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/CityRepository.cs index cd85cbcb5a..b3d1663edb 100644 --- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/CityRepository.cs +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/CityRepository.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; +using Volo.Abp.Domain.Repositories; using Volo.Abp.Domain.Repositories.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore; using Volo.Abp.TestApp.Domain; diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/MongoDbAsyncQueryableProvider_Tests.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/MongoDbAsyncQueryableProvider_Tests.cs index 22013d9b63..3daff7049c 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/MongoDbAsyncQueryableProvider_Tests.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/MongoDbAsyncQueryableProvider_Tests.cs @@ -24,10 +24,10 @@ namespace Volo.Abp.MongoDB } [Fact] - public void Should_Accept_MongoDb_Related_Queries() + public async Task Should_Accept_MongoDb_Related_Queries() { - var query = _personRepository.Where(p => p.Age > 0); - + var query = (await _personRepository.GetQueryableAsync()).Where(p => p.Age > 0); + _mongoDbAsyncQueryableProvider.CanExecute(query).ShouldBeTrue(); } @@ -35,17 +35,17 @@ namespace Volo.Abp.MongoDB public void Should_Not_Accept_Other_Providers() { var query = new[] {1, 2, 3}.AsQueryable().Where(x => x > 0); - + _mongoDbAsyncQueryableProvider.CanExecute(query).ShouldBeFalse(); } - + [Fact] public async Task Should_Execute_Queries() { using (var uow = _unitOfWorkManager.Begin()) { - var query = _personRepository.Where(p => p.Age > 0).OrderBy(p => p.Name); - + var query = (await _personRepository.GetQueryableAsync()).Where(p => p.Age > 0).OrderBy(p => p.Name); + (await _mongoDbAsyncQueryableProvider.CountAsync(query) > 0).ShouldBeTrue(); (await _mongoDbAsyncQueryableProvider.FirstOrDefaultAsync(query)).ShouldNotBeNull(); (await _mongoDbAsyncQueryableProvider.ToListAsync(query)).Count.ShouldBeGreaterThan(0); @@ -54,4 +54,4 @@ namespace Volo.Abp.MongoDB } } } -} \ No newline at end of file +} diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/MongoDbAsyncQueryableProvider_Tests.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/MongoDbAsyncQueryableProvider_Tests.cs index 5335aa11be..48f74ab3a2 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/MongoDbAsyncQueryableProvider_Tests.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/MongoDbAsyncQueryableProvider_Tests.cs @@ -27,7 +27,7 @@ namespace Volo.Abp.MongoDB.Repositories [Fact] public async Task CanExecuteAsync() { - _mongoDbAsyncQueryableProvider.CanExecute(_personRepository).ShouldBeTrue(); + _mongoDbAsyncQueryableProvider.CanExecute(await _personRepository.GetQueryableAsync()).ShouldBeTrue(); _mongoDbAsyncQueryableProvider.CanExecute(await _personRepository.WithDetailsAsync()).ShouldBeTrue(); } @@ -36,7 +36,7 @@ namespace Volo.Abp.MongoDB.Repositories { using (var uow = _unitOfWorkManager.Begin()) { - (await _mongoDbAsyncQueryableProvider.FirstOrDefaultAsync(_personRepository.Where(p => p.Name == "Douglas"))).ShouldNotBeNull(); + (await _mongoDbAsyncQueryableProvider.FirstOrDefaultAsync((await _personRepository.GetQueryableAsync()).Where(p => p.Name == "Douglas"))).ShouldNotBeNull(); await uow.CompleteAsync(); } } @@ -46,7 +46,7 @@ namespace Volo.Abp.MongoDB.Repositories { using (var uow = _unitOfWorkManager.Begin()) { - (await _mongoDbAsyncQueryableProvider.AnyAsync(_personRepository, p => p.Name == "Douglas")).ShouldBeTrue(); + (await _mongoDbAsyncQueryableProvider.AnyAsync(await _personRepository.GetQueryableAsync(), p => p.Name == "Douglas")).ShouldBeTrue(); await uow.CompleteAsync(); } } @@ -56,7 +56,7 @@ namespace Volo.Abp.MongoDB.Repositories { using (var uow = _unitOfWorkManager.Begin()) { - (await _mongoDbAsyncQueryableProvider.CountAsync(_personRepository.Where(p => p.Name == "Douglas"))).ShouldBeGreaterThan(0); + (await _mongoDbAsyncQueryableProvider.CountAsync((await _personRepository.GetQueryableAsync()).Where(p => p.Name == "Douglas"))).ShouldBeGreaterThan(0); await uow.CompleteAsync(); } } @@ -66,7 +66,7 @@ namespace Volo.Abp.MongoDB.Repositories { using (var uow = _unitOfWorkManager.Begin()) { - (await _mongoDbAsyncQueryableProvider.LongCountAsync(_personRepository)).ShouldBeGreaterThan(0); + (await _mongoDbAsyncQueryableProvider.LongCountAsync(await _personRepository.GetQueryableAsync())).ShouldBeGreaterThan(0); await uow.CompleteAsync(); } } diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests.cs index 09b1551e3d..0be9b43db0 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests.cs @@ -14,21 +14,21 @@ namespace Volo.Abp.MongoDB.Repositories public class Repository_Basic_Tests : Repository_Basic_Tests { [Fact] - public void ToMongoQueryable_Test() + public async Task ToMongoQueryable_Test() { - ((IMongoQueryable) PersonRepository).ShouldNotBeNull(); - PersonRepository.As>().ShouldNotBeNull(); - ((IMongoQueryable) PersonRepository.Where(p => p.Name == "Douglas")).ShouldNotBeNull(); - PersonRepository.Where(p => p.Name == "Douglas").As>().ShouldNotBeNull(); + (await PersonRepository.GetQueryableAsync()).ShouldNotBeNull(); + (await PersonRepository.GetQueryableAsync()).As>().ShouldNotBeNull(); + ((IMongoQueryable)(await PersonRepository.GetQueryableAsync()).Where(p => p.Name == "Douglas")).ShouldNotBeNull(); + (await PersonRepository.GetQueryableAsync()).Where(p => p.Name == "Douglas").As>().ShouldNotBeNull(); } [Fact] public async Task Linq_Queries() { - await WithUnitOfWorkAsync(() => + await WithUnitOfWorkAsync(async () => { - PersonRepository.FirstOrDefault(p => p.Name == "Douglas").ShouldNotBeNull(); - PersonRepository.Count().ShouldBeGreaterThan(0); + (await PersonRepository.GetQueryableAsync()).FirstOrDefault(p => p.Name == "Douglas").ShouldNotBeNull(); + (await PersonRepository.GetQueryableAsync()).Count().ShouldBeGreaterThan(0); return Task.CompletedTask; }); } diff --git a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/DistrictAppService.cs b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/DistrictAppService.cs index f7e7fde5e2..645d413692 100644 --- a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/DistrictAppService.cs +++ b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/DistrictAppService.cs @@ -10,7 +10,7 @@ namespace Volo.Abp.TestApp.Application //This is especially used to test the AbstractKeyCrudAppService public class DistrictAppService : AbstractKeyCrudAppService { - public DistrictAppService(IRepository repository) + public DistrictAppService(IRepository repository) : base(repository) { } @@ -23,7 +23,7 @@ namespace Volo.Abp.TestApp.Application protected override async Task GetEntityByIdAsync(DistrictKey id) { return await AsyncExecuter.FirstOrDefaultAsync( - Repository.Where(d => d.CityId == id.CityId && d.Name == id.Name) + (await Repository.GetQueryableAsync()).Where(d => d.CityId == id.CityId && d.Name == id.Name) ); } } diff --git a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/DomainEvents_Tests.cs b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/DomainEvents_Tests.cs index 04d0dda3c4..27154ba8de 100644 --- a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/DomainEvents_Tests.cs +++ b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/DomainEvents_Tests.cs @@ -13,7 +13,7 @@ using Xunit; namespace Volo.Abp.TestApp.Testing { - public abstract class DomainEvents_Tests : TestAppTestBase + public abstract class DomainEvents_Tests : TestAppTestBase where TStartupModule : IAbpModule { protected readonly IRepository PersonRepository; @@ -35,7 +35,7 @@ namespace Volo.Abp.TestApp.Testing bool douglesNameChangeHandled = false; bool customEventHandled = false; bool customEvent2Handled = false; - + LocalEventBus.Subscribe>(data => { data.Entity.Name.ShouldBe("TestPerson1"); @@ -46,7 +46,7 @@ namespace Volo.Abp.TestApp.Testing customEvent2Handled.ShouldBeFalse(); return Task.CompletedTask; }); - + LocalEventBus.Subscribe(data => { data.Value.ShouldBe("42"); @@ -57,7 +57,7 @@ namespace Volo.Abp.TestApp.Testing customEvent2Handled.ShouldBeFalse(); return Task.CompletedTask; }); - + LocalEventBus.Subscribe(data => { data.OldName.ShouldBe("Douglas"); @@ -69,7 +69,7 @@ namespace Volo.Abp.TestApp.Testing customEvent2Handled.ShouldBeFalse(); return Task.CompletedTask; }); - + LocalEventBus.Subscribe>(data => { data.Entity.Name.ShouldBe("Douglas-Updated"); @@ -80,7 +80,7 @@ namespace Volo.Abp.TestApp.Testing customEvent2Handled.ShouldBeFalse(); return Task.CompletedTask; }); - + LocalEventBus.Subscribe(data => { data.Value.ShouldBe("44"); @@ -97,13 +97,13 @@ namespace Volo.Abp.TestApp.Testing await PersonRepository.InsertAsync( new Person(Guid.NewGuid(), "TestPerson1", 42) ); - + await LocalEventBus.PublishAsync(new MyCustomEventData { Value = "42" }); var douglas = await PersonRepository.GetAsync(TestDataBuilder.UserDouglasId); douglas.ChangeName("Douglas-Updated"); await PersonRepository.UpdateAsync(douglas); - + await LocalEventBus.PublishAsync(new MyCustomEventData2 { Value = "44" }); }); } @@ -112,7 +112,7 @@ namespace Volo.Abp.TestApp.Testing public virtual async Task Should_Rollback_Uow_If_Event_Handler_Throws_Exception() { (await PersonRepository.FindAsync(x => x.Name == "TestPerson1")).ShouldBeNull(); - + LocalEventBus.Subscribe>(data => { data.Entity.Name.ShouldBe("TestPerson1"); @@ -128,7 +128,7 @@ namespace Volo.Abp.TestApp.Testing ); }); }); - + exception.Message.ShouldBe("Just to rollback the UOW"); (await PersonRepository.FindAsync(x => x.Name == "TestPerson1")).ShouldBeNull(); @@ -162,7 +162,7 @@ namespace Volo.Abp.TestApp.Testing await WithUnitOfWorkAsync(async () => { - var dougles = PersonRepository.Single(b => b.Name == "Douglas"); + var dougles = await PersonRepository.SingleAsync(b => b.Name == "Douglas"); dougles.ChangeName("Douglas-Changed"); await PersonRepository.UpdateAsync(dougles); }); @@ -172,15 +172,15 @@ namespace Volo.Abp.TestApp.Testing isLocalEventTriggered.ShouldBeTrue(); isDistributedEventTriggered.ShouldBeTrue(); } - + private class MyCustomEventData { public string Value { get; set; } } - + private class MyCustomEventData2 { public string Value { get; set; } } } -} \ No newline at end of file +} diff --git a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/MultiTenant_Filter_Tests.cs b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/MultiTenant_Filter_Tests.cs index da3e33ffea..2a4a012217 100644 --- a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/MultiTenant_Filter_Tests.cs +++ b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/MultiTenant_Filter_Tests.cs @@ -14,7 +14,7 @@ using Xunit; namespace Volo.Abp.TestApp.Testing { - public abstract class MultiTenant_Filter_Tests : TestAppTestBase + public abstract class MultiTenant_Filter_Tests : TestAppTestBase where TStartupModule : IAbpModule { private ICurrentTenant _fakeCurrentTenant; @@ -36,13 +36,13 @@ namespace Volo.Abp.TestApp.Testing [Fact] public async Task Should_Get_Person_For_Current_Tenant() { - await WithUnitOfWorkAsync(() => + await WithUnitOfWorkAsync(async () => { //TenantId = null _fakeCurrentTenant.Id.Returns((Guid?)null); - var people = _personRepository.ToList(); + var people = await _personRepository.ToListAsync(); people.Count.ShouldBe(1); people.Any(p => p.Name == "Douglas").ShouldBeTrue(); @@ -50,7 +50,7 @@ namespace Volo.Abp.TestApp.Testing _fakeCurrentTenant.Id.Returns(TestDataBuilder.TenantId1); - people = _personRepository.ToList(); + people = await _personRepository.ToListAsync(); people.Count.ShouldBe(2); people.Any(p => p.Name == TestDataBuilder.TenantId1 + "-Person1").ShouldBeTrue(); people.Any(p => p.Name == TestDataBuilder.TenantId1 + "-Person2").ShouldBeTrue(); @@ -59,7 +59,7 @@ namespace Volo.Abp.TestApp.Testing _fakeCurrentTenant.Id.Returns(TestDataBuilder.TenantId2); - people = _personRepository.ToList(); + people = await _personRepository.ToListAsync(); people.Count.ShouldBe(0); return Task.CompletedTask; @@ -69,19 +69,19 @@ namespace Volo.Abp.TestApp.Testing [Fact] public async Task Should_Get_All_People_When_MultiTenant_Filter_Is_Disabled() { - await WithUnitOfWorkAsync(() => + await WithUnitOfWorkAsync(async () => { List people; using (_multiTenantFilter.Disable()) { //Filter disabled manually - people = _personRepository.ToList(); + people = await _personRepository.ToListAsync(); people.Count.ShouldBe(3); } //Filter re-enabled automatically - people = _personRepository.ToList(); + people = await _personRepository.ToListAsync(); people.Count.ShouldBe(1); return Task.CompletedTask; diff --git a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/Repository_Basic_Tests_With_Int_Pk.cs b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/Repository_Basic_Tests_With_Int_Pk.cs index 821a80492b..4347120d36 100644 --- a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/Repository_Basic_Tests_With_Int_Pk.cs +++ b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/Repository_Basic_Tests_With_Int_Pk.cs @@ -22,9 +22,9 @@ namespace Volo.Abp.TestApp.Testing [Fact] public virtual async Task FirstOrDefault() { - await WithUnitOfWorkAsync(() => + await WithUnitOfWorkAsync(async () => { - var entity = EntityWithIntPkRepository.FirstOrDefault(e => e.Name == "Entity1"); + var entity = await EntityWithIntPkRepository.FirstOrDefaultAsync(e => e.Name == "Entity1"); entity.ShouldNotBeNull(); entity.Name.ShouldBe("Entity1"); return Task.CompletedTask; diff --git a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/Repository_Queryable_Tests.cs b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/Repository_Queryable_Tests.cs index 3ca511a7ea..c8710bbf2c 100644 --- a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/Repository_Queryable_Tests.cs +++ b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/Repository_Queryable_Tests.cs @@ -23,9 +23,9 @@ namespace Volo.Abp.TestApp.Testing [Fact] public async Task Any() { - await WithUnitOfWorkAsync(() => + await WithUnitOfWorkAsync(async () => { - PersonRepository.Any().ShouldBeTrue(); + (await PersonRepository.AnyAsync()).ShouldBeTrue(); return Task.CompletedTask; }); } @@ -33,9 +33,9 @@ namespace Volo.Abp.TestApp.Testing [Fact] public async Task Single() { - await WithUnitOfWorkAsync(() => + await WithUnitOfWorkAsync(async () => { - var person = PersonRepository.Single(p => p.Id == TestDataBuilder.UserDouglasId); + var person = await PersonRepository.SingleAsync(p => p.Id == TestDataBuilder.UserDouglasId); person.Name.ShouldBe("Douglas"); return Task.CompletedTask; }); diff --git a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/Repository_Specifications_Tests.cs b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/Repository_Specifications_Tests.cs index c26134b27c..9ce5499d7f 100644 --- a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/Repository_Specifications_Tests.cs +++ b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/Repository_Specifications_Tests.cs @@ -24,9 +24,9 @@ namespace Volo.Abp.TestApp.Testing [Fact] public async Task SpecificationWithRepository_Test() { - await WithUnitOfWorkAsync(() => + await WithUnitOfWorkAsync(async () => { - CityRepository.Count(new CitySpecification().ToExpression()).ShouldBe(1); + (await CityRepository.CountAsync(new CitySpecification().ToExpression())).ShouldBe(1); return Task.CompletedTask; }); } @@ -39,4 +39,4 @@ namespace Volo.Abp.TestApp.Testing return city => city.Name == "Istanbul"; } } -} \ No newline at end of file +} diff --git a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/SoftDelete_Filter_Tests.cs b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/SoftDelete_Filter_Tests.cs index f3ac8c301f..514f2d2648 100644 --- a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/SoftDelete_Filter_Tests.cs +++ b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/SoftDelete_Filter_Tests.cs @@ -10,7 +10,7 @@ using Xunit; namespace Volo.Abp.TestApp.Testing { - public abstract class SoftDelete_Filter_Tests : TestAppTestBase + public abstract class SoftDelete_Filter_Tests : TestAppTestBase where TStartupModule : IAbpModule { protected readonly IRepository PersonRepository; @@ -25,9 +25,9 @@ namespace Volo.Abp.TestApp.Testing [Fact] public async Task Should_Not_Get_Deleted_Entities_Linq() { - await WithUnitOfWorkAsync(() => + await WithUnitOfWorkAsync(async () => { - var person = PersonRepository.FirstOrDefault(p => p.Name == "John-Deleted"); + var person = await PersonRepository.FirstOrDefaultAsync(p => p.Name == "John-Deleted"); person.ShouldBeNull(); return Task.CompletedTask; }); @@ -46,9 +46,9 @@ namespace Volo.Abp.TestApp.Testing [Fact] public async Task Should_Not_Get_Deleted_Entities_By_Default_ToList() { - await WithUnitOfWorkAsync(() => + await WithUnitOfWorkAsync(async () => { - var people = PersonRepository.ToList(); + var people = await PersonRepository.ToListAsync(); people.Count.ShouldBe(1); people.Any(p => p.Name == "Douglas").ShouldBeTrue(); return Task.CompletedTask; @@ -58,36 +58,36 @@ namespace Volo.Abp.TestApp.Testing [Fact] public async Task Should_Get_Deleted_Entities_When_Filter_Is_Disabled() { - await WithUnitOfWorkAsync(() => + await WithUnitOfWorkAsync(async () => { //Soft delete is enabled by default - var people = PersonRepository.ToList(); + var people = await PersonRepository.ToListAsync(); people.Any(p => !p.IsDeleted).ShouldBeTrue(); people.Any(p => p.IsDeleted).ShouldBeFalse(); using (DataFilter.Disable()) { //Soft delete is disabled - people = PersonRepository.ToList(); + people = await PersonRepository.ToListAsync(); people.Any(p => !p.IsDeleted).ShouldBeTrue(); people.Any(p => p.IsDeleted).ShouldBeTrue(); using (DataFilter.Enable()) { //Soft delete is enabled again - people = PersonRepository.ToList(); + people = await PersonRepository.ToListAsync(); people.Any(p => !p.IsDeleted).ShouldBeTrue(); people.Any(p => p.IsDeleted).ShouldBeFalse(); } //Soft delete is disabled (restored previous state) - people = PersonRepository.ToList(); + people = await PersonRepository.ToListAsync(); people.Any(p => !p.IsDeleted).ShouldBeTrue(); people.Any(p => p.IsDeleted).ShouldBeTrue(); } //Soft delete is enabled (restored previous state) - people = PersonRepository.ToList(); + people = await PersonRepository.ToListAsync(); people.Any(p => !p.IsDeleted).ShouldBeTrue(); people.Any(p => p.IsDeleted).ShouldBeFalse(); diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/EfCoreTenantRepository.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/EfCoreTenantRepository.cs index 5da11fe767..a240732236 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/EfCoreTenantRepository.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/EfCoreTenantRepository.cs @@ -69,7 +69,7 @@ namespace Volo.Abp.TenantManagement.EntityFrameworkCore public virtual async Task GetCountAsync(string filter = null, CancellationToken cancellationToken = default) { - return await this + return await (await GetQueryableAsync()) .WhereIf( !filter.IsNullOrWhiteSpace(), u => diff --git a/modules/users/src/Volo.Abp.Users.EntityFrameworkCore/Volo/Abp/Users/EntityFrameworkCore/EfCoreAbpUserRepositoryBase.cs b/modules/users/src/Volo.Abp.Users.EntityFrameworkCore/Volo/Abp/Users/EntityFrameworkCore/EfCoreAbpUserRepositoryBase.cs index 635d9fc8fd..55ed754509 100644 --- a/modules/users/src/Volo.Abp.Users.EntityFrameworkCore/Volo/Abp/Users/EntityFrameworkCore/EfCoreAbpUserRepositoryBase.cs +++ b/modules/users/src/Volo.Abp.Users.EntityFrameworkCore/Volo/Abp/Users/EntityFrameworkCore/EfCoreAbpUserRepositoryBase.cs @@ -22,7 +22,7 @@ namespace Volo.Abp.Users.EntityFrameworkCore public async Task FindByUserNameAsync(string userName, CancellationToken cancellationToken = default) { - return await this.OrderBy(x => x.Id).FirstOrDefaultAsync(u => u.UserName == userName, GetCancellationToken(cancellationToken)); + return await (await GetDbSetAsync()).OrderBy(x => x.Id).FirstOrDefaultAsync(u => u.UserName == userName, GetCancellationToken(cancellationToken)); } public virtual async Task> GetListAsync(IEnumerable ids, CancellationToken cancellationToken = default) From 6a3e4e3e5e8e9bc5769f8f160eeb4e51ce8df9ff Mon Sep 17 00:00:00 2001 From: maliming Date: Sun, 26 Sep 2021 17:10:42 +0800 Subject: [PATCH 32/49] Introduce `AbpMongoDbDateTimeSerializer`. `MongoDb` will normalize the datetime based on `AbpClockOptions`. --- .../Abp/EntityFrameworkCore/AbpDbContext.cs | 24 +++--- .../Volo/Abp/MongoDB/AbpMongoDbContext.cs | 2 + .../MongoDB/AbpMongoDbDateTimeSerializer.cs | 43 ++++++++++ .../Volo/Abp/MongoDB/MongoModelBuilder.cs | 60 +++++++++++++- .../ModelBindingController_Tests.cs | 18 ++--- .../AbpEntityFrameworkCoreTestModule.cs | 4 - .../UnitTestModelCacheKeyFactory.cs | 17 ++++ .../AbpDateTimeValueConverter_Tests.cs | 9 --- .../EFCore_DateTimeKindTests.cs | 66 +++++++++++++++ .../EntityFrameworkCore/TestAppDbContext.cs | 7 ++ .../Serializer/MongoDB_DateTimeKind_Tests.cs | 81 +++++++++++++++++++ .../Abp/TestApp/MongoDb/PersonRepository.cs | 30 +++++++ .../AbpDateTimeValueConverter_Tests.cs | 73 ----------------- .../Abp/TestApp/Testing/DateTimeKind_Tests.cs | 46 +++++++++++ 14 files changed, 371 insertions(+), 109 deletions(-) create mode 100644 framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbDateTimeSerializer.cs create mode 100644 framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/UnitTestModelCacheKeyFactory.cs delete mode 100644 framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/ValueConverters/AbpDateTimeValueConverter_Tests.cs create mode 100644 framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/ValueConverters/EFCore_DateTimeKindTests.cs create mode 100644 framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Serializer/MongoDB_DateTimeKind_Tests.cs create mode 100644 framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/PersonRepository.cs delete mode 100644 framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/AbpDateTimeValueConverter_Tests.cs create mode 100644 framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/DateTimeKind_Tests.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 588b052140..f873c2356e 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs @@ -61,9 +61,9 @@ namespace Volo.Abp.EntityFrameworkCore public IUnitOfWorkManager UnitOfWorkManager => LazyServiceProvider.LazyGetRequiredService(); public IClock Clock => LazyServiceProvider.LazyGetRequiredService(); - + public IDistributedEventBus DistributedEventBus => LazyServiceProvider.LazyGetRequiredService(); - + public ILocalEventBus LocalEventBus => LazyServiceProvider.LazyGetRequiredService(); public ILogger> Logger => LazyServiceProvider.LazyGetService>>(NullLogger>.Instance); @@ -167,9 +167,9 @@ namespace Volo.Abp.EntityFrameworkCore } var result = await base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken); - + PublishEntityEvents(eventReport); - + if (entityChangeList != null) { EntityHistoryHelper.UpdateChangeList(entityChangeList); @@ -285,11 +285,11 @@ namespace Volo.Abp.EntityFrameworkCore } } } - + private void PublishEventsForTrackedEntity(EntityEntry entry) { switch (entry.State) - { + { case EntityState.Added: EntityChangeEventHelper.PublishEntityCreatingEvent(entry.Entity); EntityChangeEventHelper.PublishEntityCreatedEvent(entry.Entity); @@ -308,7 +308,7 @@ namespace Volo.Abp.EntityFrameworkCore EntityChangeEventHelper.PublishEntityUpdatedEvent(entry.Entity); } } - + break; case EntityState.Deleted: EntityChangeEventHelper.PublishEntityDeletingEvent(entry.Entity); @@ -324,11 +324,11 @@ namespace Volo.Abp.EntityFrameworkCore ApplyAbpConcepts(entry); } } - + protected virtual EntityEventReport CreateEventReport() { var eventReport = new EntityEventReport(); - + foreach (var entry in ChangeTracker.Entries().ToList()) { var generatesDomainEventsEntity = entry.Entity as IGeneratesDomainEvents; @@ -369,7 +369,7 @@ namespace Volo.Abp.EntityFrameworkCore return eventReport; } - + protected virtual void ApplyAbpConcepts(EntityEntry entry) { switch (entry.State) @@ -638,7 +638,7 @@ namespace Volo.Abp.EntityFrameworkCore !typeof(TEntity).IsDefined(typeof(OwnedAttribute), true) && !mutableEntityType.IsOwned()) { - if (LazyServiceProvider == null || Clock == null || !Clock.SupportsMultipleTimezone) + if (LazyServiceProvider == null || Clock == null) { return; } @@ -650,7 +650,7 @@ namespace Volo.Abp.EntityFrameworkCore (property.PropertyType == typeof(DateTime) || property.PropertyType == typeof(DateTime?)) && property.CanWrite && - !property.IsDefined(typeof(DisableDateTimeNormalizationAttribute), true) + ReflectionHelper.GetSingleAttributeOfMemberOrDeclaringTypeOrDefault(property) == null ).ToList(); dateTimePropertyInfos.ForEach(property => diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbContext.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbContext.cs index 5e7eb84111..93633e3cc8 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbContext.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbContext.cs @@ -6,6 +6,8 @@ namespace Volo.Abp.MongoDB { public abstract class AbpMongoDbContext : IAbpMongoDbContext, ITransientDependency { + public IAbpLazyServiceProvider LazyServiceProvider { get; set; } + public IMongoModelSource ModelSource { get; set; } public IMongoClient Client { get; private set; } diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbDateTimeSerializer.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbDateTimeSerializer.cs new file mode 100644 index 0000000000..c3e9efba5a --- /dev/null +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbDateTimeSerializer.cs @@ -0,0 +1,43 @@ +using System; +using MongoDB.Bson; +using MongoDB.Bson.Serialization; +using MongoDB.Bson.Serialization.Serializers; + +namespace Volo.Abp.MongoDB +{ + public class AbpMongoDbDateTimeSerializer : DateTimeSerializer + { + protected DateTimeKind DateTimeKind { get; set; } + protected bool DisableDateTimeNormalization{ get; set; } + + public AbpMongoDbDateTimeSerializer(DateTimeKind dateTimeKind , bool disableDateTimeNormalization) + { + DateTimeKind = dateTimeKind; + DisableDateTimeNormalization = disableDateTimeNormalization; + } + + public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, DateTime value) + { + context.Writer.WriteDateTime(DisableDateTimeNormalization + ? ToMillisecondsSinceEpoch(value) + : ToMillisecondsSinceEpoch(DateTime.SpecifyKind(value, DateTimeKind))); + } + + public override DateTime Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) + { + var dateTime = new BsonDateTime(context.Reader.ReadDateTime()).ToUniversalTime(); + return DateTime.SpecifyKind(dateTime, DisableDateTimeNormalization ? DateTimeKind.Unspecified : DateTimeKind); + } + + private static long ToMillisecondsSinceEpoch(DateTime dateTime) + { + return (dateTime - BsonConstants.UnixEpoch).Ticks / 10000L; + } + + // For unit testing. + internal void SetDateTimeKind(DateTimeKind dateTimeKind) + { + DateTimeKind = dateTimeKind; + } + } +} diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoModelBuilder.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoModelBuilder.cs index 6d8706d7ee..1f155fc21d 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoModelBuilder.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoModelBuilder.cs @@ -3,9 +3,13 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; +using System.Reflection; +using Microsoft.Extensions.Options; using MongoDB.Bson; +using MongoDB.Bson.Serialization.Serializers; using MongoDB.Driver; -using Volo.Abp.Domain.Entities; +using Volo.Abp.Reflection; +using Volo.Abp.Timing; namespace Volo.Abp.MongoDB { @@ -20,10 +24,12 @@ namespace Volo.Abp.MongoDB _entityModelBuilders = new Dictionary(); } - public MongoDbContextModel Build(AbpMongoDbContext dbContext) + public virtual MongoDbContextModel Build(AbpMongoDbContext dbContext) { lock (SyncObj) { + var clockOptions = dbContext.LazyServiceProvider?.LazyGetService>(); + var entityModels = _entityModelBuilders .Select(x => x.Value) .Cast() @@ -34,6 +40,33 @@ namespace Volo.Abp.MongoDB foreach (var entityModel in entityModels.Values) { var map = entityModel.As().GetMap(); + + if (clockOptions != null) + { + var dateTimePropertyInfos = entityModel.EntityType.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public) + .Where(property => + (property.PropertyType == typeof(DateTime) || + property.PropertyType == typeof(DateTime?)) && + property.CanWrite + ).ToList(); + + dateTimePropertyInfos.ForEach(property => + { + var disableDateTimeNormalization = + entityModel.EntityType.IsDefined(typeof(DisableDateTimeNormalizationAttribute), true) || + ReflectionHelper.GetSingleAttributeOfMemberOrDeclaringTypeOrDefault(property) != null; + + if (property.PropertyType == typeof(DateTime?)) + { + map.MapProperty(property.Name).SetSerializer(new NullableSerializer().WithSerializer(new AbpMongoDbDateTimeSerializer(clockOptions.Value.Kind, disableDateTimeNormalization))); + } + else + { + map.MapProperty(property.Name).SetSerializer(new AbpMongoDbDateTimeSerializer(clockOptions.Value.Kind, disableDateTimeNormalization)); + } + }); + } + if (!BsonClassMap.IsClassMapRegistered(map.ClassType)) { BsonClassMap.RegisterClassMap(map); @@ -52,6 +85,29 @@ namespace Volo.Abp.MongoDB { var map = new BsonClassMap(baseClass); map.ConfigureAbpConventions(); + + if (clockOptions != null) + { + var dateTimePropertyInfos = baseClass.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public) + .Where(property => + (property.PropertyType == typeof(DateTime) || + property.PropertyType == typeof(DateTime?)) && + property.CanWrite + ).ToList(); + + dateTimePropertyInfos.ForEach(property => + { + if (property.PropertyType == typeof(DateTime?)) + { + map.MapProperty(property.Name).SetSerializer(new NullableSerializer().WithSerializer(new AbpMongoDbDateTimeSerializer(clockOptions.Value.Kind, false))); + } + else + { + map.MapProperty(property.Name).SetSerializer(new AbpMongoDbDateTimeSerializer(clockOptions.Value.Kind, false)); + } + }); + } + BsonClassMap.RegisterClassMap(map); } } diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ModelBinding/ModelBindingController_Tests.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ModelBinding/ModelBindingController_Tests.cs index fcce316772..8ae0cfd9cb 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ModelBinding/ModelBindingController_Tests.cs +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ModelBinding/ModelBindingController_Tests.cs @@ -16,7 +16,7 @@ namespace Volo.Abp.AspNetCore.Mvc.ModelBinding { public abstract class ModelBindingController_Tests : AspNetCoreMvcTestBase { - protected DateTimeKind DateTimeKind { get; set; } + protected DateTimeKind Kind { get; set; } protected override void ConfigureServices(HostBuilderContext context, IServiceCollection services) { @@ -34,7 +34,7 @@ namespace Volo.Abp.AspNetCore.Mvc.ModelBinding response.StatusCode.ShouldBe(HttpStatusCode.OK); var resultAsString = await response.Content.ReadAsStringAsync(); - resultAsString.ShouldBe(DateTimeKind.ToString().ToLower()); + resultAsString.ShouldBe(Kind.ToString().ToLower()); } [Fact] @@ -45,7 +45,7 @@ namespace Volo.Abp.AspNetCore.Mvc.ModelBinding response.StatusCode.ShouldBe(HttpStatusCode.OK); var resultAsString = await response.Content.ReadAsStringAsync(); - resultAsString.ShouldBe(DateTimeKind.ToString().ToLower()); + resultAsString.ShouldBe(Kind.ToString().ToLower()); } [Fact] @@ -89,7 +89,7 @@ namespace Volo.Abp.AspNetCore.Mvc.ModelBinding var resultAsString = await response.Content.ReadAsStringAsync(); //Time parameter(2010-01-01T00:00:00Z) with time zone information, so the default Kind is UTC //https://docs.microsoft.com/en-us/aspnet/core/migration/31-to-50?view=aspnetcore-3.1&tabs=visual-studio#datetime-values-are-model-bound-as-utc-times - resultAsString.ShouldBe($"utc_{DateTimeKind.ToString().ToLower()}_{DateTimeKind.ToString().ToLower()}_utc"); + resultAsString.ShouldBe($"utc_{Kind.ToString().ToLower()}_{Kind.ToString().ToLower()}_utc"); } [Fact] @@ -111,7 +111,7 @@ namespace Volo.Abp.AspNetCore.Mvc.ModelBinding response.StatusCode.ShouldBe(HttpStatusCode.OK); var resultAsString = await response.Content.ReadAsStringAsync(); - resultAsString.ShouldBe($"local_{DateTimeKind.ToString().ToLower()}_{DateTimeKind.ToString().ToLower()}_local"); + resultAsString.ShouldBe($"local_{Kind.ToString().ToLower()}_{Kind.ToString().ToLower()}_local"); } } @@ -119,8 +119,8 @@ namespace Volo.Abp.AspNetCore.Mvc.ModelBinding { protected override void ConfigureServices(HostBuilderContext context, IServiceCollection services) { - DateTimeKind = DateTimeKind.Utc; - services.Configure(x => x.Kind = DateTimeKind); + Kind = DateTimeKind.Utc; + services.Configure(x => x.Kind = Kind); base.ConfigureServices(context, services); } @@ -130,8 +130,8 @@ namespace Volo.Abp.AspNetCore.Mvc.ModelBinding { protected override void ConfigureServices(HostBuilderContext context, IServiceCollection services) { - DateTimeKind = DateTimeKind.Local; - services.Configure(x => x.Kind = DateTimeKind); + Kind = DateTimeKind.Local; + services.Configure(x => x.Kind = Kind); base.ConfigureServices(context, services); } diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreTestModule.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreTestModule.cs index 4f8faef65e..49713b3c1d 100644 --- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreTestModule.cs +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreTestModule.cs @@ -1,4 +1,3 @@ -using System; using Microsoft.Data.Sqlite; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; @@ -13,7 +12,6 @@ using Volo.Abp.Modularity; using Volo.Abp.TestApp; using Volo.Abp.TestApp.Domain; using Volo.Abp.TestApp.EntityFrameworkCore; -using Volo.Abp.Timing; namespace Volo.Abp.EntityFrameworkCore { @@ -55,8 +53,6 @@ namespace Volo.Abp.EntityFrameworkCore abpDbContextConfigurationContext.DbContextOptions.UseSqlite(sqliteConnection); }); }); - - Configure(options => options.Kind = DateTimeKind.Utc); } public override void OnPreApplicationInitialization(ApplicationInitializationContext context) diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/UnitTestModelCacheKeyFactory.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/UnitTestModelCacheKeyFactory.cs new file mode 100644 index 0000000000..0686bfb614 --- /dev/null +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/UnitTestModelCacheKeyFactory.cs @@ -0,0 +1,17 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; + +namespace Volo.Abp.EntityFrameworkCore +{ + /// + /// Avoid unit test caching the configure of the entity. + /// OnModelCreating will be executed multiple times + /// + public class UnitTestModelCacheKeyFactory : IModelCacheKeyFactory + { + public object Create(DbContext context) + { + return context; + } + } +} diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/ValueConverters/AbpDateTimeValueConverter_Tests.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/ValueConverters/AbpDateTimeValueConverter_Tests.cs deleted file mode 100644 index c2793b3b67..0000000000 --- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/ValueConverters/AbpDateTimeValueConverter_Tests.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Volo.Abp.TestApp.Testing; - -namespace Volo.Abp.EntityFrameworkCore.ValueConverters -{ - public class AbpDateTimeValueConverter_Tests : AbpDateTimeValueConverter_Tests - { - - } -} \ No newline at end of file diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/ValueConverters/EFCore_DateTimeKindTests.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/ValueConverters/EFCore_DateTimeKindTests.cs new file mode 100644 index 0000000000..8a39819a2e --- /dev/null +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/ValueConverters/EFCore_DateTimeKindTests.cs @@ -0,0 +1,66 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Shouldly; +using Volo.Abp.TestApp.Domain; +using Volo.Abp.TestApp.Testing; +using Volo.Abp.Timing; +using Xunit; + +namespace Volo.Abp.EntityFrameworkCore.ValueConverters +{ + public abstract class EFCore_DateTimeKindTests : DateTimeKind_Tests + { + [Fact] + public async Task DateTime_Kind_Should_Be_Normalized_In_View_Query_Test() + { + var personName = "bob lee"; + await PersonRepository.InsertAsync(new Person(Guid.NewGuid(), personName, 18) + { + Birthday = DateTime.Parse("2020-01-01 00:00:00"), + LastActive = DateTime.Parse("2020-01-01 00:00:00"), + }, true); + + var person = await PersonRepository.GetViewAsync(personName); + + person.ShouldNotBeNull(); + person.CreationTime.Kind.ShouldBe(Kind); + + person.Birthday.ShouldNotBeNull(); + person.Birthday.Value.Kind.ShouldBe(Kind); + person.Birthday.Value.ToString("yyy-MM-dd HH:mm:ss").ShouldBe("2020-01-01 00:00:00"); + + //LastActive DisableDateTimeNormalization + person.LastActive.ShouldNotBeNull(); + person.LastActive.Value.Kind.ShouldBe(DateTimeKind.Unspecified); + person.LastActive.Value.ToString("yyy-MM-dd HH:mm:ss").ShouldBe("2020-01-01 00:00:00"); + } + } + + public class DateTimeKindTests : EFCore_DateTimeKindTests + { + protected override void AfterAddApplication(IServiceCollection services) + { + Kind = DateTimeKind.Unspecified; + services.Configure(x => x.Kind = Kind); + } + } + + public class DateTimeKindTests_Local : EFCore_DateTimeKindTests + { + protected override void AfterAddApplication(IServiceCollection services) + { + Kind = DateTimeKind.Local; + services.Configure(x => x.Kind = Kind); + } + } + + public class DateTimeKindTests_Utc : EFCore_DateTimeKindTests + { + protected override void AfterAddApplication(IServiceCollection services) + { + Kind = DateTimeKind.Utc; + services.Configure(x => x.Kind = Kind); + } + } +} diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs index 014c9c42db..f7fd1b046d 100644 --- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs @@ -1,5 +1,6 @@ using System; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; using Volo.Abp.DependencyInjection; using Volo.Abp.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore.Modeling; @@ -34,6 +35,12 @@ namespace Volo.Abp.TestApp.EntityFrameworkCore } + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + optionsBuilder.ReplaceService(); + base.OnConfiguring(optionsBuilder); + } + protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Owned(); diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Serializer/MongoDB_DateTimeKind_Tests.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Serializer/MongoDB_DateTimeKind_Tests.cs new file mode 100644 index 0000000000..f691145d60 --- /dev/null +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Serializer/MongoDB_DateTimeKind_Tests.cs @@ -0,0 +1,81 @@ +using System; +using System.Reflection; +using Microsoft.Extensions.DependencyInjection; +using MongoDB.Bson.Serialization; +using MongoDB.Bson.Serialization.Serializers; +using Volo.Abp.TestApp.Testing; +using Volo.Abp.Timing; +using Xunit; + +namespace Volo.Abp.MongoDB.Serializer +{ + [Collection(MongoTestCollection.Name)] + public abstract class MongoDB_DateTimeKind_Tests : DateTimeKind_Tests, IDisposable + { + protected override void AfterAddApplication(IServiceCollection services) + { + // MongoDB uses static properties to store the mapping information, + // We must reconfigure it in the new unit test. + foreach (var registeredClassMap in BsonClassMap.GetRegisteredClassMaps()) + { + var frozen = registeredClassMap.GetType().BaseType?.GetField("_frozen", BindingFlags.NonPublic | BindingFlags.Instance); + frozen?.SetValue(registeredClassMap, false); + + foreach (var declaredMemberMap in registeredClassMap.DeclaredMemberMaps) + { + var serializer = declaredMemberMap.GetSerializer(); + switch (serializer) + { + case AbpMongoDbDateTimeSerializer dateTimeSerializer: + dateTimeSerializer.SetDateTimeKind(Kind); + break; + case NullableSerializer nullableSerializer: + { + var lazySerializer = nullableSerializer.GetType() + ?.GetField("_lazySerializer", BindingFlags.NonPublic | BindingFlags.Instance) + ?.GetValue(serializer)?.As>>(); + + if (lazySerializer?.Value is AbpMongoDbDateTimeSerializer dateTimeSerializer) + { + dateTimeSerializer.SetDateTimeKind(Kind); + } + break; + } + } + } + + frozen?.SetValue(registeredClassMap, true); + } + } + } + + public class DateTimeKindTests_Unspecified : MongoDB_DateTimeKind_Tests + { + protected override void AfterAddApplication(IServiceCollection services) + { + Kind = DateTimeKind.Unspecified; + services.Configure(x => x.Kind = Kind); + base.AfterAddApplication(services); + } + } + + public class DateTimeKindTests_Local : MongoDB_DateTimeKind_Tests + { + protected override void AfterAddApplication(IServiceCollection services) + { + Kind = DateTimeKind.Local; + services.Configure(x => x.Kind = Kind); + base.AfterAddApplication(services); + } + } + + public class DateTimeKindTests_Utc : MongoDB_DateTimeKind_Tests + { + protected override void AfterAddApplication(IServiceCollection services) + { + Kind = DateTimeKind.Utc; + services.Configure(x => x.Kind = Kind); + base.AfterAddApplication(services); + } + } +} diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/PersonRepository.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/PersonRepository.cs new file mode 100644 index 0000000000..3ed46288f1 --- /dev/null +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/PersonRepository.cs @@ -0,0 +1,30 @@ +using System; +using System.Threading.Tasks; +using MongoDB.Driver; +using Volo.Abp.Domain.Repositories.MongoDB; +using Volo.Abp.MongoDB; +using Volo.Abp.TestApp.Domain; + +namespace Volo.Abp.TestApp.MongoDB +{ + public class PersonRepository : MongoDbRepository, IPersonRepository + { + public PersonRepository(IMongoDbContextProvider dbContextProvider) + : base(dbContextProvider) + { + + } + + public async Task GetViewAsync(string name) + { + var person = await (await (await GetCollectionAsync()).FindAsync(x => x.Name == name)).FirstOrDefaultAsync(); + return new PersonView() + { + Name = person.Name, + CreationTime = person.CreationTime, + Birthday = person.Birthday, + LastActive = person.LastActive + }; + } + } +} diff --git a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/AbpDateTimeValueConverter_Tests.cs b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/AbpDateTimeValueConverter_Tests.cs deleted file mode 100644 index e36225e53c..0000000000 --- a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/AbpDateTimeValueConverter_Tests.cs +++ /dev/null @@ -1,73 +0,0 @@ -using System; -using System.Threading.Tasks; -using Microsoft.Extensions.DependencyInjection; -using Shouldly; -using Volo.Abp.Domain.Repositories; -using Volo.Abp.Modularity; -using Volo.Abp.TestApp.Domain; -using Volo.Abp.Timing; -using Xunit; - -namespace Volo.Abp.TestApp.Testing -{ - public abstract class AbpDateTimeValueConverter_Tests : TestAppTestBase - where TStartupModule : IAbpModule - { - private readonly IPersonRepository _personRepository; - - protected AbpDateTimeValueConverter_Tests() - { - _personRepository = GetRequiredService(); - } - - [Fact] - public async Task DateTime_Kind_Should_Be_Normalized_To_UTC_Test() - { - var personId = Guid.Parse("4125582e-d100-4c27-aa84-e4de85830dca"); - await _personRepository.InsertAsync(new Person(personId, "bob lee", 18) - { - Birthday = DateTime.Parse("2020-01-01 00:00:00"), - LastActive = DateTime.Parse("2020-01-01 00:00:00"), - }, true); - - var person = await _personRepository.GetAsync(personId); - - person.ShouldNotBeNull(); - person.CreationTime.Kind.ShouldBe(DateTimeKind.Utc); - - person.Birthday.ShouldNotBeNull(); - person.Birthday.Value.Kind.ShouldBe(DateTimeKind.Utc); - person.Birthday.Value.ToString("yyy-MM-dd HH:mm:ss").ShouldBe("2020-01-01 00:00:00"); - - //LastActive DisableDateTimeNormalization - person.LastActive.ShouldNotBeNull(); - person.LastActive.Value.Kind.ShouldBe(DateTimeKind.Unspecified); - person.LastActive.Value.ToString("yyy-MM-dd HH:mm:ss").ShouldBe("2020-01-01 00:00:00"); - } - - [Fact] - public async Task DateTime_Kind_Should_Be_Normalized_To_UTC_View_Test() - { - var personName = "bob lee"; - await _personRepository.InsertAsync(new Person(Guid.NewGuid(), personName, 18) - { - Birthday = DateTime.Parse("2020-01-01 00:00:00"), - LastActive = DateTime.Parse("2020-01-01 00:00:00"), - }, true); - - var person = await _personRepository.GetViewAsync(personName); - - person.ShouldNotBeNull(); - person.CreationTime.Kind.ShouldBe(DateTimeKind.Utc); - - person.Birthday.ShouldNotBeNull(); - person.Birthday.Value.Kind.ShouldBe(DateTimeKind.Utc); - person.Birthday.Value.ToString("yyy-MM-dd HH:mm:ss").ShouldBe("2020-01-01 00:00:00"); - - //LastActive DisableDateTimeNormalization - person.LastActive.ShouldNotBeNull(); - person.LastActive.Value.Kind.ShouldBe(DateTimeKind.Unspecified); - person.LastActive.Value.ToString("yyy-MM-dd HH:mm:ss").ShouldBe("2020-01-01 00:00:00"); - } - } -} \ No newline at end of file diff --git a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/DateTimeKind_Tests.cs b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/DateTimeKind_Tests.cs new file mode 100644 index 0000000000..2e13db34b8 --- /dev/null +++ b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/DateTimeKind_Tests.cs @@ -0,0 +1,46 @@ +using System; +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.Modularity; +using Volo.Abp.TestApp.Domain; +using Xunit; + +namespace Volo.Abp.TestApp.Testing +{ + public abstract class DateTimeKind_Tests : TestAppTestBase + where TStartupModule : IAbpModule + { + protected IPersonRepository PersonRepository { get; } + protected DateTimeKind Kind { get; set; } + + protected DateTimeKind_Tests() + { + PersonRepository = GetRequiredService(); + } + + [Fact] + public async Task DateTime_Kind_Should_Be_Normalized_Test() + { + var personId = Guid.NewGuid(); + await PersonRepository.InsertAsync(new Person(personId, "bob lee", 18) + { + Birthday = DateTime.Parse("2020-01-01 00:00:00"), + LastActive = DateTime.Parse("2020-01-01 00:00:00"), + }, true); + + var person = await PersonRepository.GetAsync(personId); + + person.ShouldNotBeNull(); + person.CreationTime.Kind.ShouldBe(Kind); + + person.Birthday.ShouldNotBeNull(); + person.Birthday.Value.Kind.ShouldBe(Kind); + person.Birthday.Value.ToString("yyy-MM-dd HH:mm:ss").ShouldBe("2020-01-01 00:00:00"); + + //LastActive DisableDateTimeNormalization + person.LastActive.ShouldNotBeNull(); + person.LastActive.Value.Kind.ShouldBe(DateTimeKind.Unspecified); + person.LastActive.Value.ToString("yyy-MM-dd HH:mm:ss").ShouldBe("2020-01-01 00:00:00"); + } + } +} 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 33/49] 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 34/49] 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 35/49] 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 36/49] 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 3cc326d3cbf41dba17d255cb0916f6d3e48c6989 Mon Sep 17 00:00:00 2001 From: Mehmet Erim Date: Wed, 29 Sep 2021 14:23:58 +0300 Subject: [PATCH 37/49] add angular v4.x to v5.0 migration guide --- docs/en/Migration-Guides/Abp-5_0-Angular.md | 101 ++++++++++++++++++++ docs/en/Migration-Guides/Abp-5_0.md | 5 + docs/en/Migration-Guides/Index.md | 10 +- 3 files changed, 111 insertions(+), 5 deletions(-) create mode 100644 docs/en/Migration-Guides/Abp-5_0-Angular.md create mode 100644 docs/en/Migration-Guides/Abp-5_0.md diff --git a/docs/en/Migration-Guides/Abp-5_0-Angular.md b/docs/en/Migration-Guides/Abp-5_0-Angular.md new file mode 100644 index 0000000000..6cdb7af7c9 --- /dev/null +++ b/docs/en/Migration-Guides/Abp-5_0-Angular.md @@ -0,0 +1,101 @@ +# Angular UI v4.x to v5.0 Migration Guide + +## Breaking Changes + +### Overall + +See the overall list of breaking changes: + +- Bootstrap 5 implementation [#10067](https://github.com/abpframework/abp/issues/10067) +- Remove NGXS dependency & states [#9952](https://github.com/abpframework/abp/issues/9952) +- Install @angular/localize package to startup templates [#10099](https://github.com/abpframework/abp/issues/10099) +- Create new secondary entrypoints and move the related proxies to there [#10060](https://github.com/abpframework/abp/issues/10060) +- Move SettingTabsService to @abp/ng.setting-management/config package from @abp/ng.core [#10061](https://github.com/abpframework/abp/issues/10061) +- Make the @abp/ng.account dependent on @abp/ng.identity [#10059](https://github.com/abpframework/abp/issues/10059) +- Set default abp-modal size medium [#10118](https://github.com/abpframework/abp/issues/10118) +- Update all dependency versions to the latest [#9806](https://github.com/abpframework/abp/issues/9806) +- Chart.js big include with CommonJS warning [#7472](https://github.com/abpframework/abp/issues/7472) + +### Angular v12 + +The new ABP Angular UI is based on Angular v12. We started to compile Angular UI packages with the Ivy compilation. Therefore, **new packages only work with Angular v12**. If you are still on the older version of Angular v12, you have to update to Angular v12. The update is usually very easy. See [Angular Update Guide](https://update.angular.io/?l=2&v=11.0-12.0) for further information. + +### Bootstrap 5 + +TODO + +### NGXS has been removed + +We aim to make the ABP Framework free of any state-management solutions. ABP developers should be able to use the ABP Framework with any library/framework of their choice. So, we decided to remove NGXS from ABP packages. + +If you'd like to use NGXS after upgrading to v5.0, you have to install the NGXS to your project. The package can be installed with the following command: + +```bash +npm install @ngxs/store + +# or + +yarn add @ngxs/store +``` + +NGXS states and actions, some namespaces have been removed. See [this issue](https://github.com/abpframework/abp/issues/9952) for the details. + +If you don't want to use the NGXS, you should remove all NGXS related imports, injections, etc., from your project. + +### @angular/localize package + +[`@angular/localize`](https://angular.io/api/localize) dependency has been removed from `@abp/ng.core` package. The package must be installed in your app. Run the following command to install: + +```bash +npm install @angular/localize + +# or + +yarn add @angular/localize +``` + +> ABP Angular UI packages are not dependent on the `@angular/localize` package. However, some packages (like `@ng-bootstrap/ng-bootstrap`) depend on the package. Thus, this package needs to be installed in your project. + +### Proxy endpoints + +New endpoints named proxy have been created, related proxies have moved. +For example; before v5.0, `IdentityUserService` could be imported from `@abp/ng.identity`. As of v5.0, the service can be imported from `@abp/ng.identity/proxy`. See an example: + +```ts +import { IdentityUserService } from '@abp/ng.identity/proxy'; + +@Component({}) +export class YourComponent { + constructor(private identityUserService: IdentityUserService) {} +} +``` + +Following proxies have been affected: + +- `@abp/ng.account` to `@abp/ng.account.core/proxy` +- `@abp/ng.feature-management` to `@abp/ng.feature-management/proxy` +- `@abp/ng.identity` to `@abp/ng.identity/proxy` +- `@abp/ng.permission-management` to `@abp/ng.permission-management/proxy` +- `@abp/ng.tenant-management` to `@abp/ng.tenant-management/proxy` +- **ProfileService** is deleted from `@abp/ng.core`. Instead, you can import it from `@abp/ng.identity/proxy` + +### SettingTabsService + +**SettingTabsService** has moved from `@abp/ng.core` to `@abp/ng.setting-management/config`. + +### ChartComponent + +`ChartComponent` has moved from `@abp/ng.theme.shared` to `@abp/ng.components/chart.js`. To use the component, you need to import the `ChartModule` to your module as follows: + +```ts +import { ChartModule } from '@abp/ng.components/chart.js'; + +@NgModule({ + imports: [ + ChartModule, + // ... + ], + // ... +}) +export class YourFeatureModule {} +``` diff --git a/docs/en/Migration-Guides/Abp-5_0.md b/docs/en/Migration-Guides/Abp-5_0.md new file mode 100644 index 0000000000..7e5a00a75b --- /dev/null +++ b/docs/en/Migration-Guides/Abp-5_0.md @@ -0,0 +1,5 @@ +# ABP Framework 3.3 to 4.0 Migration Guide + +## Angular UI + +See the [Angular UI Migration Guide](Abp-5_0-Angular.md). diff --git a/docs/en/Migration-Guides/Index.md b/docs/en/Migration-Guides/Index.md index c7bee5a82a..909f6c0998 100644 --- a/docs/en/Migration-Guides/Index.md +++ b/docs/en/Migration-Guides/Index.md @@ -1,7 +1,7 @@ # ABP Framework Migration Guides -* [4.2 to 4.3](Abp-4_3.md) -* [4.x to 4.2](Abp-4_2.md) -* [3.3.x to 4.0](Abp-4_0.md) -* [2.9.x to 3.0](../UI/Angular/Migration-Guide-v3.md) - +- [4.x to 5.0](Abp-5_0.md) +- [4.2 to 4.3](Abp-4_3.md) +- [4.x to 4.2](Abp-4_2.md) +- [3.3.x to 4.0](Abp-4_0.md) +- [2.9.x to 3.0](../UI/Angular/Migration-Guide-v3.md) From 240ec5b9ed048cb66828107255cffc414bf33a2a Mon Sep 17 00:00:00 2001 From: Mehmet Erim Date: Wed, 29 Sep 2021 14:25:52 +0300 Subject: [PATCH 38/49] Update Abp-5_0.md --- docs/en/Migration-Guides/Abp-5_0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/Migration-Guides/Abp-5_0.md b/docs/en/Migration-Guides/Abp-5_0.md index 7e5a00a75b..5ae3fc87fd 100644 --- a/docs/en/Migration-Guides/Abp-5_0.md +++ b/docs/en/Migration-Guides/Abp-5_0.md @@ -1,4 +1,4 @@ -# ABP Framework 3.3 to 4.0 Migration Guide +# ABP Framework v4.x to v5.0 Migration Guide ## Angular UI From b809ee50e329d341f64f271c3d0eb05568d56379 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Thu, 30 Sep 2021 00:01:57 +0800 Subject: [PATCH 39/49] 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 40/49] 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 c56f38ee596c83d566b3757620094086b3dad85d Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 30 Sep 2021 10:05:30 +0800 Subject: [PATCH 41/49] Add `ValueGeneratedOnAdd`. --- .../Migrations/20210909052638_Initial.Designer.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20210909052638_Initial.Designer.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20210909052638_Initial.Designer.cs index 1c6326a5b6..fa24bfe18c 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20210909052638_Initial.Designer.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20210909052638_Initial.Designer.cs @@ -365,6 +365,7 @@ namespace MyCompanyName.MyProjectName.Migrations modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => { b.Property("Id") + .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); b.Property("ConcurrencyStamp") @@ -411,6 +412,7 @@ namespace MyCompanyName.MyProjectName.Migrations modelBuilder.Entity("Volo.Abp.Identity.IdentityLinkUser", b => { b.Property("Id") + .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); b.Property("SourceTenantId") @@ -437,6 +439,7 @@ namespace MyCompanyName.MyProjectName.Migrations modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => { b.Property("Id") + .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); b.Property("ConcurrencyStamp") @@ -513,6 +516,7 @@ namespace MyCompanyName.MyProjectName.Migrations modelBuilder.Entity("Volo.Abp.Identity.IdentitySecurityLog", b => { b.Property("Id") + .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); b.Property("Action") @@ -587,6 +591,7 @@ namespace MyCompanyName.MyProjectName.Migrations modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => { b.Property("Id") + .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); b.Property("AccessFailedCount") @@ -869,6 +874,7 @@ namespace MyCompanyName.MyProjectName.Migrations modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => { b.Property("Id") + .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); b.Property("Code") @@ -1860,6 +1866,7 @@ namespace MyCompanyName.MyProjectName.Migrations modelBuilder.Entity("Volo.Abp.TenantManagement.Tenant", b => { b.Property("Id") + .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); b.Property("ConcurrencyStamp") From 48340817a28c451669b17daa7ef0caf7963e8451 Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 30 Sep 2021 10:46:10 +0800 Subject: [PATCH 42/49] Add `ValueGeneratedOnAdd`. --- .../Migrations/MyProjectNameDbContextModelSnapshot.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs index 1812b59627..928c1b96eb 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs @@ -363,6 +363,7 @@ namespace MyCompanyName.MyProjectName.Migrations modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => { b.Property("Id") + .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); b.Property("ConcurrencyStamp") @@ -409,6 +410,7 @@ namespace MyCompanyName.MyProjectName.Migrations modelBuilder.Entity("Volo.Abp.Identity.IdentityLinkUser", b => { b.Property("Id") + .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); b.Property("SourceTenantId") @@ -435,6 +437,7 @@ namespace MyCompanyName.MyProjectName.Migrations modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => { b.Property("Id") + .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); b.Property("ConcurrencyStamp") @@ -511,6 +514,7 @@ namespace MyCompanyName.MyProjectName.Migrations modelBuilder.Entity("Volo.Abp.Identity.IdentitySecurityLog", b => { b.Property("Id") + .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); b.Property("Action") @@ -585,6 +589,7 @@ namespace MyCompanyName.MyProjectName.Migrations modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => { b.Property("Id") + .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); b.Property("AccessFailedCount") @@ -867,6 +872,7 @@ namespace MyCompanyName.MyProjectName.Migrations modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => { b.Property("Id") + .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); b.Property("Code") @@ -1858,6 +1864,7 @@ namespace MyCompanyName.MyProjectName.Migrations modelBuilder.Entity("Volo.Abp.TenantManagement.Tenant", b => { b.Property("Id") + .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); b.Property("ConcurrencyStamp") From 2eddc9aa2b7d4001501f097e95bb04b6325a53ad Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 30 Sep 2021 14:38:26 +0800 Subject: [PATCH 43/49] Add an options to disable the `AbpMongoDbDateTimeSerializer`. --- .../Volo/Abp/MongoDB/AbpMongoDbOptions.cs | 18 ++++++++ .../Volo/Abp/MongoDB/MongoModelBuilder.cs | 19 +++++---- .../Serializer/MongoDB_DateTimeKind_Tests.cs | 41 ++++++++++++++++++- 3 files changed, 70 insertions(+), 8 deletions(-) create mode 100644 framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbOptions.cs diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbOptions.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbOptions.cs new file mode 100644 index 0000000000..21502e0cf8 --- /dev/null +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbOptions.cs @@ -0,0 +1,18 @@ +using Volo.Abp.Timing; + +namespace Volo.Abp.MongoDB +{ + public class AbpMongoDbOptions + { + /// + /// Serializer the datetime based on in MongoDb. + /// Default: true. + /// + public bool UseAbpClockHandleDateTime { get; set; } + + public AbpMongoDbOptions() + { + UseAbpClockHandleDateTime = true; + } + } +} diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoModelBuilder.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoModelBuilder.cs index 1f155fc21d..03f3b52572 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoModelBuilder.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoModelBuilder.cs @@ -28,7 +28,7 @@ namespace Volo.Abp.MongoDB { lock (SyncObj) { - var clockOptions = dbContext.LazyServiceProvider?.LazyGetService>(); + var useAbpClockHandleDateTime = dbContext.LazyServiceProvider.LazyGetRequiredService>().Value.UseAbpClockHandleDateTime; var entityModels = _entityModelBuilders .Select(x => x.Value) @@ -41,7 +41,7 @@ namespace Volo.Abp.MongoDB { var map = entityModel.As().GetMap(); - if (clockOptions != null) + if (useAbpClockHandleDateTime) { var dateTimePropertyInfos = entityModel.EntityType.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public) .Where(property => @@ -58,11 +58,11 @@ namespace Volo.Abp.MongoDB if (property.PropertyType == typeof(DateTime?)) { - map.MapProperty(property.Name).SetSerializer(new NullableSerializer().WithSerializer(new AbpMongoDbDateTimeSerializer(clockOptions.Value.Kind, disableDateTimeNormalization))); + map.MapProperty(property.Name).SetSerializer(new NullableSerializer().WithSerializer(new AbpMongoDbDateTimeSerializer(GetDateTimeKind(dbContext), disableDateTimeNormalization))); } else { - map.MapProperty(property.Name).SetSerializer(new AbpMongoDbDateTimeSerializer(clockOptions.Value.Kind, disableDateTimeNormalization)); + map.MapProperty(property.Name).SetSerializer(new AbpMongoDbDateTimeSerializer(GetDateTimeKind(dbContext), disableDateTimeNormalization)); } }); } @@ -86,7 +86,7 @@ namespace Volo.Abp.MongoDB var map = new BsonClassMap(baseClass); map.ConfigureAbpConventions(); - if (clockOptions != null) + if (useAbpClockHandleDateTime) { var dateTimePropertyInfos = baseClass.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public) .Where(property => @@ -99,11 +99,11 @@ namespace Volo.Abp.MongoDB { if (property.PropertyType == typeof(DateTime?)) { - map.MapProperty(property.Name).SetSerializer(new NullableSerializer().WithSerializer(new AbpMongoDbDateTimeSerializer(clockOptions.Value.Kind, false))); + map.MapProperty(property.Name).SetSerializer(new NullableSerializer().WithSerializer(new AbpMongoDbDateTimeSerializer(GetDateTimeKind(dbContext), false))); } else { - map.MapProperty(property.Name).SetSerializer(new AbpMongoDbDateTimeSerializer(clockOptions.Value.Kind, false)); + map.MapProperty(property.Name).SetSerializer(new AbpMongoDbDateTimeSerializer(GetDateTimeKind(dbContext), false)); } }); } @@ -116,6 +116,11 @@ namespace Volo.Abp.MongoDB } } + private DateTimeKind GetDateTimeKind(AbpMongoDbContext dbContext) + { + return dbContext.LazyServiceProvider.LazyGetRequiredService>().Value.Kind; + } + public virtual void Entity(Action> buildAction = null) { var model = (IMongoEntityModelBuilder)_entityModelBuilders.GetOrAdd( diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Serializer/MongoDB_DateTimeKind_Tests.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Serializer/MongoDB_DateTimeKind_Tests.cs index f691145d60..39a685380b 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Serializer/MongoDB_DateTimeKind_Tests.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Serializer/MongoDB_DateTimeKind_Tests.cs @@ -1,8 +1,11 @@ using System; using System.Reflection; +using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using MongoDB.Bson.Serialization; using MongoDB.Bson.Serialization.Serializers; +using Shouldly; +using Volo.Abp.TestApp.Domain; using Volo.Abp.TestApp.Testing; using Volo.Abp.Timing; using Xunit; @@ -10,7 +13,7 @@ using Xunit; namespace Volo.Abp.MongoDB.Serializer { [Collection(MongoTestCollection.Name)] - public abstract class MongoDB_DateTimeKind_Tests : DateTimeKind_Tests, IDisposable + public abstract class MongoDB_DateTimeKind_Tests : DateTimeKind_Tests { protected override void AfterAddApplication(IServiceCollection services) { @@ -78,4 +81,40 @@ namespace Volo.Abp.MongoDB.Serializer base.AfterAddApplication(services); } } + + [Collection(MongoTestCollection.Name)] + public class DisableDateTimeKindTests : TestAppTestBase + { + protected IPersonRepository PersonRepository { get; } + + public DisableDateTimeKindTests() + { + PersonRepository = GetRequiredService(); + } + + protected override void AfterAddApplication(IServiceCollection services) + { + services.Configure(x => x.UseAbpClockHandleDateTime = false); + base.AfterAddApplication(services); + } + + [Fact] + public async Task DateTime_Kind_Should_Be_Normalized_By_MongoDb_Test() + { + var personId = Guid.NewGuid(); + await PersonRepository.InsertAsync(new Person(personId, "bob lee", 18) + { + Birthday = DateTime.Parse("2020-01-01 00:00:00"), + LastActive = DateTime.Parse("2020-01-01 00:00:00"), + }, true); + + var person = await PersonRepository.GetAsync(personId); + + person.ShouldNotBeNull(); + person.CreationTime.Kind.ShouldBe(DateTimeKind.Utc); + + person.Birthday.ShouldNotBeNull(); + person.Birthday.Value.Kind.ShouldBe(DateTimeKind.Utc); + } + } } From 1962158928e65839f4b154bef20c9df30fb40961 Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 30 Sep 2021 15:09:42 +0800 Subject: [PATCH 44/49] Create Abp-5_0.md --- docs/en/Migration-Guides/Abp-5_0.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 docs/en/Migration-Guides/Abp-5_0.md diff --git a/docs/en/Migration-Guides/Abp-5_0.md b/docs/en/Migration-Guides/Abp-5_0.md new file mode 100644 index 0000000000..7f23f5ed19 --- /dev/null +++ b/docs/en/Migration-Guides/Abp-5_0.md @@ -0,0 +1,10 @@ +# ABP Framework 4.x to 5.0 Migration Guide + +## MongoDB + +Framework will serializer the datetime based on [AbpClockOptions](https://docs.abp.io/en/abp/latest/Timing#clock-options) start from 5.0, before `DateTime` values in MongoDB are [always saved as UTC](https://mongodb.github.io/mongo-csharp-driver/2.13/reference/bson/mapping/#datetime-serialization-options). + +You can disable this behavior by configure `AbpMongoDbOptions`. +```cs +services.Configure(x => x.UseAbpClockHandleDateTime = false); +``` From 3ee9f57c9dd50a6ecb77b121cb74808aaae17e47 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Thu, 30 Sep 2021 15:17:19 +0800 Subject: [PATCH 45/49] 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 46/49] 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 47/49] 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) From 9364884ad5c7d55e1b2f7d83983bb5ae7f59578e Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Thu, 30 Sep 2021 16:25:01 +0800 Subject: [PATCH 48/49] Update distDemoApp to NET6.0 --- .../DistDemoApp.MongoDbKafka.csproj | 2 +- .../DistDemoApp.MongoDbRebus.csproj | 2 +- .../DistEvents/DistDemoApp.Shared/DistDemoApp.Shared.csproj | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test/DistEvents/DistDemoApp.MongoDbKafka/DistDemoApp.MongoDbKafka.csproj b/test/DistEvents/DistDemoApp.MongoDbKafka/DistDemoApp.MongoDbKafka.csproj index a503c6f6c0..dbb980b427 100644 --- a/test/DistEvents/DistDemoApp.MongoDbKafka/DistDemoApp.MongoDbKafka.csproj +++ b/test/DistEvents/DistDemoApp.MongoDbKafka/DistDemoApp.MongoDbKafka.csproj @@ -2,7 +2,7 @@ Exe - net5.0 + net6.0 DistDemoApp diff --git a/test/DistEvents/DistDemoApp.MongoDbRebus/DistDemoApp.MongoDbRebus.csproj b/test/DistEvents/DistDemoApp.MongoDbRebus/DistDemoApp.MongoDbRebus.csproj index c102adb382..5698855ebb 100644 --- a/test/DistEvents/DistDemoApp.MongoDbRebus/DistDemoApp.MongoDbRebus.csproj +++ b/test/DistEvents/DistDemoApp.MongoDbRebus/DistDemoApp.MongoDbRebus.csproj @@ -2,7 +2,7 @@ Exe - net5.0 + net6.0 DistDemoApp diff --git a/test/DistEvents/DistDemoApp.Shared/DistDemoApp.Shared.csproj b/test/DistEvents/DistDemoApp.Shared/DistDemoApp.Shared.csproj index 4dc9d1dd64..4f5cb8ad84 100644 --- a/test/DistEvents/DistDemoApp.Shared/DistDemoApp.Shared.csproj +++ b/test/DistEvents/DistDemoApp.Shared/DistDemoApp.Shared.csproj @@ -1,10 +1,10 @@ - net5.0 + net6.0 DistDemoApp - + @@ -13,7 +13,7 @@ - + From a989d56168000e5a82f46846a7bc0c46ed994ba9 Mon Sep 17 00:00:00 2001 From: Berkan Sasmaz Date: Thu, 30 Sep 2021 11:31:36 +0300 Subject: [PATCH 49/49] Add missing localizations --- .../Admin/Localization/Resources/en.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json index f7094c94a7..9410a7813f 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json @@ -312,7 +312,6 @@ "PaymentStateSetTo" : "Payment state set to {0}", "ChangeState": "Change State", "Permission:TrialLicense" : "Trial License", - "Permission:ManageTrialLicense": "Manage Trial License", "Menu:TrialLicenses": "Trial Licenses", "TrialLicenses": "Trial Licenses", "UserNameFilter": "Username", @@ -340,8 +339,8 @@ "Activated": "Activated", "PurchasedToNormalLicense": "Purchased", "Expired": "Expired", - "TrialLicenseDeletionWarningMessage": "Trial license and if any organization and qa organization will be deleted!", - "IsTrial": "Is trial", + "TrialLicenseDeletionWarningMessage": "Are you sure you want to delete the trial license? Trial license, organization, support accounts will be deleted!", + "LicenseCategoryFilter": "License category", "Volo.AbpIo.Commercial:030000": "You already used your trial period.", "Volo.AbpIo.Commercial:030001": "This organization name already exists.", "Volo.AbpIo.Commercial:030002": "Once activated, trial license cannot be set to requested!", @@ -349,6 +348,7 @@ "Volo.AbpIo.Commercial:030004": "Status could not be changed due to an unexpected error!", "Volo.AbpIo.Commercial:030005": "Start date and end date cannot be given when the trial license is in the requested state!", "Volo.AbpIo.Commercial:030006": "End date must always be greater than start date!", - "Volo.AbpIo.Commercial:030007": "This trial license has already been activated once!" + "Volo.AbpIo.Commercial:030007": "This trial license has already been activated once!", + "Volo.AbpIo.Commercial:030008": "Purchase date can be set only when status is Purchased!", } }