Runner #SaidNoOneEver
Find a movie or a character from it and this API will reply to you as soon as possible #SaidNoOneEver.
Run NOW through the command:
docker run --rm -it --name runner-said-no-one-ever \
-e PUMA_BIND_ADDRESS=0.0.0.0 \
-e PUMA_BIND_PORT=8080 \
-e PUMA_MIN_THREADS=4 \
-e PUMA_MAX_THREADS=20 \
-e PUMA_NUMBER_OF_WORKERS=0 \
-e PUMA_PERSISTENT_TIMEOUT=20 \
-e PUMA_FIRST_DATA_TIMEOUT=30 \
-e RACK_ENV=production \
-e APP_ENV=production \
-e PROJECT_LOG_LEVEL=DEBUG \
-e RACK_IP_ADDRESS_HEADER=REMOTE_ADDR \
-p 8000:8080 \
willianantunes/runner-said-no-one-ever
If you download the project just issue:
docker-compose up app
And with HTTPie
:
http GET :8000/api/v1/deckard-cain name==Cockatiel
http GET :8000/api/v1/movies
In order to log as JSON, change APP_ENV
and RACK_ENV
value to production
instead of development
and run the project again! If you leave as the standard and consult movies endpoint:
Puma starting in single mode...
* Version 5.0.0 (ruby 2.7.1-p83), codename: Spoony Bard
* Min threads: 4, max threads: 20
* Environment: development
* Listening on http://0.0.0.0:8080
Use Ctrl-C to stop
I, [2020-09-26T20:45:06.062309 #6] INFO -- Controllers::API::V1::MoviesController: Asking film specialist...
D, [2020-09-26T20:45:06.062394 #6] DEBUG -- Business::FilmSpecialist: Consulting movies warehouse...
I, [2020-09-26T20:45:06.913184 #6] INFO -- Controllers::API::V1::MoviesController: Sleeping the following number of seconds: 1
D, [2020-09-26T20:45:07.918926 #6] DEBUG -- Controllers::API::V1::MoviesController: Character and movie: Miracle Max / PrincessBride
172.25.0.1 - - [26/Sep/2020:20:45:07 +0000] "GET /api/v1/movies?greg=mygod&aaaaa=bb HTTP/1.1" 200 51 1.8644
Now as production
:
{"registered_at":"2020-09-26T20:48:55.182+00:00","pid":7,"thread_id":3380,"message":"Puma starting in single mode..."}
{"registered_at":"2020-09-26T20:48:55.182+00:00","pid":7,"thread_id":3380,"message":"* Version 5.0.0 (ruby 2.7.1-p83), codename: Spoony Bard"}
{"registered_at":"2020-09-26T20:48:55.182+00:00","pid":7,"thread_id":3380,"message":"* Min threads: 4, max threads: 20"}
{"registered_at":"2020-09-26T20:48:55.182+00:00","pid":7,"thread_id":3380,"message":"* Environment: production"}
{"registered_at":"2020-09-26T20:48:55.464+00:00","pid":7,"thread_id":3380,"message":"* Listening on http://0.0.0.0:8080"}
{"registered_at":"2020-09-26T20:48:55.464+00:00","pid":7,"thread_id":3380,"message":"Use Ctrl-C to stop"}
{"level":"INFO","prog_name":"Controllers::API::V1::MoviesController","pid":7,"thread_id":3720,"registered_at":"2020-09-26T20:48:57.928+00:00","message":"Asking film specialist..."}
{"level":"DEBUG","prog_name":"Business::FilmSpecialist","pid":7,"thread_id":3720,"registered_at":"2020-09-26T20:48:57.928+00:00","message":"Consulting movies warehouse..."}
{"level":"INFO","prog_name":"Controllers::API::V1::MoviesController","pid":7,"thread_id":3720,"registered_at":"2020-09-26T20:48:58.805+00:00","message":"Sleeping the following number of seconds: 1"}
{"level":"DEBUG","prog_name":"Controllers::API::V1::MoviesController","pid":7,"thread_id":3720,"registered_at":"2020-09-26T20:48:59.807+00:00","message":"Character and movie: Carc / Hobbit"}
{"ip_address":"172.25.0.1","registered_at":"2020-09-26T20:48:59.814+00:00","pid":7,"thread_id":3720,"request_id":null,"method":"GET","path":"/api/v1/movies","query":"?greg=mygod&aaaaa=bb","version":"HTTP/1.1","status":"200","response_length":"37","referer":null,"user_agent":"HTTPie/2.2.0","request_time":1.8913743}
Execute the following command:
docker-compose up tests
And you'll see something like:
Finished in 0.11874 seconds (files took 0.75679 seconds to load)
11 examples, 0 failures
Coverage report generated for RSpec to /app/coverage. 269 / 276 LOC (97.46%) covered.
The idea here is to delay 1 second or more (given your custom configuration) to answer a request, thus you can use this behavior for interesting tests, like dispatching 10 requests from your back-end to this service and do it efficiently with some approaches like through Threads or Coroutines. See this flow which I used for a RoR project emulating a Hangman game through an API:
Why Sinatra? See more here.
In order to create a project following Ruby conventions to organize a project, I executed the following command:
bundle gem runner_said_no_one_ever --no-exe --no-coc --mit --test=rspec
After that, I deleted the following files:
runner_said_no_one_ever.gemspec
.travis.yml
bin
See more details here.
Articles:
- How to create a Ruby API with Sinatra
- Where does bundler store gems?
- Create a custom RuboCop action
- Make Rubocop Part of Your Tests
- Structuring Sinatra Applications
- Bundler.setup vs. Bundler.require
- Why is bad specific setup for development, test, production
- Rack Explained For Ruby Developers
- Logging with Ruby Sinatra and Passenger
- The recommendation of structured logging and the reason I have made Ougai for Ruby
Discussions:
Some projects: