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.
Join the DZone community and get the full member experience.
Join For Freeduring 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.

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.

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

here, i will finish the implementation of my function

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.

the final implementation of eventsourcingsubscriber should look like this:
i call the handler function for each event.

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.

here is the implementation of the test.

test case 4: handle with events should call appendasync
here i verify that if the event is not null, then handle should call appendasync.

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.

update registerspeechusecase
then update the registerspeechusecase and call subscribe function : await _domaineventsubscriber.subscribe(speech);

update presentation
open startup.cs file and configure some dependency injections.

open appsettings.development.json and update the connectionstrings to use the appropriate database server, database name, and credentials.

scripts to create a database are located in logcorner.edusync.speech.database project
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 :
{
"title":"le lorem ipsum est simplement du faux texte",
"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",
"url":"http://www.yahoo_1.fr",
"type":"3″
}

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 :

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}}".

launch postman and run the following http post.
endpoint : http://localhost:8080/api/speech
method : post
content-type : application/json
body :
xxxxxxxxxx
{
"title":"le lorem ipsum est simplement du faux texte",
"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",
"url":"http://www.yahoo_1.fr",
"type":"3″
}
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)
xxxxxxxxxx
docker exec -it 0b "bash"
connect to sql server linux
/opt/mssql-tools/bin/sqlcmd -s localhost -u sa -p 'passw0rd'
run sql queries
use [logcorner.edusync.speech.database]
go
select * from [dbo].[speech]
go
select * from [dbo].[eventstore]
go

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
Published at DZone with permission of Gora LEYE, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Trending
-
Understanding Data Compaction in 3 Minutes
-
The Role of Automation in Streamlining DevOps Processes
-
The Dark Side of DevSecOps and Why We Need Governance Engineering
-
Why I Prefer Trunk-Based Development
Comments