Add documentation.
This commit is contained in:
77
README.md
Normal file
77
README.md
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
# Virtual threads experiences
|
||||||
|
## General information
|
||||||
|
This project aims to show what is the developer experience when the virtual threads are used, in comparison of the framework Reactor.
|
||||||
|
|
||||||
|
Therefore, there is one spring boot application which uses "standard java code" with virtual threads, and another spring boot application which uses Reactor.
|
||||||
|
|
||||||
|
## Spring boot applications
|
||||||
|
### Common concepts
|
||||||
|
Both applications are developed to serve same endpoints with same models.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Architecture
|
||||||
|
Both applications are architectured with a "light" version of the hexagonal architecture.
|
||||||
|
|
||||||
|
Java packages represent the hexagonal architecture modules:
|
||||||
|
- domain (Business code)
|
||||||
|
- exposition (Rest API)
|
||||||
|
- infrastructure (JPA layer)
|
||||||
|
|
||||||
|
#### Models
|
||||||
|
[<img src="./doc/images/models.png" witdh="1600px" />](./doc/images/models.png)
|
||||||
|
|
||||||
|
#### Exposed endpoints
|
||||||
|
- Catalogs
|
||||||
|
- GET /api/catalogs/{catalogId}
|
||||||
|
- Items
|
||||||
|
- GET /api/items
|
||||||
|
- POST /api/items
|
||||||
|
- Marketplace
|
||||||
|
- GET /api/marketplace
|
||||||
|
|
||||||
|
### Virtual threads application
|
||||||
|
The application runs on port `51001`.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./gradlew :virtual-threads-app:bootRun
|
||||||
|
```
|
||||||
|
|
||||||
|
### Reactor application
|
||||||
|
The application runs on port `52001`.
|
||||||
|
|
||||||
|
To start the application, run this command:
|
||||||
|
```bash
|
||||||
|
./gradlew :reactor-app:bootRun
|
||||||
|
```
|
||||||
|
|
||||||
|
## Database
|
||||||
|
The database is a PostgreSQL database which runs inside a container.
|
||||||
|
|
||||||
|
To start the database, just run this command inside the project root folder:
|
||||||
|
```bash
|
||||||
|
docker compose up --detach --file ./docker-compose.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, you will have to initialise the tables by executing scripts located [there](./src/main/sql/init_database.sql) into the container.
|
||||||
|
|
||||||
|
You can connect to it with this "unix" command:
|
||||||
|
```bash
|
||||||
|
docker exec --interactive --tty virtual-threads-test-db /bin/bash
|
||||||
|
psql --host localhost --port 5432 --username virtual_threads_test_user virtual_threads_test_db
|
||||||
|
```
|
||||||
|
|
||||||
|
### Database files
|
||||||
|
There is a volumes for the database container, which points to this location: [local/postgresql](./local/postgresql).
|
||||||
|
|
||||||
|
## Bruno http client collection
|
||||||
|
There is a collection of queries, usable with [bruno](https://www.usebruno.com/). It is located inside the [rest-client-collection](./rest-client-collection).
|
||||||
|
|
||||||
|
## Load testing
|
||||||
|
Load tests use K6 framework.
|
||||||
|
|
||||||
|
### Targeting the application to test
|
||||||
|
By default, tests are configured to load the `virtual-threads-app`.
|
||||||
|
|
||||||
|
If you want to run them on the `reactor-app`, you have to edit the variable `TARGET_URL` inside the file [config.ts](./k6-load-tests/src/tests/config.ts).
|
||||||
|
|
||||||
BIN
doc/images/models.png
Normal file
BIN
doc/images/models.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 35 KiB |
37
doc/sources_of_model_schema_built_with_umlet.uxf
Normal file
37
doc/sources_of_model_schema_built_with_umlet.uxf
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<diagram program="umletino" version="15.1"><zoom_level>10</zoom_level><element><id>UMLClass</id><coordinates><x>730</x><y>500</y><w>90</w><h>60</h></coordinates><panel_attributes>Catalog
|
||||||
|
--
|
||||||
|
id: UUID
|
||||||
|
name: String</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>730</x><y>580</y><w>180</w><h>80</h></coordinates><panel_attributes>Item
|
||||||
|
--
|
||||||
|
id: UUID
|
||||||
|
name: String
|
||||||
|
sharedDate: ZonedDateTime</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>590</x><y>410</y><w>90</w><h>50</h></coordinates><panel_attributes>Marketplace
|
||||||
|
--
|
||||||
|
</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>620</x><y>450</y><w>130</w><h>100</h></coordinates><panel_attributes>lt=-
|
||||||
|
m1=0..*
|
||||||
|
m2=0..*</panel_attributes><additional_attributes>10;10;10;70;110;70</additional_attributes></element><element><id>Relation</id><coordinates><x>590</x><y>450</y><w>160</w><h>180</h></coordinates><panel_attributes>lt=-
|
||||||
|
m1=0..*
|
||||||
|
m2=0..*</panel_attributes><additional_attributes>10;10;10;150;140;150</additional_attributes></element><element><id>UMLNote</id><coordinates><x>550</x><y>340</y><w>400</w><h>30</h></coordinates><panel_attributes>Domain
|
||||||
|
bg=blue</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLNote</id><coordinates><x>20</x><y>340</y><w>400</w><h>30</h></coordinates><panel_attributes>Exposition
|
||||||
|
bg=red</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLNote</id><coordinates><x>1080</x><y>340</y><w>400</w><h>30</h></coordinates><panel_attributes>Infrastructure
|
||||||
|
bg=green</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>90</x><y>450</y><w>130</w><h>100</h></coordinates><panel_attributes>lt=-
|
||||||
|
m1=0..*
|
||||||
|
m2=0..*</panel_attributes><additional_attributes>10;10;10;70;110;70</additional_attributes></element><element><id>Relation</id><coordinates><x>60</x><y>450</y><w>160</w><h>180</h></coordinates><panel_attributes>lt=-
|
||||||
|
m1=0..*
|
||||||
|
m2=0..*</panel_attributes><additional_attributes>10;10;10;150;140;150</additional_attributes></element><element><id>UMLClass</id><coordinates><x>200</x><y>500</y><w>90</w><h>60</h></coordinates><panel_attributes>CatalogDto
|
||||||
|
--
|
||||||
|
id: UUID
|
||||||
|
name: String</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>200</x><y>580</y><w>180</w><h>80</h></coordinates><panel_attributes>ItemDto
|
||||||
|
--
|
||||||
|
id: UUID
|
||||||
|
name: String
|
||||||
|
isShared: Boolean</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>50</x><y>410</y><w>110</w><h>50</h></coordinates><panel_attributes>MarketplaceDto
|
||||||
|
--
|
||||||
|
</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>1120</x><y>470</y><w>130</w><h>60</h></coordinates><panel_attributes>CatalogJpaEntity
|
||||||
|
--
|
||||||
|
id: UUID
|
||||||
|
name: String</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>1280</x><y>460</y><w>180</w><h>80</h></coordinates><panel_attributes>ItemJpaEntity
|
||||||
|
--
|
||||||
|
id: UUID
|
||||||
|
name: String
|
||||||
|
sharedDate: ZonedDateTime</panel_attributes><additional_attributes></additional_attributes></element></diagram>
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
target:
|
|
||||||
url: http://localhost
|
|
||||||
port: 51001
|
|
||||||
@@ -6,10 +6,7 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"test:demo": "yarn build && k6 run dist/tests/load-tests.cjs",
|
"start": "yarn build && k6 run dist/tests/load-tests.cjs"
|
||||||
"test:demo-stages": "yarn build && k6 run dist/tests/reqres-stages.cjs",
|
|
||||||
"test-with-monitoring:demo": "yarn build && docker run --platform linux/amd64 -it -p 5665:5665 -v $(pwd)/dist/:/src ghcr.io/grafana/xk6-dashboard:0.6.1 run --out 'dashboard=period=2s' /src/tests/reqres.cjs",
|
|
||||||
"test-with-monitoring:demo-stages": "yarn build && docker run --platform linux/amd64 -it -p 5665:5665 -v $(pwd)/dist/:/src ghcr.io/grafana/xk6-dashboard:0.6.1 run --out 'dashboard=period=2s' /src/tests/reqres-stages.cjs"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "7.23.3",
|
"@babel/core": "7.23.3",
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import {logWaitingTime} from "../utils/logger";
|
|||||||
import {Trend} from "k6/metrics";
|
import {Trend} from "k6/metrics";
|
||||||
import {check} from "k6";
|
import {check} from "k6";
|
||||||
import {Response} from "../data/common";
|
import {Response} from "../data/common";
|
||||||
|
import {TARGET_URL} from "../tests/config";
|
||||||
|
|
||||||
// Metrics that we want to track
|
// Metrics that we want to track
|
||||||
const metrics = {
|
const metrics = {
|
||||||
@@ -11,9 +12,7 @@ const metrics = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const getMarketplace = (): Response<Marketplace> => {
|
export const getMarketplace = (): Response<Marketplace> => {
|
||||||
const serverUrl = `http://localhost:51001`;
|
const urlToTest = `${TARGET_URL}/api/marketplace`;
|
||||||
|
|
||||||
const urlToTest = `${serverUrl}/api/marketplace`;
|
|
||||||
const response = http.get(urlToTest);
|
const response = http.get(urlToTest);
|
||||||
|
|
||||||
logWaitingTime({
|
logWaitingTime({
|
||||||
|
|||||||
@@ -1 +1,6 @@
|
|||||||
export const VUs = 1
|
export const VUs = 1;
|
||||||
|
// @ts-ignore - if it is unused
|
||||||
|
const VIRTUAL_THREADS_APP_PORT = 51001;
|
||||||
|
// @ts-ignore - if it is unused
|
||||||
|
const REACTOR_APP_PORT = 52001;
|
||||||
|
export const TARGET_URL = `http://localhost:${VIRTUAL_THREADS_APP_PORT}`;
|
||||||
0
local/postgresql/.gitkeep
Normal file
0
local/postgresql/.gitkeep
Normal file
Reference in New Issue
Block a user