class JRubyBridge::Service

A Ruby-managed JRuby application.

Constants

DAEMON

Path to JRuby application

PORT

Port to listen on in JRuby

TIMEOUT

Time to allow JRuby to initialize, in 100-ms increments

Public Class Methods

default_uri() click to toggle source
# File lib/jruby_bridge/service.rb, line 102
def self.default_uri
  "druby://localhost:#{PORT}"
end
drb_start(port) click to toggle source

Called by the server script in JRuby context

# File lib/jruby_bridge/service.rb, line 90
def self.drb_start(port)
  port ||= PORT

  DRb.start_service "druby://localhost:#{port.to_i}", self.new

  _self = self
  trap('HUP') { DRb.stop_service; _self.drb_start(port) }
  trap('INT') { DRb.stop_service }

  DRb.thread.join
end
exec(port) click to toggle source

Replace current process with JRuby running JRubyBridge::Service

# File lib/jruby_bridge/service.rb, line 72
def self.exec(port)
  unless jruby = get_jruby
    # Note: a raised exception goes nowhere: instead use exit status
    $stderr.puts "No JRuby found!"
    return 1
  end

  command = [
    jruby,
    @remote_requires.map { |path| %Q(-r"#{path}") },
    DAEMON,
    port
  ].compact.join(' ')

  Kernel.exec command
end
get_jruby() click to toggle source

Return command to launch JRuby interpreter

# File lib/jruby_bridge/service.rb, line 107
def self.get_jruby
  # FIXME: this should detect RVM first and system second

  # 1. detect system JRuby
  jruby = `which jruby`
  return jruby.chomp if (! jruby.empty?)

  # 2. detect RVM-managed JRuby
  return nil if (`which rvm`).empty?
  jruby = `rvm list`.split("\n").select { |rb| rb.include? 'jruby' }.first
  return nil if (! jruby)

  "rvm #{jruby.strip.split(' ').first} do ruby "
end
new_drb_object() click to toggle source
# File lib/jruby_bridge/service.rb, line 122
def self.new_drb_object
  # This returns a proxied instance of Service
  DRb::DRbObject.new_with_uri(default_uri)
end
remote_require(*args) click to toggle source
# File lib/jruby_bridge/service.rb, line 28
def self.remote_require(*args)
  @remote_requires = args
end
start() click to toggle source
# File lib/jruby_bridge/service.rb, line 39
def self.start
  return @pid if @pid
  _self = self
  @pid = Process.fork do
    exit _self.exec(PORT)
  end
  # TODO : check child exit status and raise JRubyExecError
  Process.detach(@pid)

  connected = false
  TIMEOUT.times do
    begin
      DRb::DRbObject.new_with_uri(default_uri).to_s
      connected = true
      break
    rescue DRb::DRbConnError
      sleep 0.1
    end
  end
  unless connected
    raise "Could not connect to #{default_uri}"
  end
end
stop() click to toggle source
# File lib/jruby_bridge/service.rb, line 63
def self.stop
  new_drb_object.stop
end
with_service() { || ... } click to toggle source
# File lib/jruby_bridge/service.rb, line 32
def self.with_service(&block)
  start
  yield
ensure
  stop
end

Public Instance Methods

remote_proxied_new(klass, *args) click to toggle source

Objects created from within this instance reside in the JRuby process

# File lib/jruby_bridge/service.rb, line 24
def remote_proxied_new(klass, *args)
  klass.proxied_new *args
end
stop() click to toggle source
# File lib/jruby_bridge/service.rb, line 67
def stop
  DRb.stop_service
end