This is an experiment with ZIO + HTTP4s + DOOBIE. It is fully described in a series of posts in MEDIUM. It can be regarded as the continuation of THIS BLOG POST which serves as the inspiration of this project.
The basic idea is to have a server running with that software stack. I want to make it as production-like as possible, so I have refactored the original code adding some extra layers and testing.
What this project does is start a small server with 2 endpoints: one allows to write a User, and the other to retrieve it. There are example CURLS defining the functionality:
curl --location --request POST 'localhost:8083/' \
--header 'Content-Type: application/json' \
--data-raw '{
"id": "1",
"name": "manuel"
}'
curl --location --request GET 'localhost:8083/1'
curl --location --request DELETE 'localhost:8083/1'
My proposed architecture is:
- Main: file that connects the wires and runs the server
- HTTP: package with the HTTP server
- DOMAIN: package with the Domain logic
- Model:
- objects to be managed by the domain.
- For an in-depth description of the employed data types see Road To ZIO[n]: chapter 2, Types in the Domain layer
- Errors: this is how we model the Errors in the application and deal with them in a functional way. As it is a
small code we are keeping all in here instead of spreading them through the different layers
- for a description of the error management see Road to ZIO(n): chapter 1, the basics
- objects to be managed by the domain.
- Service: business logic regarding the domain objects
- Ports: interfaces defining the desired I/O
- Model:
- ADAPTER: package with implementation for the ports
- this is described in Road to ZIO[n]: Chapter 4, the Persistence layer
- CONFIGURATION: boring configuration stuff
The project uses a H2 in-memory DB to store Users.
Testing is performed in different layers:
- Domain: unit tests for the services residing in the Service package.
- I am using a mock DB in here -just an array- to isolate responsibilities
- I am using property-based testing for the model whenever possible
- For a full description of the test see Road to ZIO[N]: chapter 3, testing the Domain
- Adapters: unit tests for the adapters, making sure that they implement correctly the desired functionalities.
- Also described in section 4
- Full testing of the HTTP layer with integration tests. This way we verify that:
- the wiring is correct and we are able to perform CRUD operations
- the HTTP layer is correct, and the server is returning the correct HTTP codes both in the case of correct executions and failures
- See Road to ZIO[n]: Integration Tests in Scala with ZIO+HTTP4S
This is an ongoing process and it is still not finished. Some missing sections are:
-
Clean (probably with a full refactor) the HTTP layer.
-
Scalability tests
- attack the API with something like Gatling and see how ZIO+HTTP4S+DOOBIE behaves under heavy loads
-
Kafka Producer/Consumer
- I want to test how to write and read Kafka stuff with ZIO
-
Update to ZIO2
- while this tutorial has been written, a new version of ZIO has been released. It is supposed to simplify most of the pain points, so it is definitely worth to take a deep look at it.