-
Notifications
You must be signed in to change notification settings - Fork 1
4. Readmodels
Microwave supports distributed systems and you can subscribe to events from any service with just implementing an interface. Microwave will get the events, put them in the handling classes and saves the location where you left of, in case a service is unavailable or an error occurs during the event handling on the client side.
Microwave has ReadModels and Querries that can be used to create a querry service that is independent from the write
side and therefore can be run in parallel. There are two main differences between Querries and ReadModels: ReadModels
can be retrieved with an Identity and Querries are retrieved by their classname. For example you can have a
ReadModel that represents a UserReadModel
that can be retrieved by the UserId and a Querry could be the Top 10 Most
Active Users in the Domain.
To add a Querry, inherit from Querry
and implement the IHandle
Interface to register the Querry to the specific
DomainEvent. A Querry could look like this:
public class UserCounterQuerry : Querry, IHandle<UserCreatedEvent>
{
public int Count { get; private set; }
public void Handle(UserCreatedEvent domainEvent)
{
Count++;
}
}
To add a ReadModel inherit from ReadModel<T>
where T is the type of DomainEvent where the Readmodel is being
created. After the creation Microwave tracks the ReadModel and updates it when new events emerge. Also implement
IHandle
accordingly. The Readmodel also has a version that
is being updated alongside with the write side, so you can call the write side with the eventual consistent version.
If you want to version to be passed in the function, to save it directly in the readmodel or do something else with
it, implement the IHandleVersioned
interface and Microwave will also pass the version of the domain event.
The version is also updated, when the event is not processed by the ReadModel. For example the entity could create
another event UserDeletedEvent
but as there is no IHandle
implemented, the event get skipped but the version
will still be updated.
A ReadModel could look like this:
public class UserReadModel : ReadModel<UserCreatedEvent>,
IHandle<UserCreatedEvent>,
IHandleVersioned<UserChangedNameEvent>
{
public void Handle(UserCreatedEvent domainEvent)
{
Id = domainEvent.EntityId;
}
public void Apply(UserChangedNameEvent domainEvent, long version)
{
Name = domainEvent.Name;
InnerVersion = version;
}
public Identity Id { get; private set; }
public string Name { get; private set; }
public long InnerVersion { get; private set; }
}
To load the Querries and ReadModels there is a IReadModelRepository
that
offer functionality to load and update Querries/Readmodels. Inject it and you can use it to update Querries or
Readmodels inside a IHandleAsync
by yourself, if you need to.
Microwave triggers an update for readmodels/querries every second by default. If you have readmodels that do not have
to be updated frequently and if you want to save traffic, you can define the update cycle with the
IPollingInterval
in the startup class. The class accepts a string wich represents a cron notation or a integer
which triggers the job
every n
full seconds. The T
is the class that implements the IHandle
or IHandleAsync
interface. A registration
could look
like this:
public void ConfigureServices(IServiceCollection services)
{
...
services.AddMicrowave(config =>
{
config.PollingIntervals.Add(new PollingInterval<MyAsyncHandler>("* * * * 2")); // Update every two minutes
config.PollingIntervals.Add(new PollingInterval<MyReadModel1>(20)); // Update every 20 seconds
});
}