{{announcement.body}}
{{announcement.title}}

Building Microservices Through Event-Driven Architecture, Part 8

DZone 's Guide to

Building Microservices Through Event-Driven Architecture, Part 8

I will talk about Event-Sourcing implementation of your application. This layer surrounds the domain and implements the uses cases.

· Microservices Zone ·
Free Resource

During this article, I will talk about Event-Sourcing implementation of your application. This layer surrounds the domain and implements the uses cases (the application-specific business rules). It orchestrates the data flow and uses the domain model and infrastructures, and has no dependency on a database, UI or special frameworks.

You may also like: Building Microservices Through Event-Driven Architecture, Part 7

For our event-sourcing system, I will take all the uncommitted events from the aggregate and call a function of the repository which will have the responsibility to save the events in the eventstore. So I will call the function AppendAsync(EventStore @event) of IEventStoreRepository.

Because I have not yet implemented the updates, I will not take care of the aggregate version, (I have a single post method that creates a speech, so the aggregate version will always be equal to zero).
When I will implement the updates, I will take care of the aggregate version in the application and presentation layers.

Event-Sourcing Interfaces

I can define two interfaces IEventSourcingSubscriber and IEventSourcingHandler, you can use another naming convention, but for now, I leave them as they are.

code snippet

Subscribe is a function that gets all uncommitted events from the aggregate and for each event call a function Handle that take an event and the current aggregate version as inputs. code snippet

The handle is a function that serializes the event into a string and calls AppendAsync(EventStore @event) of the IEventStoreRepository.

Event-Sourcing Implementation

Event-Sourcing Subscriber Implementation

So the first test should be: Subscribe with no uncommitted events should not call handle

I have no uncommitted events, I will do nothing. Then the Assert section will look like this:

mockEventSourcingHandler. Verify(m => m. Handle(It.IsAny<Event>(),It.IsAny<long>()), Times.Never, "Handle must not be called");

Test Case 1: Subscribe With No Uncommitted Events Should Not Call Handle

code snippet

Here, I will finish the implementation of my function

code snippet

Test Case 2: Subscribe With Uncommitted Events Should Call Handle Only Once

mockEventSourcingHandler. Verify(m => m. Handle(It.IsAny<Event>(),It.IsAny<long>()), Times.Once, "Handle must be called only once").

In the Assert section, I can verify that the Handle function is called only once.

code snippet

The final implementation of EventSourcingSubscriber should look like this:

I call the handler function for each event.

code snippet

Event-Sourcing Handler Implementation

Test Case 3: Handle With Null Events Should Raise Eventnullexception

I mock some dependencies and verify that if the event is null, then handle should raise an exception.

code snippet

Here is the implementation of the test.

code snippet

Test Case 4: Handle With Events Should Call AppendAsync

Here I verify that if the event is not null, then Handle should call AppendAsync.

code snippet

Here is the implementation of the test. You can observe that I use an IEventSerializer interface to serialize the event into a JSON string, this JSON string will be the payload of the event stream.

code snippet

Update RegisterSpeechUseCase

Then update the RegisterSpeechUseCase and call Subscribe function : await _domainEventSubscriber.Subscribe(speech);

code snippet

Update Presentation

Open Startup.cs file and configure some dependency injections.

code snippet

Open appsettings.Development.json and update the ConnectionStrings to use the appropriate database server, database name, and credentials.

code snippet

Scripts to create a database are located in LogCorner.EduSync.Speech.Database project

file dropdown menu

Test Using Postaman

Test Local Code Using Visual Studio

Select LogCorner.EduSync.Speech.Presentation project and hit F5.

Launch postman and run the following HTTP Post.

Endpoint: http://localhost:62694/api/speech

Method: POST

Content-Type: Application/json

Body:

Java




x


 
1
{ 
2
"Title":"Le Lorem Ipsum est simplement du faux texte", 
3
"Description":"Le Lorem Ipsum est simplement du faux texte employé dans la composition et la mise en page avant impression. Le Lorem Ipsum est le faux texte standard de l'imprimerie depuis les années 1500, quand un imprimeur anonyme assembla ensemble des morceaux de texte pour réaliser un livre spécimen de polices de texte", 
4
"Url":"http://www.yahoo_1.fr", 
5
"Type":"3″ 
6
}



code snippet

Open SQL Server Management Studio and run the following commands :

SELECT * FROM [LogCorner.EduSync.Speech.Data].[dbo].[Speech]
SELECT * FROM [LogCorner.EduSync.Speech.Data].[dbo].[EventStore]

The result should look like this :

SQL server management studio

As a result, I should have records on the Speech table and the EventStore table, the version is always equal to zero because this tutorial does not cover updates.

Test Local Code Using Docker

Locate \LogCorner.EduSync.Command\src folder (the folder where is located docker-compose.yml file) and run the following command.

  • Docker-compose build.
  • Docker-compose up.
  • Docker ps -all -format "table {{.ID}}\t{{.Image}}\t{{.Names}}".
code snippet

Launch postman and run the following HTTP Post.

Endpoint : http://localhost:8080/api/speech

Method: POST

Content-Type: application/json

Body :

Java




xxxxxxxxxx
1


 
1
{ 
2
"Title":"Le Lorem Ipsum est simplement du faux texte", 
3
"Description":"Le Lorem Ipsum est simplement du faux texte employé dans la composition et la mise en page avant impression. Le Lorem Ipsum est le faux texte standard de l'imprimerie depuis les années 1500, quand un imprimeur anonyme assembla ensemble des morceaux de texte pour réaliser un livre spécimen de polices de texte", 
4
"Url":"http://www.yahoo_1.fr", 
5
"Type":"3″ 
6
}



Finally, inspect the running containers like this :

Open a bash shell by running the following command ( where 0b is first letters of logcorner.edusync.speech.presentation.data container Id)

Dockerfile




xxxxxxxxxx
1
14


 
1
Docker exec -it 0b "bash"
2
Connect to sql server linux
3
 
           
4
/opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P 'PassW0rd'
5
Run sql queries
6
 
           
7
use [LogCorner.EduSync.Speech.Database] 
8
go
9
 
           
10
select * from [dbo].[Speech] 
11
go
12
 
           
13
select * from [dbo].[eventstore] 
14
go



code snippet

As a result, I should have records on the Speech table and the EventStore table, the version is always equal to zero because this tutorial does not cover updates.

The source code of this article is available here (Feature/Task/EventSourcingApplication).

Regards!


Further Reading

Read the rest of the series!

Part 1: Application-Specific Business Rules

Part 2: Domain Objects and Business Rules

Part 3: Presenters, Views, and Controllers

Part 4: Repositories

Part 5: Dockerization

Part 6: Implementing EventSourcing on Domain Model

Topics:
microservices ,event-driven ,event-driven microservices ,implementation ,domain ,tutorial

Published at DZone with permission of Gora LEYE , DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}