module Celluloid module Supervision class Container # Manages a fixed-size pool of actors # Delegates work (i.e. methods) and supervises actors # Don't use this class directly. Instead use MyKlass.pool class Pool def initialize(options={}) @idle = [] @busy = [] @klass = options[:actors] @actors = Set.new @mutex = Mutex.new @size = options[:size] || [Celluloid.cores || 2, 2].max @args = options[:args] ? Array(options[:args]) : [] @exit_handler = options[:exit_handler] # Do this last since it can suspend and/or crash @idle = @size.times.map { __spawn_actor__ } end # Spawn a new worker for every crashed one def __crash_handler__(actor, reason) @mutex.synchronize { @busy.delete actor @idle.delete actor @actors.delete actor } @exit_handler.call(actor, reason) if @exit_handler return unless reason @idle << __spawn_actor__ signal :respawn_complete end class << self def pooling_options(config={},mixins={}) combined = { :type => Celluloid::Supervision::Container::Pool }.merge(config).merge(mixins) combined[:args] = [[:block, :actors, :size, :args, :exit_handler].inject({}) { |e,p| e[p] = combined.delete(p) if combined[p]; e }] combined end end identifier! :size, :pool, :exit_handler configuration do @supervisor = Container::Pool @method = "pool_link" @pool = true @pool_size = @configuration[:size] @exit_handler = @configuration[:exit_handler] @configuration end end end end end