Search code examples
rubycelluloid

How can I notify a Celluliod::Actor of mastered Celluloid::Pool actor died?


I got a test example.

Here MyBoss should accomplish hard, but granulated work, despite some of its workes have to die.

require 'celluloid'
require 'celluloid/autostart'

class MyActor
  include Celluloid

  attr_reader :name, :peace_of_work

  def initialize
    @name = "actor_#{self.object_id}"
    print "Created actor '#{@name}'\n"
  end

  def run(peace_of_work)
    @peace_of_work = peace_of_work
    sleep 0.1
    raise "Actor '#{@name}' is dying" if rand(0..1.0) < 0.1
    print "Actor '#{@name}' has #{peace_of_work}-th peace of work done\n"
  end
end

class MyBoss
  def initialize
  end

  def run work_peaces
    @work_peaces = work_peaces
    @actor_pool = MyActor.pool(size: 10, args: [])
    work_peaces.each do |peace_of_work|
      @actor_pool.async.run(peace_of_work)
    end
  end
end

if __FILE__ == $PROGRAM_NAME
  boss = MyBoss.new
  work_peaces = (0..999).to_a
  boss.run(work_peaces)
  sleep
end

Actors sporadically die. Obiously I need to redo screwed up work peaces. How can I trap actors deaths in case they are in a pool? Notice MyActor.pool(size: 10, args: [])


Solution

  • This is a known issue being resolved at the link below:

    The gist is:

    trap_exit already works for the Pool manager itself. When an actor dies, it needs to be taken out of the idle and busy sets of the Pool and a new actor needs to be spawned as idle ... otherwise the Pool becomes unstable.

    A secondary method needs to be injected to run after Pool itself can correct its situation with a dead actor.