Browse Source

Inform when a new distributed message received or sent.

Resolve #16321
pull/16333/head
maliming 3 years ago
parent
commit
3d3e024f8f
No known key found for this signature in database GPG Key ID: A646B9CB645ECEA4
  1. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/Controllers/AbpAspNetCoreMvcDaprEventsController.cs
  2. 10
      framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/DistributedEventReceived.cs
  3. 10
      framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/DistributedEventSent.cs
  4. 10
      framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/DistributedEventSource.cs
  5. 28
      framework/src/Volo.Abp.EventBus.Azure/Volo/Abp/EventBus/Azure/AzureDistributedEventBus.cs
  6. 25
      framework/src/Volo.Abp.EventBus.Dapr/Volo/Abp/EventBus/Dapr/DaprDistributedEventBus.cs
  7. 43
      framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs
  8. 34
      framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs
  9. 31
      framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventBus.cs
  10. 62
      framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs
  11. 28
      framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/LocalDistributedEventBus.cs
  12. 8
      framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventBusBase.cs
  13. 42
      framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Local/LocalEventBus.cs
  14. 2
      framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbDateTimeSerializer.cs
  15. 22
      framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Distributed/DistributedEventHandles.cs
  16. 44
      framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Distributed/LocalDistributedEventBus_Test.cs

2
framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/Controllers/AbpAspNetCoreMvcDaprEventsController.cs

@ -32,7 +32,7 @@ public class AbpAspNetCoreMvcDaprEventsController : AbpController
var distributedEventBus = HttpContext.RequestServices.GetRequiredService<DaprDistributedEventBus>(); var distributedEventBus = HttpContext.RequestServices.GetRequiredService<DaprDistributedEventBus>();
var eventData = daprSerializer.Deserialize(data, distributedEventBus.GetEventType(topic)); var eventData = daprSerializer.Deserialize(data, distributedEventBus.GetEventType(topic));
await distributedEventBus.TriggerHandlersAsync(distributedEventBus.GetEventType(topic), eventData); await distributedEventBus.DaprTriggerHandlersDirectAsync(distributedEventBus.GetEventType(topic), eventData);
return Ok(); return Ok();
} }
} }

10
framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/DistributedEventReceived.cs

@ -0,0 +1,10 @@
namespace Volo.Abp.EventBus.Distributed;
public class DistributedEventReceived
{
public DistributedEventSource Source { get; set; }
public string EventName { get; set; }
public object EventData { get; set; }
}

10
framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/DistributedEventSent.cs

@ -0,0 +1,10 @@
namespace Volo.Abp.EventBus.Distributed;
public class DistributedEventSent
{
public DistributedEventSource Source { get; set; }
public string EventName { get; set; }
public object EventData { get; set; }
}

10
framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/DistributedEventSource.cs

@ -0,0 +1,10 @@
namespace Volo.Abp.EventBus.Distributed;
public enum DistributedEventSource
{
Direct,
Inbox,
Outbox
}

28
framework/src/Volo.Abp.EventBus.Azure/Volo/Abp/EventBus/Azure/AzureDistributedEventBus.cs

@ -9,6 +9,7 @@ using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.EventBus.Distributed; using Volo.Abp.EventBus.Distributed;
using Volo.Abp.AzureServiceBus; using Volo.Abp.AzureServiceBus;
using Volo.Abp.EventBus.Local;
using Volo.Abp.Guids; using Volo.Abp.Guids;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
using Volo.Abp.Threading; using Volo.Abp.Threading;
@ -40,14 +41,16 @@ public class AzureDistributedEventBus : DistributedEventBusBase, ISingletonDepen
IAzureServiceBusSerializer serializer, IAzureServiceBusSerializer serializer,
IAzureServiceBusMessageConsumerFactory messageConsumerFactory, IAzureServiceBusMessageConsumerFactory messageConsumerFactory,
IPublisherPool publisherPool, IPublisherPool publisherPool,
IEventHandlerInvoker eventHandlerInvoker) IEventHandlerInvoker eventHandlerInvoker,
ILocalEventBus localEventBus)
: base(serviceScopeFactory, : base(serviceScopeFactory,
currentTenant, currentTenant,
unitOfWorkManager, unitOfWorkManager,
abpDistributedEventBusOptions, abpDistributedEventBusOptions,
guidGenerator, guidGenerator,
clock, clock,
eventHandlerInvoker) eventHandlerInvoker,
localEventBus)
{ {
_options = abpAzureEventBusOptions.Value; _options = abpAzureEventBusOptions.Value;
_serializer = serializer; _serializer = serializer;
@ -88,12 +91,19 @@ public class AzureDistributedEventBus : DistributedEventBusBase, ISingletonDepen
var eventData = _serializer.Deserialize(message.Body.ToArray(), eventType); var eventData = _serializer.Deserialize(message.Body.ToArray(), eventType);
await TriggerHandlersAsync(eventType, eventData); await TriggerHandlersDirectAsync(eventType, eventData);
} }
public async override Task PublishFromOutboxAsync(OutgoingEventInfo outgoingEvent, OutboxConfig outboxConfig) public async override Task PublishFromOutboxAsync(OutgoingEventInfo outgoingEvent, OutboxConfig outboxConfig)
{ {
await PublishAsync(outgoingEvent.EventName, outgoingEvent.EventData, outgoingEvent.Id); await PublishAsync(outgoingEvent.EventName, outgoingEvent.EventData, outgoingEvent.Id);
await TriggerDistributedEventSentAsync(new DistributedEventSent()
{
Source = DistributedEventSource.Outbox,
EventName = outgoingEvent.EventName,
EventData = outgoingEvent.EventData
});
} }
public async override Task PublishManyFromOutboxAsync(IEnumerable<OutgoingEventInfo> outgoingEvents, OutboxConfig outboxConfig) public async override Task PublishManyFromOutboxAsync(IEnumerable<OutgoingEventInfo> outgoingEvents, OutboxConfig outboxConfig)
@ -123,6 +133,16 @@ public class AzureDistributedEventBus : DistributedEventBusBase, ISingletonDepen
} }
await publisher.SendMessagesAsync(messageBatch); await publisher.SendMessagesAsync(messageBatch);
foreach (var outgoingEvent in outgoingEventArray)
{
await TriggerDistributedEventSentAsync(new DistributedEventSent()
{
Source = DistributedEventSource.Outbox,
EventName = outgoingEvent.EventName,
EventData = outgoingEvent.EventData
});
}
} }
public async override Task ProcessFromInboxAsync(IncomingEventInfo incomingEvent, InboxConfig inboxConfig) public async override Task ProcessFromInboxAsync(IncomingEventInfo incomingEvent, InboxConfig inboxConfig)
@ -135,7 +155,7 @@ public class AzureDistributedEventBus : DistributedEventBusBase, ISingletonDepen
var eventData = _serializer.Deserialize(incomingEvent.EventData, eventType); var eventData = _serializer.Deserialize(incomingEvent.EventData, eventType);
var exceptions = new List<Exception>(); var exceptions = new List<Exception>();
await TriggerHandlersAsync(eventType, eventData, exceptions, inboxConfig); await TriggerHandlersFromInboxAsync(eventType, eventData, exceptions, inboxConfig);
if (exceptions.Any()) if (exceptions.Any())
{ {
ThrowOriginalExceptions(eventType, exceptions); ThrowOriginalExceptions(eventType, exceptions);

25
framework/src/Volo.Abp.EventBus.Dapr/Volo/Abp/EventBus/Dapr/DaprDistributedEventBus.cs

@ -8,6 +8,7 @@ using Microsoft.Extensions.Options;
using Volo.Abp.Dapr; using Volo.Abp.Dapr;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.EventBus.Distributed; using Volo.Abp.EventBus.Distributed;
using Volo.Abp.EventBus.Local;
using Volo.Abp.Guids; using Volo.Abp.Guids;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
using Volo.Abp.Threading; using Volo.Abp.Threading;
@ -37,8 +38,9 @@ public class DaprDistributedEventBus : DistributedEventBusBase, ISingletonDepend
IEventHandlerInvoker eventHandlerInvoker, IEventHandlerInvoker eventHandlerInvoker,
IDaprSerializer serializer, IDaprSerializer serializer,
IOptions<AbpDaprEventBusOptions> daprEventBusOptions, IOptions<AbpDaprEventBusOptions> daprEventBusOptions,
IAbpDaprClientFactory daprClientFactory) IAbpDaprClientFactory daprClientFactory,
: base(serviceScopeFactory, currentTenant, unitOfWorkManager, abpDistributedEventBusOptions, guidGenerator, clock, eventHandlerInvoker) ILocalEventBus localEventBus)
: base(serviceScopeFactory, currentTenant, unitOfWorkManager, abpDistributedEventBusOptions, guidGenerator, clock, eventHandlerInvoker, localEventBus)
{ {
Serializer = serializer; Serializer = serializer;
DaprEventBusOptions = daprEventBusOptions.Value; DaprEventBusOptions = daprEventBusOptions.Value;
@ -142,6 +144,12 @@ public class DaprDistributedEventBus : DistributedEventBusBase, ISingletonDepend
public override async Task PublishFromOutboxAsync(OutgoingEventInfo outgoingEvent, OutboxConfig outboxConfig) public override async Task PublishFromOutboxAsync(OutgoingEventInfo outgoingEvent, OutboxConfig outboxConfig)
{ {
await PublishToDaprAsync(outgoingEvent.EventName, Serializer.Deserialize(outgoingEvent.EventData, GetEventType(outgoingEvent.EventName))); await PublishToDaprAsync(outgoingEvent.EventName, Serializer.Deserialize(outgoingEvent.EventData, GetEventType(outgoingEvent.EventName)));
await TriggerDistributedEventSentAsync(new DistributedEventSent()
{
Source = DistributedEventSource.Outbox,
EventName = outgoingEvent.EventName,
EventData = outgoingEvent.EventData
});
} }
public override async Task PublishManyFromOutboxAsync(IEnumerable<OutgoingEventInfo> outgoingEvents, OutboxConfig outboxConfig) public override async Task PublishManyFromOutboxAsync(IEnumerable<OutgoingEventInfo> outgoingEvents, OutboxConfig outboxConfig)
@ -151,9 +159,20 @@ public class DaprDistributedEventBus : DistributedEventBusBase, ISingletonDepend
foreach (var outgoingEvent in outgoingEventArray) foreach (var outgoingEvent in outgoingEventArray)
{ {
await PublishToDaprAsync(outgoingEvent.EventName, Serializer.Deserialize(outgoingEvent.EventData, GetEventType(outgoingEvent.EventName))); await PublishToDaprAsync(outgoingEvent.EventName, Serializer.Deserialize(outgoingEvent.EventData, GetEventType(outgoingEvent.EventName)));
await TriggerDistributedEventSentAsync(new DistributedEventSent()
{
Source = DistributedEventSource.Outbox,
EventName = outgoingEvent.EventName,
EventData = outgoingEvent.EventData
});
} }
} }
public virtual async Task DaprTriggerHandlersDirectAsync(Type eventType, object eventData)
{
await TriggerHandlersDirectAsync(eventType, eventData);
}
public async override Task ProcessFromInboxAsync(IncomingEventInfo incomingEvent, InboxConfig inboxConfig) public async override Task ProcessFromInboxAsync(IncomingEventInfo incomingEvent, InboxConfig inboxConfig)
{ {
var eventType = EventTypes.GetOrDefault(incomingEvent.EventName); var eventType = EventTypes.GetOrDefault(incomingEvent.EventName);
@ -164,7 +183,7 @@ public class DaprDistributedEventBus : DistributedEventBusBase, ISingletonDepend
var eventData = Serializer.Deserialize(incomingEvent.EventData, eventType); var eventData = Serializer.Deserialize(incomingEvent.EventData, eventType);
var exceptions = new List<Exception>(); var exceptions = new List<Exception>();
await TriggerHandlersAsync(eventType, eventData, exceptions, inboxConfig); await TriggerHandlersFromInboxAsync(eventType, eventData, exceptions, inboxConfig);
if (exceptions.Any()) if (exceptions.Any())
{ {
ThrowOriginalExceptions(eventType, exceptions); ThrowOriginalExceptions(eventType, exceptions);

43
framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs

@ -8,6 +8,7 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.EventBus.Distributed; using Volo.Abp.EventBus.Distributed;
using Volo.Abp.EventBus.Local;
using Volo.Abp.Guids; using Volo.Abp.Guids;
using Volo.Abp.Kafka; using Volo.Abp.Kafka;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
@ -40,7 +41,8 @@ public class KafkaDistributedEventBus : DistributedEventBusBase, ISingletonDepen
IProducerPool producerPool, IProducerPool producerPool,
IGuidGenerator guidGenerator, IGuidGenerator guidGenerator,
IClock clock, IClock clock,
IEventHandlerInvoker eventHandlerInvoker) IEventHandlerInvoker eventHandlerInvoker,
ILocalEventBus localEventBus)
: base( : base(
serviceScopeFactory, serviceScopeFactory,
currentTenant, currentTenant,
@ -48,7 +50,8 @@ public class KafkaDistributedEventBus : DistributedEventBusBase, ISingletonDepen
abpDistributedEventBusOptions, abpDistributedEventBusOptions,
guidGenerator, guidGenerator,
clock, clock,
eventHandlerInvoker) eventHandlerInvoker,
localEventBus)
{ {
AbpKafkaEventBusOptions = abpKafkaEventBusOptions.Value; AbpKafkaEventBusOptions = abpKafkaEventBusOptions.Value;
MessageConsumerFactory = messageConsumerFactory; MessageConsumerFactory = messageConsumerFactory;
@ -88,7 +91,7 @@ public class KafkaDistributedEventBus : DistributedEventBusBase, ISingletonDepen
var eventData = Serializer.Deserialize(message.Value, eventType); var eventData = Serializer.Deserialize(message.Value, eventType);
await TriggerHandlersAsync(eventType, eventData); await TriggerHandlersDirectAsync(eventType, eventData);
} }
public override IDisposable Subscribe(Type eventType, IEventHandlerFactory factory) public override IDisposable Subscribe(Type eventType, IEventHandlerFactory factory)
@ -177,11 +180,11 @@ public class KafkaDistributedEventBus : DistributedEventBusBase, ISingletonDepen
unitOfWork.AddOrReplaceDistributedEvent(eventRecord); unitOfWork.AddOrReplaceDistributedEvent(eventRecord);
} }
public override Task PublishFromOutboxAsync( public override async Task PublishFromOutboxAsync(
OutgoingEventInfo outgoingEvent, OutgoingEventInfo outgoingEvent,
OutboxConfig outboxConfig) OutboxConfig outboxConfig)
{ {
return PublishAsync( await PublishAsync(
AbpKafkaEventBusOptions.TopicName, AbpKafkaEventBusOptions.TopicName,
outgoingEvent.EventName, outgoingEvent.EventName,
outgoingEvent.EventData, outgoingEvent.EventData,
@ -190,21 +193,28 @@ public class KafkaDistributedEventBus : DistributedEventBusBase, ISingletonDepen
{ "messageId", System.Text.Encoding.UTF8.GetBytes(outgoingEvent.Id.ToString("N")) } { "messageId", System.Text.Encoding.UTF8.GetBytes(outgoingEvent.Id.ToString("N")) }
} }
); );
await TriggerDistributedEventSentAsync(new DistributedEventSent()
{
Source = DistributedEventSource.Outbox,
EventName = outgoingEvent.EventName,
EventData = outgoingEvent.EventData
});
} }
public override Task PublishManyFromOutboxAsync(IEnumerable<OutgoingEventInfo> outgoingEvents, OutboxConfig outboxConfig) public async override Task PublishManyFromOutboxAsync(IEnumerable<OutgoingEventInfo> outgoingEvents, OutboxConfig outboxConfig)
{ {
var producer = ProducerPool.Get(AbpKafkaEventBusOptions.ConnectionName); var producer = ProducerPool.Get(AbpKafkaEventBusOptions.ConnectionName);
var outgoingEventArray = outgoingEvents.ToArray(); var outgoingEventArray = outgoingEvents.ToArray();
foreach (var outgoingEvent in outgoingEventArray) foreach (var outgoingEvent in outgoingEventArray)
{ {
var messageId = outgoingEvent.Id.ToString("N"); var messageId = outgoingEvent.Id.ToString("N");
var headers = new Headers var headers = new Headers
{ {
{ "messageId", System.Text.Encoding.UTF8.GetBytes(messageId)} { "messageId", System.Text.Encoding.UTF8.GetBytes(messageId)}
}; };
producer.Produce( producer.Produce(
AbpKafkaEventBusOptions.TopicName, AbpKafkaEventBusOptions.TopicName,
new Message<string, byte[]> new Message<string, byte[]>
@ -213,9 +223,14 @@ public class KafkaDistributedEventBus : DistributedEventBusBase, ISingletonDepen
Value = outgoingEvent.EventData, Value = outgoingEvent.EventData,
Headers = headers Headers = headers
}); });
await TriggerDistributedEventSentAsync(new DistributedEventSent()
{
Source = DistributedEventSource.Outbox,
EventName = outgoingEvent.EventName,
EventData = outgoingEvent.EventData
});
} }
return Task.CompletedTask;
} }
public async override Task ProcessFromInboxAsync( public async override Task ProcessFromInboxAsync(
@ -230,7 +245,7 @@ public class KafkaDistributedEventBus : DistributedEventBusBase, ISingletonDepen
var eventData = Serializer.Deserialize(incomingEvent.EventData, eventType); var eventData = Serializer.Deserialize(incomingEvent.EventData, eventType);
var exceptions = new List<Exception>(); var exceptions = new List<Exception>();
await TriggerHandlersAsync(eventType, eventData, exceptions, inboxConfig); await TriggerHandlersFromInboxAsync(eventType, eventData, exceptions, inboxConfig);
if (exceptions.Any()) if (exceptions.Any())
{ {
ThrowOriginalExceptions(eventType, exceptions); ThrowOriginalExceptions(eventType, exceptions);
@ -251,9 +266,9 @@ public class KafkaDistributedEventBus : DistributedEventBusBase, ISingletonDepen
} }
private Task<DeliveryResult<string, byte[]>> PublishAsync( private Task<DeliveryResult<string, byte[]>> PublishAsync(
string topicName, string topicName,
string eventName, string eventName,
byte[] body, byte[] body,
Headers headers) Headers headers)
{ {
var producer = ProducerPool.Get(AbpKafkaEventBusOptions.ConnectionName); var producer = ProducerPool.Get(AbpKafkaEventBusOptions.ConnectionName);

34
framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs

@ -9,6 +9,7 @@ using RabbitMQ.Client;
using RabbitMQ.Client.Events; using RabbitMQ.Client.Events;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.EventBus.Distributed; using Volo.Abp.EventBus.Distributed;
using Volo.Abp.EventBus.Local;
using Volo.Abp.Guids; using Volo.Abp.Guids;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
using Volo.Abp.RabbitMQ; using Volo.Abp.RabbitMQ;
@ -47,7 +48,8 @@ public class RabbitMqDistributedEventBus : DistributedEventBusBase, ISingletonDe
IUnitOfWorkManager unitOfWorkManager, IUnitOfWorkManager unitOfWorkManager,
IGuidGenerator guidGenerator, IGuidGenerator guidGenerator,
IClock clock, IClock clock,
IEventHandlerInvoker eventHandlerInvoker) IEventHandlerInvoker eventHandlerInvoker,
ILocalEventBus localEventBus)
: base( : base(
serviceScopeFactory, serviceScopeFactory,
currentTenant, currentTenant,
@ -55,7 +57,8 @@ public class RabbitMqDistributedEventBus : DistributedEventBusBase, ISingletonDe
distributedEventBusOptions, distributedEventBusOptions,
guidGenerator, guidGenerator,
clock, clock,
eventHandlerInvoker) eventHandlerInvoker,
localEventBus)
{ {
ConnectionPool = connectionPool; ConnectionPool = connectionPool;
Serializer = serializer; Serializer = serializer;
@ -107,7 +110,7 @@ public class RabbitMqDistributedEventBus : DistributedEventBusBase, ISingletonDe
var eventData = Serializer.Deserialize(eventBytes, eventType); var eventData = Serializer.Deserialize(eventBytes, eventType);
await TriggerHandlersAsync(eventType, eventData); await TriggerHandlersDirectAsync(eventType, eventData);
} }
public override IDisposable Subscribe(Type eventType, IEventHandlerFactory factory) public override IDisposable Subscribe(Type eventType, IEventHandlerFactory factory)
@ -193,11 +196,17 @@ public class RabbitMqDistributedEventBus : DistributedEventBusBase, ISingletonDe
unitOfWork.AddOrReplaceDistributedEvent(eventRecord); unitOfWork.AddOrReplaceDistributedEvent(eventRecord);
} }
public override Task PublishFromOutboxAsync( public override async Task PublishFromOutboxAsync(
OutgoingEventInfo outgoingEvent, OutgoingEventInfo outgoingEvent,
OutboxConfig outboxConfig) OutboxConfig outboxConfig)
{ {
return PublishAsync(outgoingEvent.EventName, outgoingEvent.EventData, null, eventId: outgoingEvent.Id); await PublishAsync(outgoingEvent.EventName, outgoingEvent.EventData, null, eventId: outgoingEvent.Id);
await TriggerDistributedEventSentAsync(new DistributedEventSent()
{
Source = DistributedEventSource.Outbox,
EventName = outgoingEvent.EventName,
EventData = outgoingEvent.EventData
});
} }
public async override Task PublishManyFromOutboxAsync( public async override Task PublishManyFromOutboxAsync(
@ -213,10 +222,17 @@ public class RabbitMqDistributedEventBus : DistributedEventBusBase, ISingletonDe
{ {
await PublishAsync( await PublishAsync(
channel, channel,
outgoingEvent.EventName, outgoingEvent.EventName,
outgoingEvent.EventData, outgoingEvent.EventData,
properties: null, properties: null,
eventId: outgoingEvent.Id); eventId: outgoingEvent.Id);
await TriggerDistributedEventSentAsync(new DistributedEventSent()
{
Source = DistributedEventSource.Outbox,
EventName = outgoingEvent.EventName,
EventData = outgoingEvent.EventData
});
} }
channel.WaitForConfirmsOrDie(); channel.WaitForConfirmsOrDie();
@ -235,7 +251,7 @@ public class RabbitMqDistributedEventBus : DistributedEventBusBase, ISingletonDe
var eventData = Serializer.Deserialize(incomingEvent.EventData, eventType); var eventData = Serializer.Deserialize(incomingEvent.EventData, eventType);
var exceptions = new List<Exception>(); var exceptions = new List<Exception>();
await TriggerHandlersAsync(eventType, eventData, exceptions, inboxConfig); await TriggerHandlersFromInboxAsync(eventType, eventData, exceptions, inboxConfig);
if (exceptions.Any()) if (exceptions.Any())
{ {
ThrowOriginalExceptions(eventType, exceptions); ThrowOriginalExceptions(eventType, exceptions);
@ -249,7 +265,7 @@ public class RabbitMqDistributedEventBus : DistributedEventBusBase, ISingletonDe
public Task PublishAsync( public Task PublishAsync(
Type eventType, Type eventType,
object eventData, object eventData,
IBasicProperties properties, IBasicProperties properties,
Dictionary<string, object> headersArguments = null) Dictionary<string, object> headersArguments = null)
{ {

31
framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventBus.cs

@ -11,6 +11,7 @@ using Rebus.Pipeline;
using Rebus.Transport; using Rebus.Transport;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.EventBus.Distributed; using Volo.Abp.EventBus.Distributed;
using Volo.Abp.EventBus.Local;
using Volo.Abp.Guids; using Volo.Abp.Guids;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
using Volo.Abp.Threading; using Volo.Abp.Threading;
@ -41,7 +42,8 @@ public class RebusDistributedEventBus : DistributedEventBusBase, ISingletonDepen
IRebusSerializer serializer, IRebusSerializer serializer,
IGuidGenerator guidGenerator, IGuidGenerator guidGenerator,
IClock clock, IClock clock,
IEventHandlerInvoker eventHandlerInvoker) : IEventHandlerInvoker eventHandlerInvoker,
ILocalEventBus localEventBus) :
base( base(
serviceScopeFactory, serviceScopeFactory,
currentTenant, currentTenant,
@ -49,7 +51,8 @@ public class RebusDistributedEventBus : DistributedEventBusBase, ISingletonDepen
abpDistributedEventBusOptions, abpDistributedEventBusOptions,
guidGenerator, guidGenerator,
clock, clock,
eventHandlerInvoker) eventHandlerInvoker,
localEventBus)
{ {
Rebus = rebus; Rebus = rebus;
Serializer = serializer; Serializer = serializer;
@ -147,7 +150,7 @@ public class RebusDistributedEventBus : DistributedEventBusBase, ISingletonDepen
return; return;
} }
await TriggerHandlersAsync(eventType, eventData); await TriggerHandlersDirectAsync(eventType, eventData);
} }
protected async override Task PublishToEventBusAsync(Type eventType, object eventData) protected async override Task PublishToEventBusAsync(Type eventType, object eventData)
@ -225,14 +228,21 @@ public class RebusDistributedEventBus : DistributedEventBusBase, ISingletonDepen
return false; return false;
} }
public override Task PublishFromOutboxAsync( public override async Task PublishFromOutboxAsync(
OutgoingEventInfo outgoingEvent, OutgoingEventInfo outgoingEvent,
OutboxConfig outboxConfig) OutboxConfig outboxConfig)
{ {
var eventType = EventTypes.GetOrDefault(outgoingEvent.EventName); var eventType = EventTypes.GetOrDefault(outgoingEvent.EventName);
var eventData = Serializer.Deserialize(outgoingEvent.EventData, eventType); var eventData = Serializer.Deserialize(outgoingEvent.EventData, eventType);
return PublishAsync(eventType, eventData, eventId: outgoingEvent.Id); await PublishAsync(eventType, eventData, eventId: outgoingEvent.Id);
await TriggerDistributedEventSentAsync(new DistributedEventSent()
{
Source = DistributedEventSource.Outbox,
EventName = outgoingEvent.EventName,
EventData = outgoingEvent.EventData
});
} }
public async override Task PublishManyFromOutboxAsync(IEnumerable<OutgoingEventInfo> outgoingEvents, OutboxConfig outboxConfig) public async override Task PublishManyFromOutboxAsync(IEnumerable<OutgoingEventInfo> outgoingEvents, OutboxConfig outboxConfig)
@ -244,8 +254,15 @@ public class RebusDistributedEventBus : DistributedEventBusBase, ISingletonDepen
foreach (var outgoingEvent in outgoingEventArray) foreach (var outgoingEvent in outgoingEventArray)
{ {
await PublishFromOutboxAsync(outgoingEvent, outboxConfig); await PublishFromOutboxAsync(outgoingEvent, outboxConfig);
await TriggerDistributedEventSentAsync(new DistributedEventSent()
{
Source = DistributedEventSource.Outbox,
EventName = outgoingEvent.EventName,
EventData = outgoingEvent.EventData
});
} }
await scope.CompleteAsync(); await scope.CompleteAsync();
} }
} }
@ -262,7 +279,7 @@ public class RebusDistributedEventBus : DistributedEventBusBase, ISingletonDepen
var eventData = Serializer.Deserialize(incomingEvent.EventData, eventType); var eventData = Serializer.Deserialize(incomingEvent.EventData, eventType);
var exceptions = new List<Exception>(); var exceptions = new List<Exception>();
await TriggerHandlersAsync(eventType, eventData, exceptions, inboxConfig); await TriggerHandlersFromInboxAsync(eventType, eventData, exceptions, inboxConfig);
if (exceptions.Any()) if (exceptions.Any())
{ {
ThrowOriginalExceptions(eventType, exceptions); ThrowOriginalExceptions(eventType, exceptions);

62
framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs

@ -4,6 +4,7 @@ using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Volo.Abp.EventBus.Local;
using Volo.Abp.Guids; using Volo.Abp.Guids;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
using Volo.Abp.Timing; using Volo.Abp.Timing;
@ -16,6 +17,7 @@ public abstract class DistributedEventBusBase : EventBusBase, IDistributedEventB
protected IGuidGenerator GuidGenerator { get; } protected IGuidGenerator GuidGenerator { get; }
protected IClock Clock { get; } protected IClock Clock { get; }
protected AbpDistributedEventBusOptions AbpDistributedEventBusOptions { get; } protected AbpDistributedEventBusOptions AbpDistributedEventBusOptions { get; }
protected ILocalEventBus LocalEventBus { get; }
protected DistributedEventBusBase( protected DistributedEventBusBase(
IServiceScopeFactory serviceScopeFactory, IServiceScopeFactory serviceScopeFactory,
@ -24,8 +26,8 @@ public abstract class DistributedEventBusBase : EventBusBase, IDistributedEventB
IOptions<AbpDistributedEventBusOptions> abpDistributedEventBusOptions, IOptions<AbpDistributedEventBusOptions> abpDistributedEventBusOptions,
IGuidGenerator guidGenerator, IGuidGenerator guidGenerator,
IClock clock, IClock clock,
IEventHandlerInvoker eventHandlerInvoker IEventHandlerInvoker eventHandlerInvoker,
) : base( ILocalEventBus localEventBus) : base(
serviceScopeFactory, serviceScopeFactory,
currentTenant, currentTenant,
unitOfWorkManager, unitOfWorkManager,
@ -34,6 +36,7 @@ public abstract class DistributedEventBusBase : EventBusBase, IDistributedEventB
GuidGenerator = guidGenerator; GuidGenerator = guidGenerator;
Clock = clock; Clock = clock;
AbpDistributedEventBusOptions = abpDistributedEventBusOptions.Value; AbpDistributedEventBusOptions = abpDistributedEventBusOptions.Value;
LocalEventBus = localEventBus;
} }
public IDisposable Subscribe<TEvent>(IDistributedEventHandler<TEvent> handler) where TEvent : class public IDisposable Subscribe<TEvent>(IDistributedEventHandler<TEvent> handler) where TEvent : class
@ -79,6 +82,13 @@ public abstract class DistributedEventBusBase : EventBusBase, IDistributedEventB
} }
await PublishToEventBusAsync(eventType, eventData); await PublishToEventBusAsync(eventType, eventData);
await TriggerDistributedEventSentAsync(new DistributedEventSent()
{
Source = DistributedEventSource.Direct,
EventName = EventNameAttribute.GetNameOrDefault(eventType),
EventData = eventData
});
} }
public abstract Task PublishFromOutboxAsync( public abstract Task PublishFromOutboxAsync(
@ -170,4 +180,52 @@ public abstract class DistributedEventBusBase : EventBusBase, IDistributedEventB
} }
protected abstract byte[] Serialize(object eventData); protected abstract byte[] Serialize(object eventData);
protected virtual async Task TriggerHandlersDirectAsync(Type eventType, object eventData)
{
await TriggerHandlersAsync(eventType, eventData);
await TriggerDistributedEventReceivedAsync(new DistributedEventReceived
{
Source = DistributedEventSource.Direct,
EventName = EventNameAttribute.GetNameOrDefault(eventType),
EventData = eventData
});
}
protected virtual async Task TriggerHandlersFromInboxAsync(Type eventType, object eventData, List<Exception> exceptions, InboxConfig inboxConfig = null)
{
await TriggerHandlersAsync(eventType, eventData, exceptions, inboxConfig);
await TriggerDistributedEventReceivedAsync(new DistributedEventReceived
{
Source = DistributedEventSource.Inbox,
EventName = EventNameAttribute.GetNameOrDefault(eventType),
EventData = eventData
});
}
public virtual async Task TriggerDistributedEventSentAsync(DistributedEventSent distributedEvent)
{
try
{
await LocalEventBus.PublishAsync(distributedEvent);
}
catch (Exception _)
{
// ignored
}
}
public virtual async Task TriggerDistributedEventReceivedAsync(DistributedEventReceived distributedEvent)
{
try
{
await LocalEventBus.PublishAsync(distributedEvent);
}
catch (Exception _)
{
// ignored
}
}
} }

28
framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/LocalDistributedEventBus.cs

@ -28,6 +28,30 @@ public class LocalDistributedEventBus : IDistributedEventBus, ISingletonDependen
ServiceScopeFactory = serviceScopeFactory; ServiceScopeFactory = serviceScopeFactory;
AbpDistributedEventBusOptions = distributedEventBusOptions.Value; AbpDistributedEventBusOptions = distributedEventBusOptions.Value;
Subscribe(distributedEventBusOptions.Value.Handlers); Subscribe(distributedEventBusOptions.Value.Handlers);
// For unit testing
if (localEventBus is LocalEventBus eventBus)
{
eventBus.OnEventHandleInvoking = async (eventType, eventData) =>
{
await localEventBus.PublishAsync(new DistributedEventReceived()
{
Source = DistributedEventSource.Direct,
EventName = EventNameAttribute.GetNameOrDefault(eventType),
EventData = eventData
}, onUnitOfWorkComplete: false);
};
eventBus.OnPublishing = async (eventType, eventData) =>
{
await localEventBus.PublishAsync(new DistributedEventSent()
{
Source = DistributedEventSource.Direct,
EventName = EventNameAttribute.GetNameOrDefault(eventType),
EventData = eventData
}, onUnitOfWorkComplete: false);
};
}
} }
public virtual void Subscribe(ITypeList<IEventHandler> handlers) public virtual void Subscribe(ITypeList<IEventHandler> handlers)
@ -132,7 +156,7 @@ public class LocalDistributedEventBus : IDistributedEventBus, ISingletonDependen
{ {
return _localEventBus.PublishAsync(eventType, eventData, onUnitOfWorkComplete); return _localEventBus.PublishAsync(eventType, eventData, onUnitOfWorkComplete);
} }
public Task PublishAsync<TEvent>(TEvent eventData, bool onUnitOfWorkComplete = true, bool useOutbox = true) where TEvent : class public Task PublishAsync<TEvent>(TEvent eventData, bool onUnitOfWorkComplete = true, bool useOutbox = true) where TEvent : class
{ {
return _localEventBus.PublishAsync(eventData, onUnitOfWorkComplete); return _localEventBus.PublishAsync(eventData, onUnitOfWorkComplete);
@ -142,4 +166,4 @@ public class LocalDistributedEventBus : IDistributedEventBus, ISingletonDependen
{ {
return _localEventBus.PublishAsync(eventType, eventData, onUnitOfWorkComplete); return _localEventBus.PublishAsync(eventType, eventData, onUnitOfWorkComplete);
} }
} }

8
framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventBusBase.cs

@ -9,7 +9,6 @@ using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Collections; using Volo.Abp.Collections;
using Volo.Abp.EventBus.Distributed; using Volo.Abp.EventBus.Distributed;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
using Volo.Abp.Reflection;
using Volo.Abp.Uow; using Volo.Abp.Uow;
namespace Volo.Abp.EventBus; namespace Volo.Abp.EventBus;
@ -214,7 +213,7 @@ public abstract class EventBusBase : IEventBus
using (CurrentTenant.Change(GetEventDataTenantId(eventData))) using (CurrentTenant.Change(GetEventDataTenantId(eventData)))
{ {
await EventHandlerInvoker.InvokeAsync(eventHandlerWrapper.EventHandler, eventData, eventType); await InvokeEventHandlerAsync(eventHandlerWrapper.EventHandler, eventData, eventType);
} }
} }
catch (TargetInvocationException ex) catch (TargetInvocationException ex)
@ -228,6 +227,11 @@ public abstract class EventBusBase : IEventBus
} }
} }
protected virtual Task InvokeEventHandlerAsync(IEventHandler eventHandler, object eventData, Type eventType)
{
return EventHandlerInvoker.InvokeAsync(eventHandler, eventData, eventType);
}
protected virtual Guid? GetEventDataTenantId(object eventData) protected virtual Guid? GetEventDataTenantId(object eventData)
{ {
return eventData switch return eventData switch

42
framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Local/LocalEventBus.cs

@ -8,6 +8,7 @@ using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.EventBus.Distributed;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
using Volo.Abp.Threading; using Volo.Abp.Threading;
using Volo.Abp.Uow; using Volo.Abp.Uow;
@ -135,6 +136,33 @@ public class LocalEventBus : EventBusBase, ILocalEventBus, ISingletonDependency
await TriggerHandlersAsync(localEventMessage.EventType, localEventMessage.EventData); await TriggerHandlersAsync(localEventMessage.EventType, localEventMessage.EventData);
} }
// Internal for unit testing
internal Func<Type, object, Task> OnPublishing { get; set; }
// For unit testing
public async override Task PublishAsync(
Type eventType,
object eventData,
bool onUnitOfWorkComplete = true)
{
if (onUnitOfWorkComplete && UnitOfWorkManager.Current != null)
{
AddToUnitOfWork(
UnitOfWorkManager.Current,
new UnitOfWorkEventRecord(eventType, eventData, EventOrderGenerator.GetNext())
);
return;
}
// For unit testing
if (OnPublishing != null && eventType != typeof(DistributedEventSent) && eventType != typeof(DistributedEventReceived))
{
await OnPublishing(eventType, eventData);
}
await PublishToEventBusAsync(eventType, eventData);
}
protected override IEnumerable<EventTypeWithEventHandlerFactories> GetHandlerFactories(Type eventType) protected override IEnumerable<EventTypeWithEventHandlerFactories> GetHandlerFactories(Type eventType)
{ {
var handlerFactoryList = new List<EventTypeWithEventHandlerFactories>(); var handlerFactoryList = new List<EventTypeWithEventHandlerFactories>();
@ -168,4 +196,18 @@ public class LocalEventBus : EventBusBase, ILocalEventBus, ISingletonDependency
return false; return false;
} }
// Internal for unit testing
internal Func<Type, object, Task> OnEventHandleInvoking { get; set; }
// Internal for unit testing
protected async override Task InvokeEventHandlerAsync(IEventHandler eventHandler, object eventData, Type eventType)
{
if (OnEventHandleInvoking != null && eventType != typeof(DistributedEventSent) && eventType != typeof(DistributedEventReceived))
{
await OnEventHandleInvoking(eventType, eventData);
}
await base.InvokeEventHandlerAsync(eventHandler, eventData, eventType);
}
} }

2
framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbDateTimeSerializer.cs

@ -34,7 +34,7 @@ public class AbpMongoDbDateTimeSerializer : DateTimeSerializer
return (dateTime - BsonConstants.UnixEpoch).Ticks / 10000L; return (dateTime - BsonConstants.UnixEpoch).Ticks / 10000L;
} }
// For unit testing. // For unit testing
internal void SetDateTimeKind(DateTimeKind dateTimeKind) internal void SetDateTimeKind(DateTimeKind dateTimeKind)
{ {
DateTimeKind = dateTimeKind; DateTimeKind = dateTimeKind;

22
framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Distributed/DistributedEventHandles.cs

@ -0,0 +1,22 @@
using System.Threading.Tasks;
namespace Volo.Abp.EventBus.Distributed;
public class DistributedEventHandles : ILocalEventHandler<DistributedEventSent>, ILocalEventHandler<DistributedEventReceived>
{
public static int SentCount { get; set; }
public static int ReceivedCount { get; set; }
public Task HandleEventAsync(DistributedEventSent eventData)
{
SentCount++;
return Task.CompletedTask;
}
public Task HandleEventAsync(DistributedEventReceived eventData)
{
ReceivedCount++;
return Task.CompletedTask;
}
}

44
framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Distributed/LocalDistributedEventBus_Test.cs

@ -1,7 +1,8 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.Domain.Entities.Events.Distributed; using Volo.Abp.Domain.Entities.Events.Distributed;
using Volo.Abp.MultiTenancy; using Volo.Abp.EventBus.Local;
using Volo.Abp.Uow;
using Xunit; using Xunit;
namespace Volo.Abp.EventBus.Distributed; namespace Volo.Abp.EventBus.Distributed;
@ -49,7 +50,7 @@ public class LocalDistributedEventBus_Test : LocalDistributedEventBusTestBase
public async Task Should_Get_TenantId_From_EventEto_Extra_Property() public async Task Should_Get_TenantId_From_EventEto_Extra_Property()
{ {
var tenantId = Guid.NewGuid(); var tenantId = Guid.NewGuid();
DistributedEventBus.Subscribe<MySimpleEto>(GetRequiredService<MySimpleDistributedSingleInstanceEventHandler>()); DistributedEventBus.Subscribe<MySimpleEto>(GetRequiredService<MySimpleDistributedSingleInstanceEventHandler>());
await DistributedEventBus.PublishAsync(new MySimpleEto await DistributedEventBus.PublishAsync(new MySimpleEto
@ -59,7 +60,44 @@ public class LocalDistributedEventBus_Test : LocalDistributedEventBusTestBase
{"TenantId", tenantId.ToString()} {"TenantId", tenantId.ToString()}
} }
}); });
Assert.Equal(tenantId, MySimpleDistributedSingleInstanceEventHandler.TenantId); Assert.Equal(tenantId, MySimpleDistributedSingleInstanceEventHandler.TenantId);
} }
[Fact]
public async Task DistributedEventSentAndReceived_Test()
{
GetRequiredService<ILocalEventBus>().Subscribe<DistributedEventSent, DistributedEventHandles>();
GetRequiredService<ILocalEventBus>().Subscribe<DistributedEventReceived, DistributedEventHandles>();
DistributedEventBus.Subscribe<MyEventDate, MyEventHandle>();
using (var uow = GetRequiredService<IUnitOfWorkManager>().Begin())
{
await DistributedEventBus.PublishAsync(new MyEventDate(), onUnitOfWorkComplete: false);
Assert.Equal(1, DistributedEventHandles.SentCount);
Assert.Equal(1, DistributedEventHandles.ReceivedCount);
await DistributedEventBus.PublishAsync(new MyEventDate(), onUnitOfWorkComplete: true);
await uow.CompleteAsync();
Assert.Equal(2, DistributedEventHandles.SentCount);
Assert.Equal(2, DistributedEventHandles.ReceivedCount);
}
}
class MyEventDate
{
}
class MyEventHandle : IDistributedEventHandler<MyEventDate>
{
public Task HandleEventAsync(MyEventDate eventData)
{
return Task.CompletedTask;
}
}
} }

Loading…
Cancel
Save