Requirements
Functional Requirements:
- Allow reservation of a parking spot.
- User should be shown a UI layout of all the parking spots with visible indicator for the size of the car park so that he can choose accordingly. Booked slots should be shown in red and available slots should be shown in green
- Process payment for the reservation.
- Enable parking of a car in the reserved spot.
- For a person who has reserved the parking, he should be able to click on a button -> navigate to parking. and he should be shown a map with navigation to that parking.
- Support early departure before reservation time expires.
- No refund for the early departure, but the slot should become available for the next person
- Gate check-in/out.
- User should be able to show a QR code to the scanner at the check in and his entry time will be recorded. At the exit, the same QR should be shown and exit time will be recorded. If he has crossed the initial purchased time, we need to charge for the extra time. This will be manual
- Handle no show.
- If a booked slot is not checked in for more than 15 mins from the time of booking, we need to mark that booking as no show and make it available
Non-Functional Requirements:
- List the key non-functional requirements (eg low latency, scalability, reliability, etc.)...
- Scalability
- Parking reservation is expected to be deployed across malls and office spaces in the USA. Therefore expect a large volume of traffic. Let's say an average mall attracts 10000 people per day.Let's say 60% of the people who come to malls come in cars. We are looking at 6000 people per day. let's divide this among 12 hours. An average of 500 per hour for a mall. Let's assume we have around 1000 malls in USA. Expect something like 500000 requests per hour peak load.
- Average load should be 300000 requests per hour
- High Consistency
- Our system involves reservation and payment, hence a very high level of consistency is expected. We should be able to handle concurrent requests for reservation
- Concurrent reservation - We should resolve ti by whichever request reaches first
- Duplicate payment - When user clicks on pay or book the slot, the button should get disabled. Using idempotent key, we should ensure that there is no duplicate payment or booking from the same person
- Our system involves reservation and payment, hence a very high level of consistency is expected. We should be able to handle concurrent requests for reservation
- Availability
- While high availability is desirable, this system is meant to prioritize consistency. hence if there is any network partition, we should reject the request and not accept. The system should target availability for 99.9 % of the time
API Design
- Retrieve all the available slots
- get: /api/v1/getAllSlots -> List<SlotInfo>
- Retrieve info about an individual slot
- get : /api/v1/get/<slotId> -> SlotInfo
- Reserve a particular slot
- put: /api/v1/reserve/<slotId> -> ReservationConfirmation
- Check in to reserved slot
- put: /api/v1/checkin/<slotId> -> CheckinTime
- Check out from reserved slot
- put: /api/v1/checkout/<slotId>
- Payment completed callback
- PUT : /api/v1/payment/completed/
High-Level Design
Describe the overall system architecture. Identify the main components needed to solve the problem end-to-end. Use the diagramming tool to create a block diagram.
The main class of this is the ParkingSlot
ParkingSlot
{
car_park_id: long,
slot_id: long,
is_booked : boolean,
booking_start_time: DateTime,
booking_end_time: DateTime,
is_occupied: boolean,
category: Vehicle_Size,
latitude: float,
longitude: float,
in_time: DateTime
}
Vehicle_Size Enum {
SUV , SEDAN, COUPE, HATCH_BACK, MOTOR_CYCLE }
Following are the main components to solve the problem end to end
- Load Balancer
- We will use Nginx to distribute requests from clients to the app servers that host the UI components.
- Application server
- UI
- We will start with 3 UI servers. Nginx will distribute the requests to individual server based on load
- Backend API
- Slot management service
- Reservation service
- Payment service
- UI
- Cache
- Cache will be used to store the most commonly searched park's slots
- This will be an LRU cache
- Cache will be invalidated any time the park's slots are updated
- Cache will also come with a TTL of 30 mins
- DB
- We will be using an RDBMS based DB like MySQL as we have more structured data and no joins as such
- We need to write and read in equal measures and hence we will use MySQL
- We will be sharding the database into 3 shards and we will split the data according to the park's id. this will ensure that the data is split evenly
- API Services
- Slot Management service
- This service is used by the UI to collect information about all the slots of a particular parking lot
- Slot management service will first query the cache with the given parking id. If it's available, it serves that data.
- If cache miss, it fetches the data from DB and updates in cache and then returns the list of all SlotInfo for that parking lot
- Slot management service will also provide information about an individual slot
- this is done by looking up the cache. If miss, we retrieve from DB and update in cache
- Slot management service will also handle check in and checkout of the car
- Check in
- At the check in gate, the user shows his booking id QR code and the check in API is called
- check in service will mark the check in time of the car in the database
- Check out
- At the check out gate, the user shows his booking id QR code and the check out API is called
- Check out service will ensure that the total time spent ( check out time - check in time ) is within the reserved time and then allows to exit. The Check in and check out fields are cleared and the slot is marked available
- If any extra time is spent, we need to direct to payment service and allow to exit only after payment is successful.
- Reservation service
- This service is used to reserve an available slot
- Service will directly check in the database and lock the slot.
- Session is started for 5 mins. The transaction needs to be closed within that time . Each slot will correspond to one row in the table and it will be locked for the duration of the session. This will ensure that if two people try to reserve at the same time only one will be successful and the other will get an error message saying slot is unavailable and ask to try another slot
- Reservation service will call the payment service to complete the payment.
- Payment service
- The Payment service is called by the reservation and the check out services to complete payment
- Reservation payment
- The payment service is called by reservation service along with the payment details
- The payment service will then call the Payment gateway ( Stripe / Visa / UPI ) along with the payment details and an idempotent key.
- The payment service will also provide a call back endpoint to the payment gateway. The gateway will call the endpoint after the transaction is complete
- Once the callback API is hit, we update the calling service -> reservation
- Reservation service then updates the SlotInfo in DB and the session is closed successfully and lock on DB is also released
- Checkout service
- The payment service is called by reservation service along with the payment details
- The payment service will then call the Payment gateway ( Stripe / Visa / UPI ) along with the payment details and an idempotent key.
- The payment service will also provide a call back endpoint to the payment gateway. The gateway will call the endpoint after the transaction is complete
- Once the callback API is hit, we update the calling service -> checkout
- Checkout service will then update the gates to open if payment is successful
- Slot Management service
Detailed Component Design
Deep dive into 2-3 key components. Explain how they work, how they scale, discuss tradeoffs, capacity, and any relevant algorithms or data structures.
- Conflict resolution - What happens when two users try to reserve the same slot
- We can implement a temporary locking in the DB whenever a user selects a slot with a TTL of 5 mins. so no other user can see that slot available
- If two users see the same slot as available and try to block it, the Database will atomically lock whichever request reaches it first and it will block and mark the slot unavailable for the TTL. The second request will be denied and that user will get an error message asking to book another slot if available or retry after 5 mins which is our TTL for the other user's session
- Role of cache
- We are fetching data from the cache to display availability. How do we prevent a stale cache entry from displaying the wrong status
- We can opt for a write through and read through cache. How it works is whenever we need to update some data , we will update the cache and that will update the DB. Likewise we will never directly read from the DB, but only from the cache. So cache will always have the latest data
- We are fetching data from the cache to display availability. How do we prevent a stale cache entry from displaying the wrong status
- Duplicate requests
- It is possible that same user tries to block the same seat probably because his browser closed or for some other reason. This can be handled in the following way
- When we lock the slot we do so with a unique idempotent key. that includes a combination of the user id, the slot info and the time . So when the user tries to reserve again in a duplicate request, we indicate that it is already blocked and he can continue with the booking or if it's already reserved, we can mark that it's reserved already
- It is possible that same user tries to block the same seat probably because his browser closed or for some other reason. This can be handled in the following way