To help you get started quickly on the Cronus we will build an application that will satisfy all future business requirements.
We need a new task management system.
We need data to be consistent.
We need to be able to reassign tasks inside the user group.
We need an accurate progress report for every user.
Groups progress report needs to be secured such that only group members can access it.
We need a notification to the group members when a user finishes his task.
We need a screen to view the historical changes in user activity.
When users close their accounts we need to ask them why (optional survey).
We need to generate a monthly report that indicates why lost users closed their accounts.
Projections are queryable models used for the reading part of our application. We can design projections in such a way that we can manage what data we want to store and by what will be searched. Events are the basis for projections data.
For using projections we should update the configuration file for both API and Service.
And add some dependencies.
You can choose whitch implementation to use. You can get hte tasks(commented in the controller) with same name, or all tasks.
Every time the event will occur it will be handled and persist in its state.
Inject IProjectionReader
that will be responsible for getting the projection state by Id on which projection was subscribed before: Subscribe<TaskCreated>(x => x.UserId).
(The dashboard is not requerd)
If we hit this controller immediately after the first start, it could lead to a probable read error. We need to give it some time to initialize our new projection store and build new versions of the projections. For an empty event store, it could take less than a few seconds but in order not to wait for this and verify that all working properly, we will check it manually.
Cronus Dashboard is a UI management tool for the Cronus framework. It hosts inside our Application so add this missing code to our background service.
Start our Cronus Service and API.
In the dashboard select the Connections
tab and click New Connection
.
Set the predefined port for the Cronus endpoint: http://localhost:7477 and specify your connection name. Click Check
and then Add Connection
.
After you add a connection select it from the drop-down menu and navigate to the Projections tab.
You would be able to see all projections in the system.
Now we would be able to request a controller with userId
. GetAsync
method of IProjectionReader
will restore all events related to projection and apply them to the state.
First, we need to add a UserId and TaskId to have the Identifications of these two entities
Then we need to create a Cronus command for task creation and an Event that will indicate that the event has occurred.
Add Aggregate that inherits AggregateRoot with the generic state.
Apply method will pass the event to the state of an aggregate and change its state.
Finally, we can create an Application Service for command handling.
We register a handler by inheriting from ICommandHandler<>.
When the command arrives we read the state of the aggregate, and if it is not found we create a new one and call SaveAsync
to save its state to the database.
Now we need a controller to publish our commands and create tasks.
Here we create TaskId and UserId and inject_IPublisher<CreateTask>
_to publish the command. After this, the command will be sent to RabbitMq and then handled in Application Service.
Now let's start our Service and API. We should be able to make post requests to our Controller throw the Swagger and create our first Task in the system. It must be persisted in the Event Store.
Download DevCenter or any other UI tool for Cassandra.
Let's take an Id from the response and encode it to Base64.
Than try: select * from taskmanagerevents where id = 'dXJuOnRlbmFudDp0YXNrOmU1MjA1NTA3LWYyNmUtNGExMy05OTU4LTNjMzVlYzAwY2I1Yw=='
Prerequisite software: Docker
Create a new console application project in a new folder using dotnet command.
Also, create a Web API project using the same folder for communicating with our Service. Then add both projects to the common solution.
Then we add the Cronus dependency.
This is the minimum set of packages for our Cronus host to work.
Setup Cassandra (Container memory is limited to 2GB):
docker run --restart=always -d --name cassandra -p 9042:9042 -p 9160:9160 -p 7199:7199 -p 7001:7001 -p 7000:7000 cassandra
Setup RabbitMq (Container memory is limited to 512MB):
docker run --restart=always -d --hostname node1 -e RABBITMQ_NODENAME=docker-UNIQUENAME-rabbitmq --name rabbitmq -p 15672:15672 -p 5672:5672 elders/rabbitmq:3.8.3
Add appsettings.json with the following configuration into the project folder.
//This should be int the Service and in the Api.
You can also see how the Cronus application can be configured in more detail in Configuration.
This is the code that your Program.cs in TaskManager.Service should contain.
This is the code that you should add in the Program.cs in TaskManager.Api.