Benjamin
Benjamin

Reputation: 10403

Why my eventmachine client code doesn't work asynchronously?

def index
  p "INDEX, #{Fiber.current.object_id}" # <- #1
  EventMachine.run {
    http = EventMachine::HttpRequest.new('http://google.com/').get :query => {'keyname' => 'value'}

    http.errback { p "Uh oh, #{Fiber.current.object_id}"; EM.stop } # <- #2
    http.callback {
      p "#{http.response_header.status}, #{Fiber.current.object_id}" # <- #3
      p "#{http.response_header}"
      p "#{http.response}"

      EventMachine.stop
    }
  }

  render text: 'test1'
end

In this code, I expected getting different Fiber id at #1, #2, #3 line. But all fiber objects' id was same. I tried Thread.current.object_id, but it was same result too.
What am I misunderstaning? Is that code even executes asynchronously?

P.S I'm using ruby 2.0 and the code is running with rails4

Upvotes: 0

Views: 166

Answers (2)

Sim
Sim

Reputation: 13548

As a search of the repository shows, em-http does not use fibers by default. The link, however, lists an example of how you can use fibers if you are so inclined.

Upvotes: 0

7stud
7stud

Reputation: 48659

http://ruby-doc.org/core-2.0/Fiber.html

Fibers are primitives for implementing light weight cooperative concurrency in Ruby. Basically they are a means of creating code blocks that can be paused and resumed, much like threads. The main difference is that they are never preempted and that the scheduling must be done by the programmer and not the VM.

Where in your code are you scheduling fibers, e.g. calling Fiber.yield or my_fiber.resume?

current() → fiber
Returns the current fiber. You need to require 'fiber' before using this method. If you are not running in the context of a fiber this method will return the root fiber.

Where in your code have you created additional fibers, e.g. Fiber.new do ...?

Is that code even executes asynchronously?

require 'em-http-request'
require 'fiber'

puts Fiber.current.object_id

def index
  p "INDEX, #{Fiber.current.object_id}" # <- #1
  EventMachine.run {
    http = EventMachine::HttpRequest.new('http://google.com/').get :query => {'keyname' => 'value'}

    http.errback { p "#{Uh oh}, #{Fiber.current.object_id}"; EM.stop } # <- #2
    http.callback {
      p "#{http.response_header.status}, #{Fiber.current.object_id}" # <- #3
      p "#{http.response_header}"
      p "#{http.response}"

      EventMachine.stop
    }
  }

  #render text: 'test1'
end

index()

--output:--
2157346420
"INDEX, 2157346420"
"301, 2157346420"
"{\"LOCATION\"=>\"http://www.google.com/?keyname=value\", \"CONTENT_TYPE\"=>\"text/html; charset=UTF-8\", \"DATE\"=>\"Mon, 22 Jul 2013 08:44:35 GMT\", \"EXPIRES\"=>\"Wed, 21 Aug 2013 08:44:35 GMT\", \"CACHE_CONTROL\"=>\"public, max-age=2592000\", \"SERVER\"=>\"gws\", \"CONTENT_LENGTH\"=>\"233\", \"X_XSS_PROTECTION\"=>\"1; mode=block\", \"X_FRAME_OPTIONS\"=>\"SAMEORIGIN\", \"CONNECTION\"=>\"close\"}"
"<HTML><HEAD><meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\">\n<TITLE>301 Moved</TITLE></HEAD><BODY>\n<H1>301 Moved</H1>\nThe document has moved\n<A HREF=\"http://www.google.com/?keyname=value\">here</A>.\r\n</BODY></HTML>\r\n"

Nope.

And this is an error:

http.errback { p "#{Uh oh}"  ...

Upvotes: 1

Related Questions