hopsoft/legion

View on GitHub
lib/legion/supervisor.rb

Summary

Maintainability
A
45 mins
Test Coverage
require "drb"

module Legion
  class Supervisor
    attr_reader(
      :klass,
      :processes,
      :port,
      :local_instances,
      :remote_instances
    )

    def initialize(klass, processes: 1, port: 42042)
      @klass = klass
      @processes = processes
      @port = port
      @local_instances = []
      @remote_instances = []
    end

    def run
      start
      yield self
      stop
    end

    def start
      DRb.start_service
      (1..processes).each do |i|
        local_instance = klass.new
        local_instance.start_remote_instance(port: port)
        @port += 1
        local_instances << local_instance
        remote_instance = DRbObject.new_with_uri(local_instance.uri)
        verify_remote_instance(remote_instance)
        remote_instances << remote_instance
      end
    end

    def stop
      remote_instances.each { |inst| inst.exit }
      DRb.stop_service
    end

    def get_remote_instance
      remote_instance = nil
      while remote_instance.nil?
        (0..remote_instances.length - 1).each do |index|
          next if remote_instances[index].busy?
          remote_instance = remote_instances[index]
          break
        end
        sleep 0.01 if remote_instance.nil?
      end
      remote_instance
    end

    def method_missing(name, *args)
      get_remote_instance.send("#{name}_async", *args)
    end

    def respond_to?(name)
      return true if super
      klass.instance_methods.include? name.to_sym
    end

    protected

    def verify_remote_instance(remote_instance)
      ok = false
      while !ok
        begin
          ok = remote_instance.ok?
        rescue DRb::DRbConnError
          sleep 0.1
        end
      end
      ok
    end

  end
end