theine 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/bin/theine_set_ruby +5 -2
- data/lib/theine/client.rb +91 -28
- data/lib/theine/config.rb +27 -0
- data/lib/theine/server.rb +61 -52
- data/lib/theine/worker.rb +124 -0
- metadata +3 -2
- data/lib/theine/instance.rb +0 -114
data/bin/theine_set_ruby
CHANGED
|
@@ -3,13 +3,16 @@ script = <<EOS
|
|
|
3
3
|
#!/bin/sh
|
|
4
4
|
RUBY_CMD="%RUBY_CMD%"
|
|
5
5
|
|
|
6
|
-
$RUBY_CMD -e "require '
|
|
6
|
+
$RUBY_CMD -e "require '%CLIENT_RB_PATH%'" "$@"
|
|
7
7
|
EOS
|
|
8
8
|
|
|
9
9
|
if ARGV[0]
|
|
10
10
|
path = %x[which theine]
|
|
11
|
+
client_rb_path = File.expand_path('../../lib/theine/client.rb', __FILE__)
|
|
11
12
|
File.open(path.strip, "w") do |f|
|
|
12
|
-
|
|
13
|
+
script.gsub!("%CLIENT_RB_PATH%", client_rb_path)
|
|
14
|
+
script.gsub!("%RUBY_CMD%", ARGV[0])
|
|
15
|
+
f.write(script)
|
|
13
16
|
end
|
|
14
17
|
puts "Set theine to run using #{ARGV[0]}."
|
|
15
18
|
else
|
data/lib/theine/client.rb
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
require 'drb/drb'
|
|
2
2
|
require 'readline'
|
|
3
|
-
|
|
4
|
-
PRAILS_BASE_PORT = 11000
|
|
3
|
+
require_relative './config'
|
|
5
4
|
|
|
6
5
|
class IOUndumpedProxy
|
|
7
6
|
include DRb::DRbUndumped
|
|
@@ -31,6 +30,10 @@ class IOUndumpedProxy
|
|
|
31
30
|
end
|
|
32
31
|
end
|
|
33
32
|
|
|
33
|
+
def gets(*args)
|
|
34
|
+
@obj.gets(*args)
|
|
35
|
+
end
|
|
36
|
+
|
|
34
37
|
def puts(*lines)
|
|
35
38
|
@obj.puts(*lines)
|
|
36
39
|
end
|
|
@@ -59,32 +62,92 @@ class IOUndumpedProxy
|
|
|
59
62
|
end
|
|
60
63
|
end
|
|
61
64
|
|
|
62
|
-
|
|
63
|
-
|
|
65
|
+
module Theine
|
|
66
|
+
class Client
|
|
67
|
+
def self.start
|
|
68
|
+
new
|
|
69
|
+
end
|
|
64
70
|
|
|
65
|
-
|
|
71
|
+
attr_reader :config
|
|
72
|
+
|
|
73
|
+
def initialize
|
|
74
|
+
@config = ConfigReader.new(Dir.pwd)
|
|
75
|
+
reset_argv!
|
|
76
|
+
trap_signals
|
|
77
|
+
begin
|
|
78
|
+
connect_worker
|
|
79
|
+
redirect_io
|
|
80
|
+
run_command
|
|
81
|
+
ensure
|
|
82
|
+
stop
|
|
83
|
+
end
|
|
84
|
+
end
|
|
66
85
|
|
|
67
|
-
|
|
68
|
-
begin
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
86
|
+
def stop(sleep_for = 0.1)
|
|
87
|
+
begin
|
|
88
|
+
if @worker
|
|
89
|
+
%x[kill -2 #{@worker.pid}] # TODO: if client was term-ed, term worker (maybe term)
|
|
90
|
+
puts "Stopping Theine worker."
|
|
91
|
+
sleep(sleep_for) if sleep_for > 0 # to finish receiving IO
|
|
92
|
+
end
|
|
93
|
+
rescue DRb::DRbConnError
|
|
94
|
+
end
|
|
95
|
+
exit(0)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
private
|
|
99
|
+
def run_command
|
|
100
|
+
@worker.command_rails(@argv)
|
|
101
|
+
rescue DRb::DRbConnError
|
|
102
|
+
$stderr.puts "\nTheine closed the connection."
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def reset_argv!
|
|
106
|
+
@argv = ARGV.dup
|
|
107
|
+
ARGV.clear
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def trap_signals
|
|
111
|
+
trap('INT') { exit(0) } # TODO: is this needed?
|
|
112
|
+
trap('TERM') { exit(0) }
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def redirect_io
|
|
116
|
+
@worker.stdin = IOUndumpedProxy.new($stdin)
|
|
117
|
+
@worker.stdout = IOUndumpedProxy.new($stdout)
|
|
118
|
+
@worker.stderr = IOUndumpedProxy.new($stderr)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def connect_worker
|
|
122
|
+
balancer = wait_until_result("Cannot connect to theine server. Waiting") do
|
|
123
|
+
object = DRbObject.new_with_uri("druby://localhost:#{config.base_port}")
|
|
124
|
+
object.respond_to?(:get_port) # test if connected
|
|
125
|
+
object
|
|
126
|
+
end
|
|
127
|
+
port = wait_until_result("Waiting for Theine worker...") do
|
|
128
|
+
balancer.get_port
|
|
129
|
+
end
|
|
130
|
+
@worker = DRbObject.new_with_uri("druby://localhost:#{port}")
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
WaitResultNoResultError = Class.new(StandardError)
|
|
134
|
+
def wait_until_result(wait_message)
|
|
135
|
+
result = nil
|
|
136
|
+
dots = 0
|
|
137
|
+
begin
|
|
138
|
+
result = yield
|
|
139
|
+
raise WaitResultNoResultError unless result
|
|
140
|
+
rescue DRb::DRbConnError, WaitResultNoResultError
|
|
141
|
+
print dots == 0 ? wait_message : "."
|
|
142
|
+
dots += 1
|
|
143
|
+
sleep 0.5
|
|
144
|
+
retry
|
|
145
|
+
end
|
|
146
|
+
print "\n" if dots > 0
|
|
147
|
+
result
|
|
148
|
+
end
|
|
149
|
+
end
|
|
90
150
|
end
|
|
151
|
+
|
|
152
|
+
DRb.start_service
|
|
153
|
+
Theine::Client.start
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require 'yaml'
|
|
2
|
+
|
|
3
|
+
module Theine
|
|
4
|
+
class ConfigReader
|
|
5
|
+
attr_reader :rails_root
|
|
6
|
+
attr_accessor :base_port, :max_port, :min_free_workers, :spawn_parallel
|
|
7
|
+
def initialize(rails_root)
|
|
8
|
+
@rails_root = rails_root
|
|
9
|
+
@base_port = 11000
|
|
10
|
+
@max_port = 11100
|
|
11
|
+
@min_free_workers = 2
|
|
12
|
+
@spawn_parallel = true
|
|
13
|
+
load_config(File.expand_path("~/.theine"))
|
|
14
|
+
load_config("#{rails_root}/.theine")
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def load_config(path)
|
|
18
|
+
if File.exist?(path)
|
|
19
|
+
config = YAML.load(File.read(path))
|
|
20
|
+
config.each_pair do |k, v|
|
|
21
|
+
setter = :"#{k}="
|
|
22
|
+
send(setter, v) if respond_to?(setter)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
data/lib/theine/server.rb
CHANGED
|
@@ -1,75 +1,84 @@
|
|
|
1
1
|
require 'drb/drb'
|
|
2
2
|
require 'thread'
|
|
3
|
+
require 'yaml'
|
|
4
|
+
require_relative './config'
|
|
3
5
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
module Theine
|
|
7
|
+
class Server
|
|
8
|
+
include DRb::DRbUndumped
|
|
9
|
+
attr_reader :config
|
|
8
10
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
+
def initialize
|
|
12
|
+
@config = ConfigReader.new(Dir.pwd)
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
@spawning = []
|
|
14
|
+
@workers = []
|
|
15
|
+
@spawning = []
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def add_instance
|
|
22
|
-
path = File.expand_path('../instance.rb', __FILE__)
|
|
23
|
-
port = @available_ports.shift
|
|
24
|
-
puts "(spawn #{port})"
|
|
25
|
-
spawn("ruby", path, PRAILS_BASE_PORT.to_s, port.to_s, RAILS_APP_ROOT)
|
|
26
|
-
@instances_mutex.synchronize { @spawning << 1 }
|
|
27
|
-
end
|
|
17
|
+
@available_ports = ((config.base_port + 1)..config.max_port).to_a
|
|
18
|
+
@check_mutex = Mutex.new
|
|
19
|
+
@workers_mutex = Mutex.new
|
|
28
20
|
|
|
29
|
-
|
|
30
|
-
|
|
21
|
+
run
|
|
22
|
+
end
|
|
31
23
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
24
|
+
def add_worker
|
|
25
|
+
path = File.expand_path('../worker.rb', __FILE__)
|
|
26
|
+
port = @available_ports.shift
|
|
27
|
+
puts "(spawn #{port})"
|
|
28
|
+
spawn("ruby", path, config.base_port.to_s, port.to_s, config.rails_root)
|
|
29
|
+
@workers_mutex.synchronize { @spawning << 1 }
|
|
35
30
|
end
|
|
36
|
-
end
|
|
37
31
|
|
|
38
|
-
|
|
39
|
-
|
|
32
|
+
def worker_boot(port)
|
|
33
|
+
puts "+ worker #{port}"
|
|
40
34
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
port = @instances.shift
|
|
35
|
+
@workers_mutex.synchronize do
|
|
36
|
+
@spawning.pop
|
|
37
|
+
@workers << port
|
|
45
38
|
end
|
|
46
|
-
sleep 0.1 unless port
|
|
47
39
|
end
|
|
48
40
|
|
|
49
|
-
|
|
41
|
+
def worker_done(port)
|
|
42
|
+
puts "- worker #{port}"
|
|
43
|
+
end
|
|
50
44
|
|
|
51
|
-
|
|
52
|
-
|
|
45
|
+
def get_port
|
|
46
|
+
add_worker if all_size == 0
|
|
53
47
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
# TODO: mutex, and dont do it if already in progress
|
|
57
|
-
# do this in thread
|
|
58
|
-
while all_size < MIN_FREE_INSTANCES
|
|
59
|
-
sleep 0.1 until @instances_mutex.synchronize { @spawning.empty? }
|
|
60
|
-
add_instance
|
|
48
|
+
port = @workers_mutex.synchronize do
|
|
49
|
+
@workers.shift
|
|
61
50
|
end
|
|
62
|
-
|
|
51
|
+
|
|
52
|
+
Thread.new { check_min_free_workers }
|
|
53
|
+
|
|
54
|
+
port
|
|
63
55
|
end
|
|
64
|
-
end
|
|
65
56
|
|
|
66
|
-
|
|
67
|
-
|
|
57
|
+
def check_min_free_workers
|
|
58
|
+
if @check_mutex.try_lock
|
|
59
|
+
# TODO: mutex, and dont do it if already in progress
|
|
60
|
+
# do this in thread
|
|
61
|
+
while all_size < config.min_free_workers
|
|
62
|
+
unless config.spawn_parallel
|
|
63
|
+
sleep 0.1 until @workers_mutex.synchronize { @spawning.empty? }
|
|
64
|
+
end
|
|
65
|
+
add_worker
|
|
66
|
+
end
|
|
67
|
+
@check_mutex.unlock
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def all_size
|
|
72
|
+
@workers_mutex.synchronize { @workers.size + @spawning.size }
|
|
73
|
+
end
|
|
74
|
+
private
|
|
75
|
+
def run
|
|
76
|
+
DRb.start_service("druby://localhost:#{config.base_port}", self)
|
|
77
|
+
check_min_free_workers
|
|
78
|
+
DRb.thread.join
|
|
79
|
+
end
|
|
68
80
|
end
|
|
69
81
|
end
|
|
70
82
|
|
|
71
|
-
server =
|
|
72
|
-
DRb.start_service("druby://localhost:#{PRAILS_BASE_PORT}", server)
|
|
83
|
+
server = Theine::Server.new
|
|
73
84
|
|
|
74
|
-
server.check_min_free_instances
|
|
75
|
-
DRb.thread.join
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
root_path = ARGV[2]
|
|
2
|
+
APP_PATH = "#{root_path}/config/application"
|
|
3
|
+
require "#{root_path}/config/boot"
|
|
4
|
+
require "#{root_path}/config/environment"
|
|
5
|
+
require 'drb/drb'
|
|
6
|
+
|
|
7
|
+
$real_stdout = $stdout
|
|
8
|
+
$real_stderr = $stderr
|
|
9
|
+
|
|
10
|
+
module Theine
|
|
11
|
+
class Worker
|
|
12
|
+
attr_reader :stdin, :stdout, :stderr
|
|
13
|
+
InputProxy = Struct.new :input do
|
|
14
|
+
# Reads a line from the input
|
|
15
|
+
def readline(prompt)
|
|
16
|
+
case readline_arity
|
|
17
|
+
when 1 then input.readline(prompt)
|
|
18
|
+
else input.readline
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def completion_proc=(val)
|
|
23
|
+
input.completion_proc = val
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def readline_arity
|
|
27
|
+
input.method_missing(:method, :readline).arity
|
|
28
|
+
rescue NameError
|
|
29
|
+
0
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def gets(*args)
|
|
33
|
+
input.gets(*args)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def initialize
|
|
38
|
+
@pumps = []
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def command_rails(argv)
|
|
42
|
+
rails_reload!
|
|
43
|
+
|
|
44
|
+
ARGV.clear
|
|
45
|
+
ARGV.concat(argv)
|
|
46
|
+
|
|
47
|
+
require 'pry'
|
|
48
|
+
::Rails.application.config.console = Pry
|
|
49
|
+
|
|
50
|
+
Pry.config.input = stdin
|
|
51
|
+
Pry.config.output = stdout
|
|
52
|
+
|
|
53
|
+
require 'rails/commands'
|
|
54
|
+
sleep 0.1 # allow Pumps to finish
|
|
55
|
+
DRb.stop_service
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def stdin=(value)
|
|
59
|
+
@stdin = InputProxy.new(value)
|
|
60
|
+
$stdin = @stdin
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def stdout=(value)
|
|
64
|
+
$orig_stdout = $stdout
|
|
65
|
+
@stdout = value
|
|
66
|
+
r, w = IO.pipe
|
|
67
|
+
$stdout = w
|
|
68
|
+
@pumps << Pump.new(r, @stdout)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def stderr=(value)
|
|
72
|
+
$orig_stderr = $stderr
|
|
73
|
+
@stderr = value
|
|
74
|
+
r, w = IO.pipe
|
|
75
|
+
$stderr = w
|
|
76
|
+
@pumps << Pump.new(r, @stderr)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def pid
|
|
80
|
+
::Process.pid
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
private
|
|
84
|
+
def rails_reload!
|
|
85
|
+
ActionDispatch::Reloader.cleanup!
|
|
86
|
+
ActionDispatch::Reloader.prepare!
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
class Pump < Thread
|
|
90
|
+
def initialize(input, output)
|
|
91
|
+
if output
|
|
92
|
+
@input = input
|
|
93
|
+
@output = output
|
|
94
|
+
super(&method(:main))
|
|
95
|
+
else
|
|
96
|
+
close_stream(input)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
private
|
|
101
|
+
def main
|
|
102
|
+
while buf = @input.sysread(1024)
|
|
103
|
+
@output.print(buf)
|
|
104
|
+
@output.flush
|
|
105
|
+
end
|
|
106
|
+
ensure
|
|
107
|
+
@output.close
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
base_port = ARGV[0]
|
|
114
|
+
worker_port = ARGV[1]
|
|
115
|
+
DRb.start_service("druby://localhost:#{worker_port}", Theine::Worker.new)
|
|
116
|
+
|
|
117
|
+
balancer = DRbObject.new_with_uri("druby://localhost:#{base_port}")
|
|
118
|
+
balancer.worker_boot(worker_port)
|
|
119
|
+
|
|
120
|
+
begin
|
|
121
|
+
DRb.thread.join
|
|
122
|
+
ensure
|
|
123
|
+
balancer.worker_done(worker_port)
|
|
124
|
+
end
|
metadata
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: theine
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease:
|
|
5
|
-
version: 0.0.
|
|
5
|
+
version: 0.0.3
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
8
8
|
- Jan Berdajs
|
|
@@ -23,7 +23,8 @@ files:
|
|
|
23
23
|
- lib/theine.rb
|
|
24
24
|
- lib/theine/client.rb
|
|
25
25
|
- lib/theine/server.rb
|
|
26
|
-
- lib/theine/
|
|
26
|
+
- lib/theine/worker.rb
|
|
27
|
+
- lib/theine/config.rb
|
|
27
28
|
- bin/theine
|
|
28
29
|
- bin/theine_server
|
|
29
30
|
- bin/theine_set_ruby
|
data/lib/theine/instance.rb
DELETED
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
root_path = ARGV[2]
|
|
2
|
-
APP_PATH = "#{root_path}/config/application"
|
|
3
|
-
require "#{root_path}/config/boot"
|
|
4
|
-
require "#{root_path}/config/environment"
|
|
5
|
-
require 'drb/drb'
|
|
6
|
-
|
|
7
|
-
$real_stdout = $stdout
|
|
8
|
-
$real_stderr = $stderr
|
|
9
|
-
|
|
10
|
-
class PrailsServer
|
|
11
|
-
attr_reader :stdin, :stdout, :stderr
|
|
12
|
-
InputProxy = Struct.new :input do
|
|
13
|
-
# Reads a line from the input
|
|
14
|
-
def readline(prompt)
|
|
15
|
-
case readline_arity
|
|
16
|
-
when 1 then input.readline(prompt)
|
|
17
|
-
else input.readline
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def completion_proc=(val)
|
|
22
|
-
input.completion_proc = val
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def readline_arity
|
|
26
|
-
input.method_missing(:method, :readline).arity
|
|
27
|
-
rescue NameError
|
|
28
|
-
0
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def initialize
|
|
33
|
-
@pumps = []
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def command_rails(argv)
|
|
37
|
-
rails_reload!
|
|
38
|
-
|
|
39
|
-
ARGV.clear
|
|
40
|
-
ARGV.concat(argv)
|
|
41
|
-
|
|
42
|
-
require 'pry'
|
|
43
|
-
::Rails.application.config.console = Pry
|
|
44
|
-
|
|
45
|
-
Pry.config.input = stdin
|
|
46
|
-
Pry.config.output = stdout
|
|
47
|
-
|
|
48
|
-
require 'rails/commands'
|
|
49
|
-
sleep 0.1 # allow Pumps to finish
|
|
50
|
-
DRb.stop_service
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
def stdin=(value)
|
|
54
|
-
@stdin = InputProxy.new(value)
|
|
55
|
-
$stdin = @stdin
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def stdout=(value)
|
|
59
|
-
$orig_stdout = $stdout
|
|
60
|
-
@stdout = value
|
|
61
|
-
r, w = IO.pipe
|
|
62
|
-
$stdout = w
|
|
63
|
-
@pumps << Pump.new(r, @stdout)
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def stderr=(value)
|
|
67
|
-
$orig_stderr = $stderr
|
|
68
|
-
@stderr = value
|
|
69
|
-
r, w = IO.pipe
|
|
70
|
-
$stderr = w
|
|
71
|
-
@pumps << Pump.new(r, @stderr)
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
def pid
|
|
75
|
-
::Process.pid
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
private
|
|
79
|
-
def rails_reload!
|
|
80
|
-
ActionDispatch::Reloader.cleanup!
|
|
81
|
-
ActionDispatch::Reloader.prepare!
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
class Pump < Thread
|
|
85
|
-
def initialize(input, output)
|
|
86
|
-
if output
|
|
87
|
-
@input = input
|
|
88
|
-
@output = output
|
|
89
|
-
super(&method(:main))
|
|
90
|
-
else
|
|
91
|
-
close_stream(input)
|
|
92
|
-
end
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
private
|
|
96
|
-
def main
|
|
97
|
-
while buf = @input.sysread(1024)
|
|
98
|
-
@output.print(buf)
|
|
99
|
-
@output.flush
|
|
100
|
-
end
|
|
101
|
-
ensure
|
|
102
|
-
@output.close
|
|
103
|
-
end
|
|
104
|
-
end
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
base_port = ARGV[0]
|
|
108
|
-
instance_port = ARGV[1]
|
|
109
|
-
DRb.start_service("druby://localhost:#{instance_port}", PrailsServer.new)
|
|
110
|
-
|
|
111
|
-
balancer = DRbObject.new_with_uri("druby://localhost:#{base_port}")
|
|
112
|
-
balancer.instance_boot(instance_port)
|
|
113
|
-
|
|
114
|
-
DRb.thread.join
|