Skip to content

civilcoder55/rails-api

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

23 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Rails API

Instabug chat API (BE Engineer challenge).

Usage with docker

  1. Clone the repo
git clone https://github.com/civilcoder55/rails-api.git
  1. run containers
sudo docker-compose up -d
  1. access api at http://localhost:3000/api/v1

  2. access docs at http://localhost:4000/docs/

  3. run specs

sudo docker run --rm -it insta-task-ror-image rspec

API Client Collection

  • click image to download insomnia api collection [can work with postman]

API Endpoints

Applications Endpoints

Method URL Description
GET /api/v1/applications Retrieve all applications.
POST /api/v1/applications Create a new application.
GET /api/v1/applications/:token Retrieve application by token.
PUT /api/v1/applications/:token Update application by token.

Chats Endpoints

Method URL Description
GET /api/v1/applications/:token/chats Retrieve all application chats.
POST /api/v1/applications/:token/chats Create a new application chat.
GET /api/v1/applications/:token/chats/:number Retrieve application chat by number.

Messages Endpoints

Method URL Description
GET /api/v1/applications/:token/chats/:chat_number/messages Retrieve all chat messages.
POST /api/v1/applications/:token/chats/:chat_number/messages Create a new chat message.
GET /api/v1/applications/:token/chats/:chat_number/messages/:number Retrieve chat message by number.
GET /api/v1/applications/:token/chats/:chat_number/messages?query=:search Search chat messages by query.

screens

simple architecture diagram

ERD

Tests

break down the task requirements

  • for applications tokens :

    • used SHA1 hash with random string + timestamp to ensure uniqueness .
  • for resources numbring :

    • i choosed to keep tracking of numbring with cache store (Redis) instead of naive way of getting last resource number form database then increment it, so by this we save database hit
  • for hiding resouce ID :

    • it can be done with many ways, maybe not selecting id when reading form database , or using serializers or even custom representers like what i did so i wrapped resource result with representer and i customed what fields should be returned

  • for identifying the application by its token and the chat by its number along with the application token

    • i used nested resource to achieve this "/api/v1/applications/:token/chats/:number"
  • for partially search messages bodies with elasticsearch

    • i used simple elasticsearch text mapping to make use of inverted index that supports very fast full-text searches.

  • to be running on multiple servers and race conditions

    • for multiple server and centralized database and cache server scenario, we will have race condition when fetching and updating the next resource number for this we need some mutex locking, so redis provide us with atomic counter incr and also we don't need to locking as it's one atomic command.

  • to avoid writing directly to MySQL

    • i used queuing systme to push write operations to, and a sidekiq worker to consume and do writes, for queuing we can use any queuing system like rabbitmq,sqs,redis - i choosed redis
  • for updating counts in database

    • i used simple sidekiq cron task to run every 15 minutes to updated mysql columns from redis cache
  • i didn't implement pagination but for this i will go for cursor pagination because it perform better than offset

  • database indexing

    • i added index for application token
    • composite index for (application foriegn key + number) for chats and messages

Built With

  • Ruby (2.7.6)
  • Rails (5.2)
  • ElasticSearch (7.13.4)
  • MySQL
  • Redis

todo

  • read and analyze task doc
  • create new rails app and setup initial configs
  • create database models and migrations
  • create applications/chats/messages rest endpoints
  • integrate elasticsearch for message searching
  • add redis for chats/message counts tracking
  • queue database writes with sidekiq/redis
  • add counts updater cron
  • write specs
  • dockerize application stack
  • optimizing
  • create readme file