Skip to content

sheikhrachel/future

Repository files navigation

Future Take-Home Interview

Candidate: Rachel Sheikh
Email: sheikhrachel97@gmail.com
Date: 28.10.2022

Quickstart

This project is a web server build with go 1.19, serving traffic with gin

Option 1: Using the live server

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!

Option 2: Using the bundled server executable

Don't feel like installing Go / dealing with dependencies? Use the bundled in build!

From the root:

./server

Option 3: Using go run main.go

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!

Overview

Available Endpoints

Post a new appointment (as JSON) - single

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 a new appointment (as JSON) - batch

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 a list of available appointment times for a trainer between two dates

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 a list of booked appointments

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
}

Assumptions

  • 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

Infra set up

  • Papertrail integration for loud logs
  • RDS Postgres instance for data storage

Next Steps (shortlist)

  • 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

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages