Celluloid::Worker is dead, long live... Celluloid

247 views
Skip to first unread message

Tony Arcieri

unread,
May 12, 2012, 9:06:21 PM5/12/12
to cellulo...@googlegroups.com
I've decided to get rid of Celluloid::Worker, which was never released in an actual gem of Celluloid, but I know some people are using from master. Don't worry, the transition won't be hard. Where you would've done:

    include Celluloid::Worker

just do:

    include Celluloid

That's right, I'm adding the Celluloid.pool class method to every class that includes Celluloid. It's that easy!

I haven't done this yet, but I'll be committing it Really Soon Now, so if you were previously using Celluloid::Worker, heads up.

--
Tony Arcieri

Jonathan Rochkind

unread,
May 23, 2012, 9:56:27 AM5/23/12
to Celluloid
Awesome. Any rough estimate of when a celluloid release with `pool`
will happen? (The dangers of using stuff in one's own production from
head but not a release are clearly illustrated).

Tony Arcieri

unread,
May 23, 2012, 10:40:46 AM5/23/12
to cellulo...@googlegroups.com
I've been wanting to get another release of Celluloid pushed out, but have been really busy lately. Hopefully this weekend!
--
Tony Arcieri

Sean McKibben

unread,
May 23, 2012, 10:59:31 AM5/23/12
to cellulo...@googlegroups.com
I hear ya Jonathan! I also have to use sidekiq too... Thank goodness for BUNDLE_GEMFILE...

Can't wait until this gets to gem land.

Thanks Tony!

Sean

Tony Arcieri

unread,
May 27, 2012, 3:21:17 PM5/27/12
to cellulo...@googlegroups.com
Heads up, I made this change on master:

--
Tony Arcieri

Tony Arcieri

unread,
May 27, 2012, 3:24:09 PM5/27/12
to cellulo...@googlegroups.com
Also note I'm removing the old Celluloid::Pool API in the next release. Celluloid.pool should hopefully be the final form:

--
Tony Arcieri

early adopter

unread,
May 28, 2012, 5:05:21 PM5/28/12
to Celluloid
I was relying on Celluloid::Pool to manage a max allowed number of
actors of particular class, where each actor would process a unique
message ie:

Celluloid::Pool.supervise_as :name, MyActorClass, :max_size => 5
%w[param1 param2 param3].each {|p|
Celluloid::Actor[:name].get.do_something!(p)}

will spawn 3 actors to complete the iteration.

According to my understanding, the new Celluloid::PoolManager will
execute a method against all workers at once, ie:
Celluloid::PoolManager.supervise_as :name, MyActorClass, :size => 5
%w[param1 param2 param3].each {|p|
Celluloid::Actor[:name].do_something!(p)}

will spawn 5 actors for each array element.

It's a great feature to have indeed and it makes a lot of sense.

I ask advise about my particular case - How to reimplement the same
basic idea using new PoolManager.

Usually, i know that if something doesn't do what i expect from it,
it's me doing something wrong or having a wrong concept to begin with,
but seeing how this project is young and in constant flux, i am
wondering if perhaps my input could generate some useful features for
the future.

On May 27, 9:24 pm, Tony Arcieri <tony.arci...@gmail.com> wrote:
> Also note I'm removing the old Celluloid::Pool API in the next release.
> Celluloid.pool should hopefully be the final form:
>
> https://github.com/celluloid/celluloid/commit/9a8e779196267483b860120...
>
> On Sun, May 27, 2012 at 12:21 PM, Tony Arcieri <tony.arci...@gmail.com>wrote:
>
>
>
>
>
>
>
>
>
> > Heads up, I made this change on master:
>
> >https://github.com/celluloid/celluloid/commit/d63fb4141915d6a0e68fbe5...
>
> > On Wed, May 23, 2012 at 7:59 AM, Sean McKibben <grap...@graphex.com>wrote:
>
> >> I hear ya Jonathan! I also have to use sidekiq too... Thank goodness for
> >> BUNDLE_GEMFILE...
>
> >> Can't wait until this gets to gem land.
>
> >> Thanks Tony!
>
> >> Sean
>
> >> On May 23, 2012, at 8:40 AM, Tony Arcieri wrote:
>
> >> I've been wanting to get another release of Celluloid pushed out, but
> >> have been really busy lately. Hopefully this weekend!
>

Tony Arcieri

unread,
May 29, 2012, 1:55:23 AM5/29/12
to cellulo...@googlegroups.com
No, Celluloid.pool provides similar behavior to Celluloid::Pool, the difference being that Celluloid::Pool used a block (which didn't work well with futures) and Celluloid.pool uses delegation. Messages are still sent to one and only one actor in the pool.

Celluloid.pool creates a sort of combination delegator/supervisor, although unfortunately there's presently no way to place it into a supervision hierarchy. I'll fix that before I release the next version of Celluloid.
--
Tony Arcieri

early adopter

unread,
May 29, 2012, 1:14:33 PM5/29/12
to Celluloid
Here's what i ment previously i think:

class MyActor
def fail_me
raise StandardError
end
end

p = MyActor.pool
p.fail_me

Above kills every actor in the pool, whereas:

p = Celluloid::Pool.new(MyActor)
p.get.fail_me

killed only the actor in question.

Any way to get the 'old' behaviour back or recreate it with the new
Celluloid.pool ?

On May 29, 7:55 am, Tony Arcieri <tony.arci...@gmail.com> wrote:
> No, Celluloid.pool provides similar behavior to Celluloid::Pool, the
> difference being that Celluloid::Pool used a block (which didn't work well
> with futures) and Celluloid.pool uses delegation. Messages are still sent
> to one and only one actor in the pool.
>
> Celluloid.pool creates a sort of combination delegator/supervisor, although
> unfortunately there's presently no way to place it into a supervision
> hierarchy. I'll fix that before I release the next version of Celluloid.
>

Tony Arcieri

unread,
May 30, 2012, 1:02:52 AM5/30/12
to cellulo...@googlegroups.com
Can you try master? This should be fixed now
--
Tony Arcieri

early adopter

unread,
May 30, 2012, 2:37:10 PM5/30/12
to Celluloid
Confirmed, a single actor no longer crashes the whole pool.

However, dead actors stay in the pool in @idle now.

Thanks for all your work! Much appreciated!
On May 30, 7:02 am, Tony Arcieri <tony.arci...@gmail.com> wrote:
> Can you try master? This should be fixed now
>

Tony Arcieri

unread,
May 31, 2012, 1:45:01 AM5/31/12
to cellulo...@googlegroups.com
This should now be resolved as well. I also added support for spawning pools within a group.
--
Tony Arcieri

early adopter

unread,
Jun 5, 2012, 8:20:05 PM6/5/12
to cellulo...@googlegroups.com
Tony, another maybe related question:

class MyPool < Celluloid::PoolManager
end

class MyWorker
  include Celluloid

  def fail_me
    raise StandardError
  end
end

MyPool.supervise_as :myclass, MyWorker
Celluloid::PoolManager.supervise_as :clclass, MyWorker

Celluloid::Actor[:myclass].fail_me # => 2 crashed actors + crashed pool class
Celluloid::Actor[:clclass].fail_me # => expected behaviour

[:myclass] crashes the poolmanager class and all the actors inside.
[:clclass] works as expected.

Is it supposed to do that? Am i supposed to inherit from PoolManager? if not, then how can i rename the instance of PoolManager class?

also:
Celluloid::Actor[:clclass].class.name # => Celluloid::PoolManager, but:
MyWorker.supervise_as :exmpl
Celluloid::Actor[:exmpl].class.name # => MyWorker

imho, a call like [:actor].class to an instance of PoolManager should produce the same result as a call to an instance of other actors, just my 2 cents, that's why i started to bother with renaming PoolManager in a first place.

aside from understanding your code, i have a huge noob factor to overcome, so please forgive me, if my question is moronic somehow,

Thanks!

Tony Arcieri

unread,
Jun 5, 2012, 9:45:55 PM6/5/12
to cellulo...@googlegroups.com
On Tue, Jun 5, 2012 at 5:20 PM, early adopter <ita...@sms4email.info> wrote:
aside from understanding your code, i have a huge noob factor to overcome, so please forgive me, if my question is moronic somehow,

I seem to be in a new world of trying to work out concurrent object oriented programming patterns, so forgive me as well ;)
 
class MyPool < Celluloid::PoolManager
end

class MyWorker
  include Celluloid

  def fail_me
    raise StandardError
  end
end

MyPool.supervise_as :myclass, MyWorker
Celluloid::PoolManager.supervise_as :clclass, MyWorker

Celluloid::Actor[:myclass].fail_me # => 2 crashed actors + crashed pool class
Celluloid::Actor[:clclass].fail_me # => expected behaviour

[:myclass] crashes the poolmanager class and all the actors inside.
[:clclass] works as expected.

Is it supposed to do that? Am i supposed to inherit from PoolManager? if not, then how can i rename the instance of PoolManager class?

I guess my first question is what do you hope to accomplish by subclassing PoolManager, i.e. what behavior do you want which the existing PoolManager does not provide?

If you would merely like to call some method when an actor crashes, you can define the "finalize" method of a given actor.
 
also:
Celluloid::Actor[:clclass].class.name # => Celluloid::PoolManager, but:
MyWorker.supervise_as :exmpl
Celluloid::Actor[:exmpl].class.name # => MyWorker

imho, a call like [:actor].class to an instance of PoolManager should produce the same result as a call to an instance of other actors, just my 2 cents, that's why i started to bother with renaming PoolManager in a first place.

This is an oversight as PoolManager is really a delegator
 
--
Tony Arcieri

early adopter

unread,
Jun 6, 2012, 7:59:08 AM6/6/12
to cellulo...@googlegroups.com
The only thing i want from PoolManager is to respond with the name of it's worker class, when i call [:pool].class.name, i have an array of pool objects with other components calling #select{|c| c.class.name =~ /regex/} to find the relevant pool and exec methods from it.
I need to create pools dynamically at run-time, with pools having a custom class name.
Unfortunately, the only method i found to work so far is to do something like this:

def make_pools
    services = Smshelper::Api.constants.map(&Smshelper::Api.method(:const_get)).grep(Class).select do |obj|
      obj if obj.instance_methods(false).include?(:send_message)
    end

    services.each do |k|
      k.class_eval do
        include Celluloid
        def initialize(wk, opts = {})
          super
          puts '------- INITIALIZING --------'.green.bold + report_action
        end
        def finalize
          puts '------- FINALIZING --------'.red.bold + report_action
        end
        def report_action
          self.class.name.green + ' ' + \
          self.object_id.to_s.magenta + \
          ' ' + current_actor.object_id.to_s.magenta.bold
        end
      end
      name = k.name.to_s.split('::').last.downcase.to_sym
      op_cfg = Smshelper::Config.new(name => operators[name])
      super_class = Class.new(Celluloid::PoolManager)
      pm = Smshelper::Api.const_set((name.to_s.capitalize + 'Pool'), Celluloid::PoolManager) #super_class)
      pm.supervise_as name, k, :size => 2, :args => [op_cfg]
      puts "------- POOL [:#{name.to_s.cyan.bold}] INIT --------".green.bold
end

i can't even tell, if i'm doing something stupid here, my experience with ruby is not yet at a point where i can make such a determination, i mean on the surface this code seems to do just what i want it to, except for PoolManager not wanting to play nicely...
Reply all
Reply to author
Forward
0 new messages