Class: JRubyBridge::Service

Inherits:
Object
  • Object
show all
Defined in:
lib/jruby_bridge/service.rb

Overview

A Ruby-managed JRuby application.

Constant Summary collapse

DAEMON =

Path to JRuby application

File.join(File.dirname(__FILE__), 'server.rb')
PORT =

Port to listen on in JRuby

44344
TIMEOUT =

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

300

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.default_uriObject



102
103
104
# File 'lib/jruby_bridge/service.rb', line 102

def self.default_uri
  "druby://localhost:#{PORT}"
end

.drb_start(port) ⇒ Object

Called by the server script in JRuby context



90
91
92
93
94
95
96
97
98
99
100
# 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) ⇒ Object

Replace current process with JRuby running JRubyBridge::Service



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# 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_jrubyObject

Return command to launch JRuby interpreter



107
108
109
110
111
112
113
114
115
116
117
118
119
120
# 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_objectObject



122
123
124
125
# 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) ⇒ Object



28
29
30
# File 'lib/jruby_bridge/service.rb', line 28

def self.remote_require(*args)
  @remote_requires = args
end

.startObject



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# 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

.stopObject



63
64
65
# File 'lib/jruby_bridge/service.rb', line 63

def self.stop
  new_drb_object.stop
end

.with_service(&block) ⇒ Object



32
33
34
35
36
37
# File 'lib/jruby_bridge/service.rb', line 32

def self.with_service(&block)
  start
  yield
ensure
  stop
end

Instance Method Details

#remote_proxied_new(klass, *args) ⇒ Object

Objects created from within this instance reside in the JRuby process



24
25
26
# File 'lib/jruby_bridge/service.rb', line 24

def remote_proxied_new(klass, *args)
  klass.proxied_new *args
end

#stopObject



67
68
69
# File 'lib/jruby_bridge/service.rb', line 67

def stop
  DRb.stop_service
end