Skip to content

Commit

Permalink
fire EM connection error at next tick
Browse files Browse the repository at this point in the history
this simplifies the API

A problem is that the error callback should fire before setting it up.
Hence, if we are in a fiber, and if we expected to yield after setting up
callbacks/errbacks. We would resume the fiber before yielding it,
generating a double resume error.
We work around this problem by calling :close/:on_error at next tick.
Hence, the errback's fiber will predictably be EM's reactor fiber.
  • Loading branch information
lucasdicioccio committed Dec 7, 2011
1 parent 235c69a commit eafe3d4
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 4 deletions.
4 changes: 4 additions & 0 deletions examples/fibered-http.rb
Expand Up @@ -33,6 +33,10 @@ def async_fetch(url)
puts "Setting up HTTP request #2"
data = async_fetch('http://www.yahoo.com/')
puts "Fetched page #2: #{data.response_header.status}"

puts "Setting up HTTP request #3"
data = async_fetch('http://non-existing.domain/')
puts "Fetched page #3: #{data.response_header.status}"

EventMachine.stop
}.resume
Expand Down
12 changes: 8 additions & 4 deletions lib/em-http/http_connection.rb
Expand Up @@ -64,17 +64,21 @@ def activate_connection(client)
rescue EventMachine::ConnectionError => e
#
# Currently, this can only fire on initial connection setup
# since #connect is a synchronous method. Hence, rescue the
# exception, and return a failed deferred which will immediately
# fail any client request.
# since #connect is a synchronous method. Hence, rescue the exception,
# and return a failed deferred which fail any client request at next
# tick. We fail at next tick to keep a consistent API when the newly
# created HttpClient is failed. This approach has the advantage to
# remove a state check of @deferred_status after creating a new
# HttpRequest. The drawback is that users may setup a callback which we
# know won't be used.
#
# Once there is async-DNS, then we'll iterate over the outstanding
# client requests and fail them in order.
#
# Net outcome: failed connection will invoke the same ConnectionError
# message on the connection deferred, and on the client deferred.
#
client.close(e.message)
EM.next_tick{client.close(e.message)}
end
end

Expand Down
21 changes: 21 additions & 0 deletions spec/client_fiber_spec.rb
@@ -0,0 +1,21 @@
require 'helper'
require 'fiber'

describe EventMachine::HttpRequest do
context "with fibers" do
it "should be transparent to connexion errors" do
EventMachine.run do
Fiber.new do
f = Fiber.current
http = EventMachine::HttpRequest.new('http://non-existing.domain/').get
http.callback {failed(http)}
http.errback {f.resume}
Fiber.yield
EventMachine.stop
end.resume
end
end
end
end


0 comments on commit eafe3d4

Please sign in to comment.