Skip to main content

Asynchronous Processing

Overview

The StarterKit supports both synchronous and asynchronous events. Synchronous events are built on MediatR INotification and are executed directly before the UnitOfWork.Commit completes, whereas asynchronous events are queued and executed outside of the request.

Send

Asynchronous events are built on MassTransit (with ServiceBus transport). There are two ways to send an asynchronous event:

  1. Using the IEntity.Events and IAggregatedRoot.Events collections, where the event must be marked with the IAsyncNotification interface (IAsyncNotification is a child interface of INotification, thus it can be listened to in both synchronous and asynchronous contexts).
  2. Directly through the IEventPublisherPort.
info

Note that events will only be sent to the queue after calling IUnitOfWork.CommitAsync().

Inbox/Outbox

Interacting with 3rd-party services can sometimes introduce unexpected and inconsistent failures into programs, such as:

  • When called before commit, the message was sent but the database transaction failed.
  • When called before commit, the message was sent and processed before the database transaction completed.
  • When called after commit, the transaction was completed but message sending failed.

By utilizing the Inbox/Outbox pattern provided by MassTransit, we can ensure the transactionality of message sending. Database transaction and message sending occur as a single unit. If the database transaction fails, the message will not be sent to the queue and vice versa. More information on this can be found in the MassTransit documentation Transactional Outbox.

Consume

To add a new consumer event, simply create a new class inheriting from IConsumer<YourEvent> in StarterKit.App.Infrastructure/Events/Consumers. Its addition will automatically create an Azure Service Bus Topic (if not already created) as well as a Subscription.

In the base version of StarterKit, to avoid complicating deployment, background consumers start in the same process as the web application. This may lead to issues, as some cloud providers may stop processes if the web application is not in use (for example, Azure App Services). Therefore, StarterKit BICEP scripts are configured for an Always On configuration, but sometimes it may be necessary to separate Consumers from the main process.