Skip to content
This repository has been archived by the owner on Dec 7, 2018. It is now read-only.

Instantiating Redis from inside a Celluloid::IO actor causes missing constructor error #10

Open
orospakr opened this issue Jul 19, 2013 · 5 comments

Comments

@orospakr
Copy link

I think the name "Redis" may be overridden in the local scope.

Example code:

#!/usr/bin/env ruby

require "redis"
require "celluloid"
require "celluloid/io"
require 'celluloid/redis'

class MyActor
  # comment this out to prevent the error.
  include Celluloid::IO

  def initialize
    @redis = Redis.new(:driver => :celluloid) 

    puts "Success."
  end
end

ma = MyActor.new
sleep

Error produced:

$ bundle exec ./bin/redis_spike.rb
E, [2013-07-19T10:49:33.717153 #26935] ERROR -- : MyActor crashed!
NoMethodError: undefined method `new' for Celluloid::Redis:Module
        ./bin/redis_spike.rb:13:in `initialize'
        /home/orospakr/.gem/ruby/2.0.0/gems/celluloid-0.14.1/lib/celluloid/calls.rb:25:in `public_send'
        /home/orospakr/.gem/ruby/2.0.0/gems/celluloid-0.14.1/lib/celluloid/calls.rb:25:in `dispatch'
        /home/orospakr/.gem/ruby/2.0.0/gems/celluloid-0.14.1/lib/celluloid/calls.rb:67:in `dispatch'
        /home/orospakr/.gem/ruby/2.0.0/gems/celluloid-0.14.1/lib/celluloid/actor.rb:326:in `block in handle_message'
        /home/orospakr/.gem/ruby/2.0.0/gems/celluloid-0.14.1/lib/celluloid/tasks.rb:42:in `block in initialize'
        /home/orospakr/.gem/ruby/2.0.0/gems/celluloid-0.14.1/lib/celluloid/tasks/task_fiber.rb:11:in `block in create'
D, [2013-07-19T10:49:33.718139 #26935] DEBUG -- : Terminating 1 actors...
D, [2013-07-19T10:49:33.718526 #26935] DEBUG -- : Shutdown completed cleanly
./bin/redis_spike.rb:13:in `initialize': undefined method `new' for Celluloid::Redis:Module (NoMethodError)
        from /home/orospakr/.gem/ruby/2.0.0/gems/celluloid-0.14.1/lib/celluloid/calls.rb:25:in `public_send'
        from /home/orospakr/.gem/ruby/2.0.0/gems/celluloid-0.14.1/lib/celluloid/calls.rb:25:in `dispatch'
        from /home/orospakr/.gem/ruby/2.0.0/gems/celluloid-0.14.1/lib/celluloid/calls.rb:67:in `dispatch'
        from /home/orospakr/.gem/ruby/2.0.0/gems/celluloid-0.14.1/lib/celluloid/actor.rb:326:in `block in handle_message'
        from /home/orospakr/.gem/ruby/2.0.0/gems/celluloid-0.14.1/lib/celluloid/tasks.rb:42:in `block in initialize'
        from /home/orospakr/.gem/ruby/2.0.0/gems/celluloid-0.14.1/lib/celluloid/tasks/task_fiber.rb:11:in `block in create'
        from (celluloid):0:in `remote procedure call'
        from /home/orospakr/.gem/ruby/2.0.0/gems/celluloid-0.14.1/lib/celluloid/calls.rb:95:in `value'
        from /home/orospakr/.gem/ruby/2.0.0/gems/celluloid-0.14.1/lib/celluloid/proxies/sync_proxy.rb:28:in `method_missing'
        from /home/orospakr/.gem/ruby/2.0.0/gems/celluloid-0.14.1/lib/celluloid/legacy.rb:14:in `method_missing'
        from /home/orospakr/.gem/ruby/2.0.0/gems/celluloid-0.14.1/lib/celluloid/proxies/actor_proxy.rb:25:in `_send_'
        from /home/orospakr/.gem/ruby/2.0.0/gems/celluloid-0.14.1/lib/celluloid.rb:129:in `new'
        from ./bin/redis_spike.rb:19:in `<main>'

Commenting out include Celluloid::IO prevents the error.

Is it unreasonable for me to want to use Celluloid::Redis from inside a Celluloid::IO actor? I would have thought that a Celluloid::IO Actor is just the right place to use Celluloid::Redis from, since it needs the IO reactor.

@orospakr
Copy link
Author

Thanks to benlangfield@irc, apparently the trick is to ground the identifier dereference in the global namespace:

@redis = ::Redis.new

Perhaps the README should be updated to reflect such?

@benlangfeld
Copy link
Member

Or Celluloid::Redis should be renamed CelluloidRedis to avoid the collision, especially since it's only used to house Celluloid::Redis::VERSION.

@orospakr
Copy link
Author

Agreed.

@tarcieri
Copy link
Member

Yeah, the namespace collision is annoying :(

@nagius
Copy link

nagius commented Dec 4, 2015

I ran into this bug too. It took me a while to figure it.
We should fix either the namespace collision or the documentation with a working example like :

require 'celluloid/current'
require 'celluloid/io'
require 'celluloid/redis'

class MyActor
    include Celluloid::IO

    def initialize
        @redis = ::Redis.new(:driver => :celluloid)
        async.run
    end

    def run
        every(1) { puts "Tick" }

        @redis.subscribe(:events) { |on|
            on.message { |channel, message|
                puts message
            }
        }
    end
end

MyActor.new
sleep

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants