Domain Driven Designed Application example to show the usage of the different soa-php libraries
This repo contains the code examples explained in the post series:
- Implementing a use case (I) - Intro
- Implementing a use case (II) - Command Pattern
- Implementing a use case (III) - Command Bus
- Implementing a use case (IV) — Domain Events (I)
- Implementing a use case (IV) — Domain Events (II)
- Implementing a use case (V) — Given-When-Then Testing Style
- To be continued...
There are 3 bounded contexts:
- Log User In With Password
- Refresh User Access Token
- Create a Pull Request
- Assign a Reviewer to a Pull Request
- Approve a Pull Request
- Merge Pull Request
- Pay money
- Collect Money
Merging a Pull Request is an automated process consisting of the next flow:
- When all the assigned reviewers approve the Pull Request, the Pull Request is marked as mergeable
- When the Pull Request is marked as mergeable, the system automatically pays to the reviewers the corresponding reward and charges the creator of the Pull Request a fee.
- When all the payments (collecting and paying the money) are successfully performed the system merges the Pull Request
The Merge Pull Request Process Manager handles this flow.
If you want to play around with the code you just need to:
- Install
docker
anddocker compose
tools. - Run the installation script (it will take long until all dependencies are installed):
./install.sh
- Start mongo and rabbitmq services:
docker-compose -f docker/infra-docker-compose.yml up
- Start bounded context services:
docker-compose -f docker/services-docker-compose.yml up
If you want to test how the application behaves you can:
-
Use Restlet and import the config file. Then go to the SCENARIOS tab and run the Code Review Scenario.
-
Use
curl
from the command line following the next steps:
- Create a User with
writer
role:
curl -i -X POST -H "Content-Type:application/json" -H "Id:http-request-id" -d '{ "email": "writer@email.com", "password": "some password", "username": "writer", "roles": ["writer"] }' 'http://localhost:8081/users/login/password'
- Create a User with
reviewer
role:
curl -i -X POST -H "Content-Type:application/json" -H "Id:http-request-id" -d '{ "email": "reviewer@email.com", "password": "some other password", "username": "reviewer", "roles": ["reviewer", "writer"] }' 'http://localhost:8081/users/login/password'
- Create another User with
reviewer
role:
curl -i -X POST -H "Content-Type:application/json" -H "Id:http-request-id" -d '{ "email": "another_reviewer@email.com", "password": "some password", "username": "another_reviewer", "roles": ["reviewer"] }' 'http://localhost:8081/users/login/password'
- Create a Pull Request replacing the
writer_access_token
placeholder with the access token returned when you created the writer in step 1:
curl -i -X POST -H "id:ddc42abd-f1b8-4078-8238-a265282bfbfa" -H "Authorization:Bearer {writer_access_token}" -d '{"code":"some code"}' 'http://localhost:8080/pull-requests'
- Assign a Reviewer:
{writer_access_token}
: the access token returned in step 1.
{reviewer_id}
: the UUID returned in the Location
header in step 2.
{pull_request_id}
: the UUID returned in the Location
header in step 4.
curl -i -X PUT -H "Content-Type:application/json" -H "id:79d4ee69-6e2f-4e6d-b338-9c68ecb88468" -H "Authorization:Bearer {writer_access_token}" -d '{ "reviewer": "{reviewer_id}" }' 'http://localhost:8080/pull-requests/{pull_request_id}/reviewer'
- Assign another Reviewer:
{writer_access_token}
: the access token returned in step 1.
{reviewer_id}
: the UUID returned in the Location
header in step 3.
{pull_request_id}
: the UUID returned in the Location
header in step 4.
curl -i -X PUT -H "Content-Type:application/json" -H "id:79d4ee69-6e2f-4e6d-b338-9c68ecb88468" -H "Authorization:Bearer {writer_access_token}" -d '{ "reviewer": "{reviewer_id}" }' 'http://localhost:8080/pull-requests/{pull_request_id}/reviewer'
- Approve the Pull Request by one Reviewer:
{reviewer_access_token}
: the access token returned in step 2.
{pull_request_id}
: the UUID returned in the Location
header in step 4.
curl -i -X PUT -H "Content-Type:application/json" -H "Id:d0e2b3e4-53d0-4010-a486-e1a0cf895bce" -H "Authorization:{reviewer_access_token}" -d '' 'http://localhost:8080/pull-requests/{pull_request_id}/approve'
- Approve the Pull Request by the other Reviwer:
{reviewer_access_token}
: the access token returned in step 3.
{pull_request_id}
: the UUID returned in the Location
header in step 4.
curl -i -X PUT -H "Content-Type:application/json" -H "Id:d0e2b3e4-53d0-4010-a486-e1a0cf895bce" -H "Authorization:{reviewer_access_token}" -d '' 'http://localhost:8080/pull-requests/{pull_request_id}/approve'
- At this point, since all reviewers have approved the Pull Request, the Process Manager starts managing the process to charge and pay the money, and then merge the Pull Request.
You can check the data created by connecting to the Mongo database which is listening at localhost:27017
without user nor password required. You can also check the queues and exchanges created in RabbitMQ by opening in your browser the URL http://localhost:15672/#/
. You can login into local RabbitMQ Manager using the user "devuser" with the password "devpass".
Each Bounded Context has a run.sh
script, if you want to run the unit tests you just need to go to the Bounded Context folder and execute:
cd PullRequest
./run.sh phpunit