Parking lot API problem design, an API document example is available here
Install Docker + Docker Compose then run docker-compose up
If you want to run test, so open the new terminal then
docker exec -it ctn_parking_lot_api_alpha sh
> NODE_ENV=test npx sequelize db:create
> NODE_ENV=test npx sequelize db:migrate
> npm run validate
To access production ready container, then
docker exec -it ctn_parking_lot_api sh
- Scenario: free public parking
- Database: MySQL (DBMS)
- Parking lot: support multiple parking lots
(must be ordered with `rank` property to find *nearest slot*)
- Parking lot: not support multi-level
- Parking lot: only 1 entry point for each parking lot
- Concurrent processes: support by using database transaction feature to handle processes
(park the vehicle in the same time with different entry point)
- Size:
- 3 vehicle sizes => small, medium, large
- 3 slot sizes => small, medium, large
- Ticket and provided slot:
- Customer nice enough to park in the provided/assigned slot
- Vehicle must park at the same slot size only
(e.g. small vehicle park at small slot, medium vehicle park at the medium slot)
- The ticket system will find the *nearest slot*
(slot "rank" of each parking lot must be ordered by the distance between
slot itself and parking lot entry point)
- Pricing strategy: free
- Priority slot: none
- Goal: *fast parking* so searching nearest slot must fast
We create *n* stacks for caching available slot ids
(n = number of parking lot * number of slot size)
When we park a car then
1. get stacks
2. check if each stack for specific slot size has available slot ids
3. if there is available slot then remove the first slot from the stack
When we exit a parking lot
1. get the stack that related to our slot
2. concat *our slot* with *available stack slots* then sort it
3. update the stack with available-sorted-slots from 2)
- POST
/parking_lot
to create parking lot entity - POST
/vehicle/park
to park a vehicle - POST
/vehicle/exit
to release a vehicle slot (vehicle leave the parking slot) - GET
/parking_lot/status
to get available slots of all parking slots - GET
/ticket?slot_size_id=1
to get ticket by slot size (which contains registration plate numbers / slot numbers)
- Test: unit test
- Test: E2E test
- Docker:
Dockerfile
for development - Security concerns e.g. not expose
id
field directly from database - Hide 5xx error
- Encoding e.g. encode ticket id
- Archive strategy on ticket table that continually increase
- Load Balancer
- Kong API Gateway for authentication, rate-limit, etc.
- API: pagination support
- CI: E2E test
- CI: deploy coverage report to the service e.g. https://codecov.io/
- Create example of Kubernetes deployment
- Create example of Kubernetes service
- Distributed storage, incase the data is too big
- Limitation: where the limit of caching table
- Database: add index to optimize fast search
- Example code of client side with multi-stage builds
npx sequelize db:create
npx sequelize migration:generate --name create-slot_size-table
npx sequelize migration:generate --name add-index-into-slot_size-table
npx sequelize migration:generate --name create-slot-table
npx sequelize db:seed:all
npx sequelize db:seed:undo:all
npx sequelize db:migrate
npx sequelize db:migrate:undo:all
NODE_ENV=test npx sequelize db:create
NODE_ENV=test npx sequelize db:migrate
docker build --tag parking-lot-api:1.0.0 .
docker build -f ./Dockerfile --tag parking-lot-api:1.0.0 .
docker run --name ctn_parking_lot_api parking-lot-api:1.0.0
docker exec -it ctn_parking_lot_api sh
docker exec -it ctn_mysql sh
mysql -u root -p
docker rm ctn_parking_lot_api
docker rm ctn_mysql
docker rm -f $(docker ps -qa)
docker rmi parking-lot-api:1.0.0
docker images "parking-lot-api*" --no-trunc --format "{{.ID}}"
docker rmi $(docker images "parking-lot-api*" --no-trunc --format "{{.ID}}")
docker image prune
docker-compose up
docker-compose up --build -d
cd ./example
docker build -f ./Dockerfile --tag parking-lot-api-client:1.0.0 .
docker run -p 5008:5007 --name ctn_parking_lot_api_client parking-lot-api-client:1.0.0
curl localhost:5005
curl localhost:5006
curl localhost:5007