Candidate: Rachel Sheikh
Email: sheikhrachel97@gmail.com
Date: 28.10.2022
This project is a web server build with go 1.19
, serving traffic with gin
Don't feel like cloning the repo? Use the deployed server to try out requests! Endpoints below
https://rsheikh-future.herokuapp.com/appointments/bookings/1
should return trainer 1's booked appointments!
Don't feel like installing Go / dealing with dependencies? Use the bundled in build!
From the root:
./server
missing go 1.19? Head on over to go downloads and follow the steps to set it up!
go version
should output something like
go version go1.19.1 darwin/arm64
Now let's download our dependencies
go mod get
And finally, let's start our server
go run main.go
This will start the server at http://localhost:8080
.
Note: Make sure this socket isn't in use when the run command is triggered, or the server won't start!
POST /appointments/new
Creates a single new appointment with a valid request body
Request
{
"id": "int unique appointment id",
"trainer_id": "int trainer id",
"user_id": "int user id",
"starts_at": "string datetime RFC 3999",
"ends_at": "string datetime RFC 3999"
}
ex.
{
"ended_at": "2019-01-24T10:30:00-08:00",
"id": 2,
"user_id": 2,
"started_at": "2019-01-24T10:00:00-08:00",
"trainer_id": 1
}
Response
{
"appointment_added": {
"id": 2,
"trainer_id": 1,
"user_id": 2,
"started_at": "2019-01-24T10:00:00-08:00",
"ended_at": "2019-01-24T10:30:00-08:00"
}
}
POST /appointments/new/batch
Creates multiple new appointments with a valid request body.
Request
[
{
"id": "int unique appointment id",
"trainer_id": "int trainer id",
"user_id": "int user id",
"starts_at": "string datetime RFC 3999",
"ends_at": "string datetime RFC 3999"
}
]
ex.
[
{
"id": 2,
"trainer_id": 1,
"user_id": 2,
"started_at": "2019-01-24T10:00:00-08:00",
"ended_at": "2019-01-24T10:30:00-08:00"
},
{
"id": 3,
"trainer_id": 1,
"user_id": 3,
"started_at": "2019-01-25T10:00:00-08:00",
"ended_at": "2019-01-25T10:30:00-08:00"
}
]
Response
{
"appointments_added": [
{
"id": 2,
"trainer_id": 1,
"user_id": 2,
"started_at": "2019-01-24T10:00:00-08:00",
"ended_at": "2019-01-24T10:30:00-08:00"
},
{
"id": 3,
"trainer_id": 1,
"user_id": 3,
"started_at": "2019-01-25T10:00:00-08:00",
"ended_at": "2019-01-25T10:30:00-08:00"
}
]
}
GET /appointments/availability
Returns availability for a trainer within the request window
Request
{
"ends_at": "string datetime RFC 3999",
"starts_at": "string datetime RFC 3999",
"trainer_id": "int trainer id"
}
ex.
{
"ends_at": "2019-01-24T12:00:00-08:00",
"starts_at": "2019-01-24T10:00:00-08:00",
"trainer_id": 1
}
Response
{
"trainer_id":1,
"upcoming_availability":[
"2019-01-24T09:30:00-08:00",
"2019-01-24T10:00:00-08:00",
"2019-01-24T10:30:00-08:00",
"2019-01-24T11:00:00-08:00",
"2019-01-24T11:30:00-08:00",
"2019-01-24T12:00:00-08:00",
"2019-01-24T12:30:00-08:00"
]
}
GET /appointments/bookings/:trainer_id
Returns booked appointments for a trainer
No request body, param passed in with the path
Response
{
"bookings": [
{
"id":0,
"trainer_id":1,
"user_id":1,
"started_at":"2019-01-24 10:00:00 -0800 PST",
"ended_at":"2019-01-24 10:30:00 -0800 PST"
},
{
"id":1,
"trainer_id":1,
"user_id":2,
"started_at":"2019-01-24 11:00:00 -0800 PST",
"ended_at":"2019-01-24 11:30:00 -0800 PST"
}
],
"trainer_id": 1
}
- Server handles M-F 8a-5p Pacific validation
- Server handles :30 and :00 start time validation
- Appointment IDs are generated by the client, and the server will only store new unique appointment ids
- All appointments are 30 minutes long, so client will always send an end time that fits this duration from the provided start
- Papertrail integration for loud logs
- RDS Postgres instance for data storage
- Update
/appointments/availability
and/appointments/booked/:trainer_id
to be paginated - Integrate Redis as a write-through cache to better handle concurrent appointment reads/writes
- Integrate Cloudwatch to fetch production metrics and dashboard endpoint health/latency/rps
- Setup CodePipeline and deploy to EC2 instance
- Add feature flag/dynvar tooling
- Update rate limit config based on usage
- Migrate
appointment_service
to a separate microservice that receives grpc forwarded requests from respective endpoints - Add mock interface generation via counterfeiter
- Integrate
gin-swagger
for more thorough api documentation - Perform further load testing (vegeta/siege/custom script) to calculate upper limit on concurrent requests
- Add commit pre-hooks (rapid endpoint validation/linting/testing)
- Add one-off/scheduled cron job tooling
- Integrate secrets manager for config secrets
- Identify areas for async computation with goroutines
- Increase unit test coverage to enable simultaneous development and regression coverage
- Integrate Slack alerts for ci/cd and server panics
- Integrate Pagerduty for critical non-recoverable panics
- Update
AddNewAppointment
to handle conflicting appointments for the same user or the same trainer at a given start time - Increase test coverage beyond integration tests to cover methods