bogdanrada
1/5/2016 - 6:50 AM

exit_handler monkeypatch for pool

exit_handler monkeypatch for pool

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