Requirements
Functional Requirements:
- Allow reservation of a parking spot.
- Process payment for the reservation.
- Enable parking of a car in the reserved spot.
- Support early departure before reservation time expires.
- Gate check-in/out.
- Handle no show.
Non-Functional Requirements:
- Low latency: quick payment processing
- High availability
- Consistency: in case of network partition successful payment still should be saved
- Strong consistency: parking spot should not be overbooked by two different people
API Design
Core enteties:
Parking spot
user
reservations
Table USERS:
user_id[primary key]
//other metadata
Table SPOTS:
parking_id[primary key],
price,
//other metadata
Table RESERVATIONS:
reservation_id[pk]
user_id[fk]
parking_id[fk]
from
to
checkin_time
checkout_time
created_at
API:
// list of available parkings in given log
GET /parkings?from_time={from_time}&to_time={to_time}&page={page}&count={count} ->{
available_parkings[] : {
parking_id,
price
}
}
// create new reservation
POST /users/reservations->{ parking_id = {parking_id}, from={from}, to={to},
payment_details={details} } -> 201
// get all users reservations
GET /users/reservations->{
reservations_info[] : {
parking_id, from, to
}
}
// cancel reservation
DELETE /users/reservations ->{
parking_id, from, to
}
// check in user
PUT /users/check_in->{
parking_id,
checkin_time={time}
}
// check out user
PUT /users/check_out->{
parking_id,
checkout_time={time}
}
High-Level Design
- api requests enter api gateway
- application server transfer request to corresponding service:
- To retrieve available spots we query db: SELECT parking_id, SUM(IF(Reservation.to <= from OR Reservation.from >=to, 0, 1)) as overlap_count FROM Spots LEFT JOIN Reservations ON parking_id GROUP BY parking_id HAVING overlap_count = 0
- to book reservation we send request to payment service that redirects it to stripe
- Once payment is processed we create new record in DB
- to check in we check in/out reservation time and update record in reservations
Detailed Component Design
- to support high throuput we place LB infront of app service to distribute load
- to optimze storage we shard DB using user_id parking_id to grand that all requests for user will hit single shard
- to optimize sql queries we will introduce cache infront of DB
- we will use sql db
- LB+sharding+cache grant high availability of the service
- to grant strong consitency we will introduce kafka as event broker(partitioned by parking_id) for all reservation event. that will guaranty that no two users will overbook the same lot