Véase Sinatra Recipes. Embedding Sinatra within EventMachine.
Event::Machine is a very useful tool and sometimes you need to add a web-interface on top of it. Yes, EM does support this out of the box, but it can be ugly and hard to work with. Why not use something that everyone already knows and loves like Sinatra?
Below is a (working) code-sample for running a simple HelloWorld Sinatra app within Event::Machine. I've also provided a simple example of deferring tasks within your Sinatra call.
[~/sinatra/sinatra-eventmachine]$ cat em-sinatra-test.rb require 'eventmachine' require 'sinatra/base' require 'thin' # This example shows you how to embed Sinatra into your EventMachine # application. This is very useful if you're application needs some # sort of API interface and you don't want to use EM's provided # web-server. def run(opts) # Start he reactor EM.run do # define some defaults for our app server = opts[:server] || 'thin' host = opts[:host] || '0.0.0.0' port = opts[:port] || '8181' web_app = opts[:app] # create a base-mapping that our application will set at. If I # have the following routes: dispatch = Rack::Builder.app do map '/' do run web_app end end # NOTE that we have to use an EM-compatible web-server. There # might be more, but these are some that are currently available. unless ['thin', 'hatetepe', 'goliath'].include? server raise "Need an EM webserver, but #{server} isn't" end # Start the web server. Note that you are free to run other tasks # within your EM instance. Rack::Server.start({ app: dispatch, server: server, Host: host, Port: port }) end end # Our simple hello-world app class HelloApp < Sinatra::Base # threaded - False: Will take requests on the reactor thread # True: Will queue request for background thread configure do set :threaded, false end # Request runs on the reactor thread (with threaded set to false) get '/hello' do 'Hello World' end # Request runs on the reactor thread (with threaded set to false) # and returns immediately. The deferred task does not delay the # response from the web-service. get '/delayed-hello' do EM.defer do sleep 5 end 'I\'m doing work in the background, but I am still free to take requests' end end # start the application run app: HelloApp.new
You can run this simply with the command:
ruby em-sinatra-test.rb # em-sinatra-test.rb is the filename of the above-codeYou should also be able to test that it is working correctly with the following
ab
command:
ab -c 10 -n 100 http://localhost:8181/delayed-helloApacheBench ( ab ) is a single-threaded command line computer program for measuring the performance of HTTP web servers. Originally designed to test the Apache HTTP Server, it is generic enough to test any web server (Véase http://httpd.apache.org/docs/2.2/programs/ab.html).
If this finishes in zero point something
seconds, then you have
successfully setup Sinatra to run within EM and you are taking
requests on the event-loop and deferring tasks to the background.
If it takes any longer than that, then you are most likely taking requests in the background which means when the EM queue fills up, you can't process your sinatra requests (not a good thing!). Make sure that you have threaded set to false and then try again.
Here is an execution:
[~/sinatra/sinatra-eventmachine]$ ab -c 10 -n 100 http://localhost:8181/delayed-hello This is ApacheBench, Version 2.3 <$Revision: 655654 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ Benchmarking localhost (be patient).....done Server Software: thin Server Hostname: localhost Server Port: 8181 Document Path: /delayed-hello Document Length: 70 bytes Concurrency Level: 10 Time taken for tests: 0.096 seconds Complete requests: 100 Failed requests: 0 Write errors: 0 Total transferred: 30300 bytes HTML transferred: 7000 bytes Requests per second: 1043.96 [#/sec] (mean) Time per request: 9.579 [ms] (mean) Time per request: 0.958 [ms] (mean, across all concurrent requests) Transfer rate: 308.91 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 0 0.1 0 1 Processing: 2 9 11.6 5 44 Waiting: 1 8 11.7 5 43 Total: 2 9 11.6 6 44 Percentage of the requests served within a certain time (ms) 50% 6 66% 6 75% 7 80% 7 90% 44 95% 44 98% 44 99% 44 100% 44 (longest request)