This program
require 'em-synchrony' ## v1.0.0
require 'em-hiredis' ## v0.1.0
module EventMachine
module Hiredis
class Client
def self.connect(host = 'localhost', port = 6379)
conn = new(host, port)
EM::Synchrony.sync conn.connect
conn
end
alias :old_method_missing :method_missing
def method_missing(sym, *args)
EM::Synchrony.sync old_method_missing(sym, *args)
end
end
end
end
EventMachine.synchrony do
redis = EM::Hiredis.connect
redis.set('foo', 'bar')
puts redis.get('foo')
EM.stop
end
dies like this
$ ruby /tmp/reddy.rb
/home/blt/.rvm/gems/ruby-1.9.3-p0/gems/em-synchrony-1.0.0/lib/em-synchrony.rb:58:in `yield': can't yield from root fiber (FiberError)
from /home/blt/.rvm/gems/ruby-1.9.3-p0/gems/em-synchrony-1.0.0/lib/em-synchrony.rb:58:in `sync'
from /tmp/reddy.rb:16:in `method_missing'
from /home/blt/.rvm/gems/ruby-1.9.3-p0/gems/em-hiredis-0.1.0/lib/em-hiredis/client.rb:119:in `select'
from /home/blt/.rvm/gems/ruby-1.9.3-p0/gems/em-hiredis-0.1.0/lib/em-hiredis/client.rb:38:in `block in connect'
from /home/blt/.rvm/gems/ruby-1.9.3-p0/gems/em-hiredis-0.1.0/lib/em-hiredis/event_emitter.rb:8:in `call'
from /home/blt/.rvm/gems/ruby-1.9.3-p0/gems/em-hiredis-0.1.0/lib/em-hiredis/event_emitter.rb:8:in `block in emit'
from /home/blt/.rvm/gems/ruby-1.9.3-p0/gems/em-hiredis-0.1.0/lib/em-hiredis/event_emitter.rb:8:in `each'
from /home/blt/.rvm/gems/ruby-1.9.3-p0/gems/em-hiredis-0.1.0/lib/em-hiredis/event_emitter.rb:8:in `emit'
from /home/blt/.rvm/gems/ruby-1.9.3-p0/gems/em-hiredis-0.1.0/lib/em-hiredis/connection.rb:15:in `connection_completed'
from /home/blt/.rvm/gems/ruby-1.9.3-p0/gems/eventmachine-1.0.0.beta.4/lib/eventmachine.rb:179:in `run_machine'
from /home/blt/.rvm/gems/ruby-1.9.3-p0/gems/eventmachine-1.0.0.beta.4/lib/eventmachine.rb:179:in `run'
from /home/blt/.rvm/gems/ruby-1.9.3-p0/gems/em-synchrony-1.0.0/lib/em-synchrony.rb:27:in `synchrony'
from /tmp/reddy.rb:22:in `<main>'
I find this deeply confusing. Why doesn't it work and am I at fault? If so, what can I do differently? Unless I've glossed over something, this is kosher, per the em-synchrony README.
I think your code can work if you find the correct version of em-hiredis it is trying to monkey patch, that is one problem with loose dependencies.
Here is a fully working code but based on the master branch of em-synchrony:
Gemfile:
source :rubygems
gem 'em-synchrony', :git => "git://github.com/igrigorik/em-synchrony.git"
gem 'em-hiredis', '~> 0.1.0'
test.rb:
require 'rubygems'
require 'bundler/setup'
require 'em-synchrony'
require 'em-synchrony/em-hiredis'
EventMachine.synchrony do
redis = EM::Hiredis.connect
redis.set('foo', 'bar')
puts redis.get('foo')
EM.stop
end
and then run it with:
$ bundle
$ ruby test.rb
Monkey patching is an inherently flawed way of patching gems unless you ensure the exact version of the gem you patched is used which is something em-synchrony should enforce or at least detect.
来源:https://stackoverflow.com/questions/8750788/simple-use-of-emsynchronysync-causes-root-fiber-fibererror-my-fault