Asynchronously iterating over the response of a request using Thin and Sinatra
So in the end, I found out that the example did indeed work and I could eventually get Sinatra to stream each-able results concurrently, primarily using the EM.defer
idea in Pusher and Async page. curl and Apache benchmarking confirmed that this was working.
The reason why it didn't work in the browser is because browsers limit the number of connections to the same URL. I was aware of there being a limit to concurrent connections to a single domain (also a low number), but not that (seemingly) all connections to a single URI are serialized:
http://maillist.caucho.com/pipermail/resin-interest/2009-August/003998.html
I don't know if this is configurable, I only see domain-wide configuration in Firefox, but that was the issue.
stream multiple body using async sinatra
require 'rubygems'
require 'sinatra/async'
require 'thin'
require 'json'
class Test < Sinatra::Base
register Sinatra::Async
class JSONStream
include EventMachine::Deferrable
def stream(object)
@block.call object.to_json + "\n"
end
def each(&block)
@block = block
end
end
aget '/process' do
puts 'ok'
out = JSONStream.new
body out
EM.next_tick do
c = 0
timer = EM.add_periodic_timer(0.3) do
c += 1
out.stream :data => ["this is part #{c}"]
if c == 100
timer.cancel
out.succeed
end
end
end
end
run!
end
See also: http://confreaks.net/videos/564-scotlandruby2011-real-time-rack Running Sinatra server and subprocess asynchronously
Here the main thread is the Sinatra app and the additional thread loads the data, which is more usual to me.
class Aircraft
@aircrafts = {}
def self.all
@aircrafts
end
end
Thread.new do
no = 1
while true
Aircraft.all[no] = 'Boing'
no += 1
sleep(3)
end
end
get '/aircrafts' do
Aircraft.all.to_json
end
sinatra HEAD method
That is a perfectly valid Sinatra head
route. The problem is with your curl statement.
curl -X HEAD 'http://localhost:4567/'
-X HEAD is not what you want; it will not print headers and will expect some specification of expected bytes transmission stated in Content-Length.Instead you want the following.
curl -I http://localhost:4567/
async_sinatra requests crash silently with em-http. How do I fix this?
If your web server (Eg. thin) is based on EventMachine, then the EventMachine.stop line will actually stop the webserver as well as the EventMachine instance created by EventMachine.run.
I can't find a way to stop nested EventMachines like this. My advice - use Weary or another non-blocking HTTP request library.
Ruby Http gem (http client) inside Sinatra POST
Changes to
post "/weather" do
puts HTTP.get('https://www.metaweather.com/api/location/search/?query=milwaukee') # prints correct result
HTTP.get('https://www.metaweather.com/api/location/search/?query=milwaukee').to_s
end
The HTTP.get
method returns a HTTP::Response
object rather than a String
object.From the source code only specific types of object can be returned.
res = [res] if Integer === res or String === res
if Array === res and Integer === res.first
res = res.dup
status(res.shift)
body(res.pop)
headers(*res)
elsif res.respond_to? :each
body res
end
nil # avoid double setting the same response tuple twice
Related Topics
How to Avoid Circular Creation of Associated Models in Factory_Girl
Clean Install Osx 10.9.1 Returns "Undefined Method 'Path2Class'" When Trying to Install Gems
How to Wait for System Command to End
Why Am I Getting "Unable to Autoload Constant" with Rails and Grape
Functional Testing of a Restful Post in Ruby on Rails
How to Reference a Local Gem from a Ruby Script
How to Validate This Hash Parameter
Activemodel::Validations on Anonymous Class
How to Handle Omniauth Callbacks in Multiple Environments
How to Properly Manage The Rails Tmp Directory
Change Time Zone in Pure Ruby (Not Rails)
Indent Multiline String in Erb
Define_Method with Predefined Keyword Arguments
Ruby: How to Escape Url with Square Brackets [ and ]
How to Make Http Delete Request in My Ruby Code Using Net::Http