CodeExercise
This app listen to the port 3000 on http://localhost/ returning a json with a list of 2 users that matches a particular amount of points in the format of:
{
"users": [{"id": 1, "points": 10}, {"id": 1, "points": 10}],
"timestamp": "2021-12-07T06:57:00.00000"
}
The amount of points rotates every minute and are in a range of [0-100]
Each minute a process updates every user to add a random point to it.
Technical decisions
In order to comply with the initial requirements of seed 1_000_000 users, I opted to make the seeds use Ecto.Repo.insert_all/3
to insert the users in batches of 10_000
, to speed up the process.
The same apply for the GenServer that updates every user to set a random value for points
on each user.
To be able to update the users in a timely way, I opted to use Ecto.Repo.insert_all/3
again with upsert
clauses, to update the users in batches, and setting a different random number on the points
field.
On the Genserver, I also opted to update the users inside a concurrent Task to not block the GenServer queue. The task will not be awaited as the results of this operation are not needed.
Setup
The app was built using Elixir ~> 1.12.2
, Erlang 24
.
- Install dependencies with
mix deps.get
- Create and migrate your database with
mix ecto.setup
- Start Phoenix endpoint with
mix phx.server
or inside IEx withiex -S mix phx.server
Database dev/test
To connect to database on dev/test environment, the app expects to exist a PostgreSQL role with permission to create database with the following login:
- username:
remote_user
- password:
remote
Production Environment Variables
The app will look for the following environment variables when initializing on a prod
environment
- DATABASE_URL (mandatory) like
postgres://user:pass@host/database
- SECRET_KEY_BASE (mandatory)
- POOL_SIZE (optional fallbacks to 10)
- PORT (optional fallbacks to 3000)