EventMachine and looping
eventmachine, ruby
Solution
The `run` block you give runs only once. The event loop is not exposed directly to you but is something that's intended to be invisible. Don't confuse the `run` block with a `while` loop. It's run once and once only, but it is run while the event loop is executing.
If you want to repeat an operation you need to create some kind of a stack and work through that, with each callback checking the stack if there's more work to do and then issuing another call. EventMachine applications are built using this callback-chaining method.
You will need to implement something like:
def do_stuff(queue, request = nil)
request ||= queue.pop
return unless (request)
conn = EM::Protocols::HttpClient2.connect request.host, 80
req = conn.get(request.query)
req.callback { |response|
p(response.status)
p(response.headers)
p(response.content)
EventMachine.next_tick do
# This schedules an operation to be performed the next time through
# the event-loop. Usually this is almost immediate.
do_stuff(queue)
end
}
end
Inside your event loop you kick of this chain:
EventMachine.run do
queue = [ ... ] # List of things to do
do_stuff(queue)
end
You can probably find a more elegant way to implement this once you get a better sense of how EventMachine works.
Problem
Here is my code: ``` EventMachine.run { conn = EM::Protocols::HttpClient2.connect request.host, 80 req = conn.get(request.query) req.callback { |response| p(response.status) p(response.headers) p(response.content) } } ``` The callbacks fire, that is, I get the string outputs of the status, etc. But what I want it to do is fire the callbacks, then repeat. There is more logic I plan to implement, such as tweaking the URL each time, but for now, I just want it to: - Retrieve the URL - Fire the callbacks - Repeat... My understanding about this pattern was that everything in that loop fires, then returns, then goes on forever until I do an `EM.stop`. Right now, it retrieves the URL data, and just seems to hang. Do I need to do a return of some sort to continue here? Why is it hanging, and not looping over and over? If I surround the entire above code block with a loop do ... end it works as expected.. is that the correct way to implement this? I suppose I am confused as I thought everything within `EM.run` repeats when it completes.