Integration Events¶
Since domain events
are only used in local transactions, we need a mechanism to transmit events in a distributed system so that the handling of events does not block the execution of the command
that initiated the event. This is the role of integration events
.
Register Integration Event Services¶
The framework currently implements the CAP
component to support integration events. We need to register the CAP
component in the Startup
class:
public void ConfigureServices(IServiceCollection services)
{
services.AddCap(x =>
{
x.UseEntityFramework<AppDbContext>();
x.UseRabbitMQ("localhost");
});
}
// Configure CAP for integration events
builder.Services.AddIntegrationEvents(typeof(Program))
.UseCap(b =>
{
b.RegisterServicesFromAssemblies(typeof(Program));
b.AddContextIntegrationFilters();
b.UseMySql();
});
Emitting Integration Events¶
Integration events are converted from domain events
and are generally named with the suffix IntegrationEvent
to distinguish them from domain events
, such as OrderCreatedIntegrationEvent
.
To emit an integration event, we need to define an IIntegrationEventConverter
, which the framework will automatically use to convert domain events into integration events and emit them.
public class OrderCreatedIntegrationEventConverter :
IIntegrationEventConverter<OrderCreatedDomainEvent, OrderCreatedIntegrationEvent>
{
public OrderCreatedIntegrationEvent Convert(OrderCreatedDomainEvent domainEvent)
{
return new OrderCreatedIntegrationEvent(domainEvent.Order.Id);
}
}
Integration Event Handling¶
An integration event handler is a class that implements the IIntegrationEventHandler<TIntegrationEvent>
interface, where TIntegrationEvent
is the type of the integration event.
Typically, we can do the following in an integration event handler:
- Emit commands
- Call external services
Here is an example of an integration event handler:
public class OrderCreatedIntegrationEventHandler(IMediator mediator) : IIntegrationEventHandler<OrderCreatedIntegrationEvent>
{
public async Task Handle(OrderCreatedIntegrationEvent eventData, CancellationToken cancellationToken)
{
// Handle the integration event
var cmd = new OrderPaidCommand(eventData.OrderId);
await mediator.Send(cmd, cancellationToken);
}
}
Retry on Failure¶
We use the CAP
component to implement integration events. The CAP
component provides a retry mechanism for failures. When the handling of an integration event fails, CAP
will automatically retry the handling. By default, it will retry 10
times.
Limitations¶
Integration events must use simple objects because integration events need to support JSON format serialization and deserialization and be transmitted in a distributed system.