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 - the responses should be returned in less than 200ms
- scalability - it should be able to scale out in case of high demand
- availability - should have an up time of at least 99.99%
- consistency - strong consistrency is needed so in different threads we dont have different parking lots statuses (eg in one thread park lot x is occupied but in a different thread it is free and a car can be parked there)
API Design
db:
model parking:{
status: reserved | free | taken
reservationCreatedAt?:Date
reservedFrom?: Date
reservedUntil?: Date
paidAt?: Date
leftAt?:Date
carId:String
}
GET /parkings - shows all parkings details
POST /reserve/parking/{parkingId} body:{ reservedFrom: Date, reservedUntil: Date} - used for reserving a parking lot
POST /pay/parking/{parkingId} body:{ carId:string; cardDetails:JSON } - used for paying a parking lot
POST /park/parking/{parkingId}?is_parking={is_parking}&leaving_at={leaving_at} - used for parking a car and for leaving parking earlier or on time
POST /parking/{parkingId}/status/{status} - used by admins to reset the status of a parking in case of no show
High-Level Design
reserving, parking, leaving parking, updating parking status flow:
- client makes call to DNS to fetch the IP of domain.
- DNS responds with IP
- client makes API call to IP address
- call hits load balancer - we need one in case we must scale out and add multiple instances of services.
- load balancer routes to parking service which fetches parking cache and in case of updates it also mutates the cache and parking db or in case cache is missing on read, it fetches data from db directly
- response is returned to client
payment flow:
- same 4 steps as above
- load balancer routes to payment service which call payment API and updates parking db with paidAt: Date.now() in case of succesful payment or doesnt update the parking status and user must retry payment process
- response is returned to client
parking service is handling reservations, leaving, parking and updating a parking lot status. it firstly checks the cache and if missing, it checks/updates the db.
payment service is call a 3rd party api called Payment API, it could be stripe. based on the response, it updates the parking paidAt date or in case of failure, it prompts the user to retry the payment
Detailed Component Design
if 2 clients try to reserve the parking spot, parking service saves to db who reserved the parking and at what time (reservationCreatedAt) so before updating that parking lot as reserved, it checks if it wasnt already reserved. only if its status is "free" it will let the second customer reserve it.
the cache will be updated on each write/update so it wont be stale and wont lead to any inconsistencies