Notes: Tested on OS X with Ruby, managed by rbenv. Homebrew installed native dependencies, e.g. readline, postgres (tested with 9.5.4)
brew install readline
Install ruby. Tested with 2.4.1. rbenv used to manage Ruby versions. Install bundler gem, which will manage all other gems installed.
bundle
Once the application gems are installed, running rake will run the build, and should be an additional verification point that everything is set up.
There are a number of ways to do this, one way is from a psql prompt, run:
create database my_retail_dev;
create database my_retail_test;To create the database schema:
rake db:migrate
To load data into the database using the Rails seeds functionality:
rake db:seed
Confirm data is loaded (example, may change):
# \c my_retail_dev
You are now connected to database "my_retail_dev" as user "andy".
andy@[local]:5432 my_retail_dev# select * from products;
id | external_id | price_details | created_at | updated_at
----+-------------+---------------+----------------------------+----------------------------
1 | 15117729 | | 2018-02-15 18:19:19.761739 | 2018-02-15 18:19:19.761739
2 | 16483589 | | 2018-02-15 18:19:19.765197 | 2018-02-15 18:19:19.765197
3 | 16696652 | | 2018-02-15 18:19:19.767898 | 2018-02-15 18:19:19.767898
4 | 16752456 | | 2018-02-15 18:19:19.770103 | 2018-02-15 18:19:19.770103
5 | 15643793 | | 2018-02-15 18:19:19.772462 | 2018-02-15 18:19:19.772462
(5 rows)
e.g.
select price_details->'current_price'->'value' as value, price_details->'current_price'->'currency_code' as currency from products where external_id = 13860428;
value | currency
-------+----------
13.49 | "USD"The Product resource has an ID and price details, stored as JSON data, using the jsonb column type.
Using Postman or curl, make the following HTTP requests.
GET http://localhost:5000/products/{id}
e.g. 15117729
GET http://localhost:5000/products/13860428
Response (e.g.):
{
"id": 13860428,
"name": "The Big Lebowski (Blu-ray)",
"current_price": {
"value": 13.49,
"currency_code": "USD"
}
}
curl -X GET http://localhost:5000/products/13860428
Make a put request to the following URL with the following JSON body as the payload.
Set the body to application/json.
PUT http://localhost:5000/products/13860428
{
"product": {
"id": 13860428,
value": 17.50
}
}
curl -X PUT \
http://localhost:5000/products/13860428 \
-H 'content-type: application/json' \
-d '{
"product": {
"id": 13860428,
"value": 17.50
}
}
'
curl -X PUT \
https://limitless-oasis-33699.herokuapp.com/products/13860428 \
-H 'content-type: application/json' \
-d '{
"product": {
"id": 13860428,
"value": 17.29
}
}
'
curl -X GET https://limitless-oasis-33699.herokuapp.com/products/13860428
422 Response example
curl -X GET https://limitless-oasis-33699.herokuapp.com/products/123
To boot up the application on port 5000:
rails s -p 5000
Or:
foreman start
Benchmarking with wrk tool https://github.com/wg/wrk
$ wrk -t1 -c10 -d10s http://127.0.0.1:5000/products/13860428
Running 10s test @ http://127.0.0.1:5000/products/13860428
1 threads and 10 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 135.66ms 85.83ms 753.22ms 95.61%
Req/Sec 40.25 11.22 50.00 78.26%
382 requests in 10.08s, 176.82KB read
Requests/sec: 37.89
Transfer/sec: 17.54KB
HTTP interaction with Redsky service
As requests for product IDs come in, we could cache the response with a key of the product ID, and the value as the JSON string, e.g. in memcached or another key-value store, and then for subsequent requests for the same ID, server the JSON string from the cache store and not make a live HTTP call.
We could specify a period of time that the cached response is fresh, e.g. 1 minute (the TTL).
Benchmark various JSON serialization options.
Using a parameter, a client could request a reduced set of attributes that represent the object. For example, in a mobile app on a summary screen, a trade-off for a faster summary screen could be fetching fewer attributes for each row, which would take less time to serialize, and produce a smaller JSON payload.