Closed coffeebite closed 9 years ago
Hmm. Current implementation of Synchrony.defer
will pause and wait for the block to finish, but it doesn't wrap the block itself within the fiber.. this may be an oversight. Current code:
https://github.com/igrigorik/em-synchrony/blob/master/lib/em-synchrony.rb#L119
This should fix your immediate problem:
EM.synchrony do
EM::Synchrony.defer do
Fiber.new do
driver = Selenium::WebDriver.for :chrome
driver.manage.window.resize_to 1024, 768
driver.navigate.to 'http://google.com'
EM::Synchrony.sleep 2
driver.save_screenshot 'screenshot.png'
driver.quit
end.run
end
end
Thanks @igrigorik. I assume you mean
Fiber.new do
...
end.resume
as opposed to Fiber.new ... run
I tried this previously, and I get a different error:
em-resolv-replace.rb:56:in `resume': fiber called across threads (FiberError)
Here is the resolver code again:
fiber = Fiber.current
df = EM::DnsResolver.send(resolv_method, value)
df.callback do |a|
#--FOLLOWING LINE RAISES ERROR--
fiber.resume(a)
end
df.errback do |*a|
fiber.resume(ResolvError.new(a.inspect))
end
result = Fiber.yield
Yes, sorry: end.resume
Hi Ilya No worries. It is still not working though. There is a different error this time, which I mention in the post above. Any ideas what may be happening?
Hmm, this is where it can get really tricky.. You'd have to look in the selenium driver to see what its doing. If there are multiple async calls, then the fiber logic needs to be applied in there as well -- plumbing all the way down (ugh).
Without going to deep down this route, perhaps another strategy worth considering is a sub-process: https://github.com/postrank-labs/goliath/blob/master/examples/rasterize/rasterize.rb#L22
You can spawn another ruby (or any other type) of process, and listen to its status via EM.system. For memory heavy processes, this may actually be a better option than EM.defer (which has its own host of problems).
Thanks Ilya. I guess I'll take this route then. Thanks very much.
I am running a synchrony app where I have to use a library with potentially blocking IO (Selenium + Chrome)
This works:
But this does not save me from blocking IO. Hence, I am wrapping the selenium block in a defer call as such:
But this is throwing an error
The em-resolv-replace code that is throwing this error:
It seems like this is happening because the code inside defer runs in a separate thread without fibers? If so, what is the correct way of deferring blocking calls in EM::Synchrony? If not, how can I fix this?