Storage: 1000 per day for 300 bytes that is 300k a day , ~ 10MB a month, 100MB a year with projection of 500MB in 5 years
Bandwidth: average request is 300 bytes 1000 cars with 5 requests on average 1.5 MB inbound traffic a day.
The design of user profile, registration, etc. is out of scope
Get a map of all the available spots with their status
GET /spots?from={from}&to={to}
Params:
Statuses
Response
{
spots: [
{
"id": $spotId,
"position": {"x": $x, "y": $y},
"vehicleType": $vehicleType,
"availability": [ {
"from": $from,
"to": $to
}
//...
]
}
//...
]
}
// error
{
"code": code // number
"message": message // can be the key for i18n
}
GET /spots/{id}?from={from}&to={to}
Params:
Statuses
Response
{ "id": spotId, "vehicleType": vehicleType, "availability": [ { "from": from, "to": to } //... ] } // error { "code": code // number "message": message // can be the key for i18n }GET /users/{id}/reservations
Params:
Statuses
Response
[ { "id": spotId, "vehicleType": vehicleType, "from": from, "to": to, "status": "BOOKED|CANCELLED|DELETED|STOPPED" "billed": true|false } ] // error { "code": code // number "message": message // can be the key for i18n }GET /users/{id}/reservations/{rid}
Statuses
Response
{ "id": spotId, "vehicleType": vehicleType, "from": from, "to": to, "status": "BOOKED|CANCELLED|DELETED|STOPPED", "billed": true|false } // error { "code": code // number "message": message // can be the key for i18n }POST /users/{id}/reservations
Statuses
Body:
{ "spotId": spotId, "startTimestamp": startAt, "endTimestamp": endAt, } </pre><p></p><h3>Create a reservation</h3><p>PATCH /users/{id}/reservations/{rid}</p><p><strong>Statuses</strong></p><ul><li>201 no Content</li><li>404: the reservation doesn't exist</li><li>401: if the user is not authenticated</li><li>403: if the user is not authorized to see the reservations</li><li>500 internal server error</li></ul><p><strong>Body:</strong></p><pre data-language="javascript"> { "spotId": spotId, "startTimestamp": startAt, "endTimestamp": endAt, }Response
// error { "code": code // number "message": message // can be the key for i18n }DELETE /users/{id}/reservations/{rid}
Statuses
Response
// error { "code": code // number "message": message // can be the key for i18n }PATCH /users/{id}/reservations/{rid}/stop
Statuses
Body:
{ "timestamp": timestamp } </pre><p><strong>Response</strong></p><pre data-language="javascript"> // error { "code": code // number "message": message // can be the key for i18n } </pre><p></p><h3>Gate Check-In</h3><p>PATCH /users/{id}/reservations/{rid}/check-in</p><p><strong>Statuses</strong></p><ul><li>201 no content</li><li>404 the reservation doesn't exist</li><li>401: if the user is not authenticated</li><li>403: if the user is not authorized to see the reservations</li><li>500 internal server error</li></ul><p><strong>Body:</strong></p><pre data-language="javascript"> { "timestamp": timestamp }Response
// error { "code": code // number "message": message // can be the key for i18n }PATCH /users/{id}/reservations/{rid}/check-out
Statuses
Body:
{ "timestamp": timestamp } </pre><p><strong>Response</strong></p><pre data-language="javascript"> // error { "code": code // number "message": message // can be the key for i18n } </pre><p></p><h3>Finalize reservation</h3><p>POST /users/{id}/reservations/{rid}/finalize</p><p><strong>Statuses</strong></p><ul><li>201 no content</li><li>404 the reservation doesn't exist</li><li>401: if the user is not authenticated</li><li>403: if the user is not authorized to see the reservations</li><li>500 internal server error</li></ul><p><strong>Body</strong></p><pre data-language="javascript"> { "timestamp": timestamp }Response
// error { "code": code // number "message": message // can be the key for i18n }POST /users/{id}/reservations/{rid}/pay
Statuses
Body
{ "timestamp": timestamp } </pre><p><strong>Response</strong></p><pre data-language="javascript"> // error { "code": code // number "message": $message // can be the key for i18n }Notes on Design:
Design at scale, multi-location:
With the introduction of multi-location, we need to allow a new functionality for geolocation search, which makes something like Elasticsearch for full-text search very appealing.
All the components are horizontally scalable, but the real challenge is how to make the changes in the parking spot hold linearizable so we don't get conflicts and double bookings.
A solution is to use the geo-location sharding and make sure that the writes happen only on the
leader of this shard, or at least introduce read repair across multi location cluster.
The database is pretty straightforward: we are using a structured database because we are not dealing with unstructured data
lots:
slots:
user_info:
id: unique, primary key
user_vehicles:
reservations:
payment:
Once we scale to multi-location, the sharding should be done based on geo locations for the slots and reservations.
Users can be sharded in multiple ways:
I think I added everything I needed to add.