This is a chat system that allows user to create applications, chats and messages. Also, it allows the user to search for messages in a chat.
This is our main application. It has APIs to create and get Applications, Chats and Messages. It is connected to the MySQL db, Redis (for caching and queueing) and Elasticsearch. All creation and update APIs are served asyncronously.
This is a creation service. It just creates chats and messages. It is connected to redis to update and get ids of different entities.
This is the main database. It stores all the data that is used by the Ruby Service.
This is used by the Ruby Service and Golang Service for caching and queueing. Note that the cache is used for some of the apis not all of them.
This is used by the Ruby Service to store the messages that are created. It is used then for searching in messages.
This system uses Sidekiq to proccess the jobs asyncronously. It uses redis
as the underlying queue.
This worker is responsible for inserting the new application in MySQL
db. A job is enqueued to this worker when Create Application API
is hit.
This worker inserts a new chat passed in the queue to MySQL
db. This worker serves the Create Chat API
.
This worker does exactly what previous workers do. However, it also inserts a new message to Elasticsearch
This updates the chatsCount
column in the Application
table. This runs async after Create Chat API
.
This also updates the messagesCount
column in the Message
table. However, this is called after Create Message API
This worker is responsible to update the messages in 2 places, first the Elasticsearch
. It gets the _id
of the doc from MySQL
db and
then updates the message
in Elasticsearch
, and then updates the MySQL
db entry. Note that failing in this job could create duplicate
entries in Elasticsearch
(for example, failing to insert in the db for some reason). This could be mitigated by a clean job that cleans the dangling records in Elasticsearch
.
- Clone it
git clone https://github.com/MohamedShetewi/awesome-system
- Navigate to project dir by
cd awesome-system
. - Run
docker compose up
.- Note that
Elasticsearch
takes sometime to start. So theruby-app
will keep restarting untilElasticsearch
is ready.
- Note that
ruby-service
will be available on port3001
andgo-service
will be on8000
POST /application
{
"username": "Shetewi"
}
{
"Application": "dec969c6",
"Username": "Shetewi"
}
curl --location 'http://localhost:3001/application' \
--header 'Content-Type: application/json' \
--data '{
"username": "Shetewi"
}'
GET /application/:id
{
"Application": "7aa269eb",
"Username": "Shetewi",
"ChatsCount": "0"
}
curl --location 'localhost:3001/application/7aa269eb'
POST /application/:application_id/chats
{
"Application": "dec969c6",
"Chat": 8
}
Ruby Service
curl --location --request POST 'localhost:3001/application/dec969c6/chat'
Golang Service
curl --location --request POST 'localhost:8000/application/dec969c6/chat'
GET /application/:application_id/chat/:id
{
"Application": "dec969c6",
"Chat": 5,
"MessagesCount": null
}
curl --location 'localhost:3001/application/dec969c6/chat/5'
POST /application/:application_id/chat/:chat_id/message
{
"message": "Hello, World!"
}
{
"Application": "dec969c6",
"Chat": 5,
"MessageID": 3,
"Message": "Hello world again for the not last time"
}
Ruby Service
curl --location 'localhost:3001/application/dec969c6/chat/5/message' \
--header 'Content-Type: application/json' \
--data '{"message":"Hello world again for the not last time"}'
Golang Service
curl --location 'localhost:8000/application/dec969c6/chat/5/message' \
--header 'Content-Type: application/json' \
--data '{"message":"Alhamdulilah"}'
GET application/:app_id/chat/:chat_id/search/:query
[
{
"appID": "dec969c6",
"chatID": 5,
"messageID": 4,
"message": "Alhamdulilah"
},
{
"appID": "dec969c6",
"chatID": 5,
"messageID": 5,
"message": "Alhamdulilah"
}
]
curl --location 'localhost:3001/application/dec969c6/chat/5/search/Alhamdulilah'
GET application/:app_id/chat/:chat_id/message/:message_id
{
"Application": "dec969c6",
"Chat": 5,
"MessageID": "3",
"Message": "Guess what? Alhamdulilah"
}
curl --location 'localhost:3001/application/dec969c6/chat/5/message/3'
PUT application/:app_id/chat/:chat_id/message/:message_id
{
"status": "success"
}
curl --location --request PUT 'localhost:3001/application/dec969c6/chat/5/message/3' \
--header 'Content-Type: application/json' \
--data '{"message": "Guess what? Alhamdulilah"}'
application/:app_id/chat/:chat_id/messages
{
"status": "success"
}
or
{
"error": "Message not found"
}
curl --location --request PUT 'localhost:3001/application/dec969c6/chat/5/message/3' \
--header 'Content-Type: application/json' \
--data '{"message": "Guess what? Alhamdulilah"}'