Develop an HTTP API for a team-member management application, with data persistence in Mongodb. All actions should be stored in the database.
Multi-user cases or authentication aren't implemented. Assuming all clients see the same list of team members.
One user has multiple version based on update.
erDiagram
User {
ObjectId id
string firstName
string lastName
string phone
string email
UserRole role
Date createdAt
Date updatedAt
}
UserVersion {
ObjectId id
string userId
OperationType operation
string firstName
string lastName
string phone
string email
UserRole role
Date createdAt
Date updatedAt
}
User ||--o{ UserVersion : "has"
To store versions, I have used change stream of MongoDB. All the operations are caught in the change stream and stored in another collection.
flowchart TB
api(API)
server(Server)
mongo[(Mongo DB)]
changestream(Change Stream)
consumers(Consumers)
api --> server;
server --> mongo;
mongo --Get row changes--> changestream;
changestream --> consumers;
consumers --Add new version--> mongo;
npm install --force
This project requires a MongoDB cluster with replication enabled to activate change streams.
There is a docker-compose.yml
file for starting Mongo cluster.
docker-compose up
To drop collections in MongoDB, use the drop() method. This is required to avoid errors.
mongosh
use sample
db.user_versions.drop();
db.users.drop();
Set the environment variables for the database name (DB_NAME) and URL (DB_URL):
export DB_NAME=sample
export DB_URL=mongodb://localhost:27017
Then, run Nest as usual:
npm start
Make sure to restart the service if you drop the collection.
curl --location 'localhost:3000/users' \
--header 'Content-Type: application/json' \
--data-raw '{
"firstName": "John",
"lastName": "Doe",
"email": "[email protected]",
"phone": "+919999999999",
"role": "admin"
}'
curl --location --request PUT 'localhost:3000/users/:user_id' \
--header 'Content-Type: application/json' \
--data-raw '{
"email": "[email protected]"
}'
curl --location 'localhost:3000/users'
curl --location 'localhost:3000/users/:user_id'
curl --location --request DELETE 'localhost:3000/users/:user_id'
curl --location 'localhost:3000/users/:user_id/versions'
We need to keep track of the pointer ID for changes in the change stream. Currently, it is missing. It can be synchronized in Redis. In the current scenario, server shutdowns can cause us to miss the changes if the data is modified.
To make it more resilient, we can implement Debezium + Kafka to directly sync changes to the database. This approach eliminates some implementations but comes with a higher learning curve and added expense. Additionally, it is less flexible.
Currently, all users have the ability to change anything, indicating a need for improvement. Additionally, implementing pagination could enhance speed. However, some indexes are missing, which is an area that could be improved.
Regarding quality assurance (QA), the addition of test cases is crucial. Although I've integrated the framework, the test cases are still missing. With this, proper error handling could be addressed.