0

I am trying to create a very simple web service with Goliath and Grape. All that my service would do is that given an image path and a target dimension it would return the new geometry of the image. The images are stored in the same server as the host of the web service.

So I have this code within Grape:

# some Grape code omitted
get "/" do
  EM.defer {
    image = Magick::Image.read('path to image').first
    image.change_geometry('3000x3900') do |cols, row, img|
      return {width: cols, height: row}
    end
  }
end

When I visit the endpoint in the browser all I get is this string

"#<ConditionVariable:0x007ffd9de1f6e8>"

Without EM.defer it returns the following json but with very low requests/secs (about 4 reqs/sec):

{width: 'new width', height: 'new heigth'}

How could I make the Rmagick operations non blocking and make it return the results?

Lester Celestial
  • 1,454
  • 1
  • 16
  • 26
  • See http://eventmachine.rubyforge.org/EventMachine.html#defer-class_method, `op` parameter is the `&block` from your code, it's executed in a separate thread, the `callback` parameter on the other hand is the block of code the reactor triggers once `EM.defer` returns the result. See if you can return response from EM.defer's callback block – bbozo Dec 06 '13 at 14:14

1 Answers1

0

It looks like you mixed things up a bit.

Call to RMagick is always blocking, since it requires the image to be processed. The good news is the call to grape itself is non-blocking. It means, that while your single clients must wait for claimed 1/3 secs to complete, another clients are still able to queue requests.

I guess your testing environment simply calls the respective service one-by-one, waiting for requests to complete. Instead of that you are to call the service from separate threads, getting results as they are ready.

Hope it helps.

Aleksei Matiushkin
  • 119,336
  • 10
  • 100
  • 160
  • I am aware that Rmagick would block my application, hence I tried using EM.defer with it. Perhaps there is something wrong with my implementation of EM.defer? – Lester Celestial Dec 06 '13 at 11:24
  • I suggest you have `Sinatra` behind your `Grape`, right? You don’t need to re-implement `Sinatra` functionality, please refer to `threaded` option [here](http://www.sinatrarb.com/intro.html). Anyway, implementing `EM#defer` inside of the `get` block is wrong, since client waits for the response here and you can’t prevent blocking from within already blocked method. – Aleksei Matiushkin Dec 06 '13 at 11:32
  • You can, however, not block the reactor thread for all other requests, this is why OP uses EM.defer – bbozo Dec 06 '13 at 14:12