Your First Subscribers
If we look back at our task requirements, the last one states that; The bank would like to keep track of how much money it has gained as revenue as a result of the transaction fees.
One way to satisfy this requirement is to use a DomainEventSubscriber
that Subscribes to the FeesDeductedEvent
domain event, which then tells the persistence mechanism to store the result so that it can later be read by a ReadModel
.
//Walkthrough.Domain/Subscribers/Revenue/RevenueSubscriber.cs
public class RevenueSubscriber : DomainEventSubscriber,
ISubscribeTo<Account,AccountId,FeesDeductedEvent>
{
public IActorRef RevenueRepository { get; }
public RevenueSubscriber(IActorRef revenueRepository)
{
RevenueRepository = revenueRepository;
}
public Task Handle(IDomainEvent<Account, AccountId, FeesDeductedEvent> domainEvent)
{
var command = new AddRevenueCommand(domainEvent.AggregateEvent.Amount);
RevenueRepository.Tell(command);
return Task.CompletedTask;
}
}
Our mock revenue repository is going to be modelled as an actor, but typically this would be a type of persistent storage that applies to your use case.
//Walkthrough.Domain/Repositories/RevenueRepository.cs
public class RevenueRepository : ReceiveActor
{
public Money Revenue { get; private set; } = new Money(0.00m);
public int Transactions { get; private set; } = 0;
public RevenueRepository()
{
Receive<AddRevenueCommand>(Handle);
Receive<GetRevenueQuery>(Handle);
}
private bool Handle(AddRevenueCommand command)
{
Revenue = Revenue + command.AmountToAdd;
Transactions++;
return true;
}
private bool Handle(GetRevenueQuery query)
{
var readModel = new RevenueReadModel(Revenue, Transactions);
Sender.Tell(readModel);
return true;
}
}
This repository handles a AddRevenueCommand
which is just a data transfer object (dto) that holds the amount of money to add to the current revenue. The repository also handles a query GetRevenueQuery
. You can now see a hint of how the read/query side of an Akkatecture application might work. On to the next section on read models.