expedite 0.1.0 → 0.2.0
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.
- checksums.yaml +4 -4
- data/README.md +7 -0
- data/lib/expedite/actions.rb +4 -4
- data/lib/expedite/agents.rb +1 -1
- data/lib/expedite/cli/rails.rb +13 -0
- data/lib/expedite/cli.rb +21 -10
- data/lib/expedite/client/exec.rb +10 -1
- data/lib/expedite/client/invoke.rb +6 -2
- data/lib/expedite/env.rb +2 -4
- data/lib/expedite/errors.rb +3 -0
- data/lib/expedite/helper/rails.rb +14 -0
- data/lib/expedite/protocol.rb +7 -4
- data/lib/expedite/server/agent.rb +75 -39
- data/lib/expedite/server/agent_manager.rb +28 -21
- data/lib/expedite/server/agent_pool.rb +39 -0
- data/lib/expedite/server/application_manager.rb +27 -0
- data/lib/expedite/server/controller.rb +55 -13
- data/lib/expedite/version.rb +1 -1
- data/lib/expedite.rb +0 -2
- metadata +6 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: da93957645e66819877d4c8638d2d42eb4880c631d6b4f8f224a3a9502c45a36
|
|
4
|
+
data.tar.gz: 179e78a453744f0375f6b184ffa1a2cff321b7ab92deafc9be5297fb00c63c4b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8cf3e2d403eab2d5cb7960a1d5cc43a4f94c3d0495ce36b360d32ec77ad7e5f9887a0e7aca183afa2e441ac3ff23a555ec6254f8441d971783376bdfc84db471
|
|
7
|
+
data.tar.gz: 30f00102d8d8c6cc59f138841caa116421f3002871551dca20718dfc5100aec80f469e8bb31b1d1ee8158020852090b2c053bff5d5fd7c9c728fdc26e4c3c6d0
|
data/README.md
CHANGED
|
@@ -89,6 +89,13 @@ You can also start the server in the foreground.
|
|
|
89
89
|
$ bundle exec expedite server
|
|
90
90
|
```
|
|
91
91
|
|
|
92
|
+
If `rails` is in the `Gemfile`, then you can also start the rails commands through expedite.
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
$ bundle exec expedite rails console
|
|
96
|
+
$ echo "puts ActiveRecord::Base.connection" | bundle exec expedite rails runner -
|
|
97
|
+
```
|
|
98
|
+
|
|
92
99
|
## Acknowledgements
|
|
93
100
|
|
|
94
101
|
Expedite's server core is modified from [Spring](https://github.com/rails/spring)
|
data/lib/expedite/actions.rb
CHANGED
|
@@ -35,9 +35,9 @@ module Expedite
|
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
def lookup(name)
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
ret = @registrations[name.to_s]
|
|
39
|
+
raise NotImplementedError, "Action #{name.inspect} not found" if ret.nil?
|
|
40
|
+
ret
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
def register(name, klass_or_nil = nil, **named_options, &block)
|
|
@@ -47,7 +47,7 @@ module Expedite
|
|
|
47
47
|
klass_or_nil.new(**named_options)
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
-
@registrations[name] = cmd
|
|
50
|
+
@registrations[name.to_s] = cmd
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
def reset
|
data/lib/expedite/agents.rb
CHANGED
data/lib/expedite/cli.rb
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
|
+
require 'expedite/cli/rails'
|
|
1
2
|
require 'expedite/cli/server'
|
|
2
3
|
require 'expedite/cli/status'
|
|
3
4
|
require 'expedite/cli/stop'
|
|
4
5
|
|
|
5
6
|
module Expedite
|
|
6
7
|
module Cli
|
|
8
|
+
class UnknownCommandError < StandardError
|
|
9
|
+
end
|
|
10
|
+
|
|
7
11
|
class Help
|
|
8
12
|
def run(args)
|
|
9
13
|
puts "Expected: <command>"
|
|
10
14
|
puts
|
|
11
15
|
puts "Commands:"
|
|
12
16
|
|
|
13
|
-
cmds = Expedite::Cli
|
|
17
|
+
cmds = Expedite::Cli.commands
|
|
14
18
|
cmds.keys.sort!.each do |cmd|
|
|
15
19
|
c = cmds[cmd].new
|
|
16
20
|
puts " #{cmd}: #{c.summary}"
|
|
@@ -24,22 +28,29 @@ module Expedite
|
|
|
24
28
|
|
|
25
29
|
module_function
|
|
26
30
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
def commands
|
|
32
|
+
return @commands unless @commands.nil?
|
|
33
|
+
|
|
34
|
+
cmds = {
|
|
35
|
+
'help' => Cli::Help,
|
|
36
|
+
'server' => Cli::Server,
|
|
37
|
+
'status' => Cli::Status,
|
|
38
|
+
'stop' => Cli::Stop,
|
|
39
|
+
}
|
|
40
|
+
cmds['rails'] = Cli::Rails if Gem.loaded_specs["rails"]
|
|
41
|
+
@commands = cmds
|
|
42
|
+
end
|
|
33
43
|
|
|
34
44
|
def run(args)
|
|
35
45
|
command(args.first).run(args[1..])
|
|
36
|
-
rescue
|
|
46
|
+
rescue UnknownCommandError => e
|
|
47
|
+
STDERR.puts e
|
|
37
48
|
Cli::Help.new.run([])
|
|
38
49
|
end
|
|
39
50
|
|
|
40
51
|
def command(cmd)
|
|
41
|
-
klass =
|
|
42
|
-
raise
|
|
52
|
+
klass = commands[cmd]
|
|
53
|
+
raise UnknownCommandError, "Unknown command '#{cmd}'" if klass.nil?
|
|
43
54
|
klass.new
|
|
44
55
|
end
|
|
45
56
|
end
|
data/lib/expedite/client/exec.rb
CHANGED
|
@@ -58,7 +58,16 @@ module Expedite
|
|
|
58
58
|
def run
|
|
59
59
|
status = perform(*@args)
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
code = if status.respond_to?(:to_i)
|
|
62
|
+
status.to_i
|
|
63
|
+
elsif status == true
|
|
64
|
+
0
|
|
65
|
+
elsif status == false
|
|
66
|
+
1
|
|
67
|
+
else
|
|
68
|
+
126
|
|
69
|
+
end
|
|
70
|
+
exit code
|
|
62
71
|
rescue Errno::ECONNRESET
|
|
63
72
|
exit 1
|
|
64
73
|
end
|
|
@@ -49,7 +49,7 @@ module Expedite
|
|
|
49
49
|
def connect_to_agent(client, args)
|
|
50
50
|
server.send_io client
|
|
51
51
|
|
|
52
|
-
server.send_object("args" => args, "agent" => agent)
|
|
52
|
+
server.send_object({"args" => args, "agent" => agent}, env)
|
|
53
53
|
|
|
54
54
|
if IO.select([server], [], [], CONNECT_TIMEOUT)
|
|
55
55
|
server.gets or raise CommandNotFound
|
|
@@ -65,7 +65,11 @@ module Expedite
|
|
|
65
65
|
agent.send_io STDERR
|
|
66
66
|
agent.send_io STDIN
|
|
67
67
|
|
|
68
|
-
agent.send_object(
|
|
68
|
+
agent.send_object({
|
|
69
|
+
"args" => args,
|
|
70
|
+
"env" => ENV.to_hash,
|
|
71
|
+
"method" => "invoke"
|
|
72
|
+
}, env)
|
|
69
73
|
|
|
70
74
|
pid = server.gets
|
|
71
75
|
pid = pid.chomp if pid
|
data/lib/expedite/env.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
require 'digest'
|
|
2
2
|
require 'pathname'
|
|
3
3
|
require 'expedite/version'
|
|
4
|
-
require 'expedite/server/
|
|
4
|
+
require 'expedite/server/application_manager'
|
|
5
5
|
|
|
6
6
|
module Expedite
|
|
7
7
|
class Env
|
|
@@ -18,9 +18,7 @@ module Expedite
|
|
|
18
18
|
@application_id = Digest::SHA1.hexdigest(@root)
|
|
19
19
|
|
|
20
20
|
env = self
|
|
21
|
-
@applications =
|
|
22
|
-
h[k] = Server::AgentManager.new(k, env)
|
|
23
|
-
end
|
|
21
|
+
@applications = Server::ApplicationManager.new(env)
|
|
24
22
|
end
|
|
25
23
|
|
|
26
24
|
def version
|
data/lib/expedite/errors.rb
CHANGED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
Expedite.define do
|
|
2
|
+
# Agent that rails environment loaded
|
|
3
|
+
agent :rails_environment do
|
|
4
|
+
app_root = Dir.pwd
|
|
5
|
+
require "#{app_root}/config/environment.rb"
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
# Actions that runs rails commands
|
|
9
|
+
action :rails_commands do |args|
|
|
10
|
+
ARGV.replace(args)
|
|
11
|
+
require "rails/commands"
|
|
12
|
+
true
|
|
13
|
+
end
|
|
14
|
+
end
|
data/lib/expedite/protocol.rb
CHANGED
|
@@ -2,17 +2,20 @@ require 'socket'
|
|
|
2
2
|
|
|
3
3
|
module Expedite
|
|
4
4
|
module Protocol
|
|
5
|
-
def send_object(object)
|
|
5
|
+
def send_object(object, env)
|
|
6
|
+
env.log "send_object #{object.inspect}"
|
|
6
7
|
data = Marshal.dump(object)
|
|
7
8
|
|
|
8
|
-
self.puts data.bytesize
|
|
9
|
+
self.puts data.bytesize.to_i
|
|
9
10
|
self.write data
|
|
10
11
|
end
|
|
11
12
|
|
|
12
13
|
def recv_object
|
|
13
|
-
|
|
14
|
+
len = self.gets.to_i
|
|
15
|
+
data = self.read(len)
|
|
16
|
+
Marshal.load(data)
|
|
14
17
|
end
|
|
15
18
|
end
|
|
16
19
|
end
|
|
17
20
|
|
|
18
|
-
|
|
21
|
+
IO.include ::Expedite::Protocol
|
|
@@ -23,6 +23,13 @@ module Expedite
|
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
module Server
|
|
26
|
+
# This code runs in the process that has the actual code pre-loaded, and is
|
|
27
|
+
# used to serve requests.
|
|
28
|
+
# * An "invoke" request is handled in the agent itself.
|
|
29
|
+
# * A "fork" request causes the agent to fork, and the forked process handles
|
|
30
|
+
# the request.
|
|
31
|
+
# Each agent processes a single request at a time, unless it is an
|
|
32
|
+
# Expedite::Action::Boot request which is used to make derived agents.
|
|
26
33
|
class Agent
|
|
27
34
|
include Signals
|
|
28
35
|
|
|
@@ -125,7 +132,7 @@ module Expedite
|
|
|
125
132
|
end
|
|
126
133
|
|
|
127
134
|
def serve(client)
|
|
128
|
-
|
|
135
|
+
puts "got client"
|
|
129
136
|
manager.puts
|
|
130
137
|
|
|
131
138
|
_stdout, stderr, _stdin = streams = 3.times.map { client.recv_io }
|
|
@@ -133,48 +140,23 @@ module Expedite
|
|
|
133
140
|
|
|
134
141
|
preload unless preloaded?
|
|
135
142
|
|
|
136
|
-
args, env = client.recv_object.values_at("args", "env")
|
|
143
|
+
args, env, method = client.recv_object.values_at("args", "env", "method")
|
|
137
144
|
|
|
138
145
|
exec_name = args.shift
|
|
139
146
|
action = Expedite::Actions.lookup(exec_name)
|
|
140
147
|
action.setup(client)
|
|
141
148
|
|
|
142
|
-
connect_database
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
# Load in the current env vars, except those which *were* changed when Spring started
|
|
150
|
-
env.each { |k, v| ENV[k] = v }
|
|
151
|
-
|
|
152
|
-
# requiring is faster, so if config.cache_classes was true in
|
|
153
|
-
# the environment's config file, then we can respect that from
|
|
154
|
-
# here on as we no longer need constant reloading.
|
|
155
|
-
if @original_cache_classes
|
|
156
|
-
ActiveSupport::Dependencies.mechanism = :require
|
|
157
|
-
Rails.application.config.cache_classes = true
|
|
158
|
-
end
|
|
159
|
-
|
|
160
|
-
connect_database
|
|
161
|
-
srand
|
|
162
|
-
|
|
163
|
-
invoke_after_fork_callbacks
|
|
164
|
-
shush_backtraces
|
|
165
|
-
|
|
166
|
-
begin
|
|
167
|
-
ret = action.call(*args)
|
|
168
|
-
rescue => e
|
|
169
|
-
client.send_object("exception" => e)
|
|
170
|
-
else
|
|
171
|
-
client.send_object("return" => ret )
|
|
172
|
-
end
|
|
149
|
+
connect_database # why are we connecting prior? is this for invoke?
|
|
150
|
+
pid = case method
|
|
151
|
+
when "invoke"
|
|
152
|
+
serve_invoke(client, action, args, env)
|
|
153
|
+
else
|
|
154
|
+
serve_fork(client, action, args, env)
|
|
173
155
|
end
|
|
174
156
|
|
|
175
157
|
disconnect_database
|
|
176
158
|
|
|
177
|
-
log "forked #{pid}"
|
|
159
|
+
log "forked #{pid}" # pid is current process
|
|
178
160
|
manager.puts pid
|
|
179
161
|
|
|
180
162
|
# Boot makes a new application, so we don't wait for it
|
|
@@ -201,6 +183,51 @@ module Expedite
|
|
|
201
183
|
reset_streams
|
|
202
184
|
end
|
|
203
185
|
|
|
186
|
+
# Returns pid of the current process
|
|
187
|
+
def serve_invoke(client, action, args, env)
|
|
188
|
+
begin
|
|
189
|
+
ret = action.call(*args)
|
|
190
|
+
rescue Exception => e
|
|
191
|
+
client.send_object({"exception" => e}, self.env)
|
|
192
|
+
else
|
|
193
|
+
client.send_object({"return" => ret}, self.env)
|
|
194
|
+
end
|
|
195
|
+
Process.pid
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def serve_fork(client, action, args, env)
|
|
199
|
+
fork do
|
|
200
|
+
Process.setsid
|
|
201
|
+
IGNORE_SIGNALS.each { |sig| trap(sig, "DEFAULT") }
|
|
202
|
+
trap("TERM", "DEFAULT")
|
|
203
|
+
|
|
204
|
+
# Load in the current env vars, except those which *were* changed when Spring started
|
|
205
|
+
env.each { |k, v| ENV[k] = v }
|
|
206
|
+
|
|
207
|
+
# requiring is faster, so if config.cache_classes was true in
|
|
208
|
+
# the environment's config file, then we can respect that from
|
|
209
|
+
# here on as we no longer need constant reloading.
|
|
210
|
+
if @original_cache_classes
|
|
211
|
+
ActiveSupport::Dependencies.mechanism = :require
|
|
212
|
+
Rails.application.config.cache_classes = true
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
connect_database
|
|
216
|
+
srand
|
|
217
|
+
|
|
218
|
+
invoke_after_fork_callbacks
|
|
219
|
+
shush_backtraces
|
|
220
|
+
|
|
221
|
+
begin
|
|
222
|
+
ret = action.call(*args)
|
|
223
|
+
rescue => e
|
|
224
|
+
client.send_object({"exception" => e}, self.env)
|
|
225
|
+
else
|
|
226
|
+
client.send_object({"return" => ret}, self.env)
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
|
|
204
231
|
def terminate
|
|
205
232
|
if exiting?
|
|
206
233
|
# Ensure that we do not ignore subsequent termination attempts
|
|
@@ -283,19 +310,28 @@ module Expedite
|
|
|
283
310
|
end
|
|
284
311
|
|
|
285
312
|
def wait(pid, streams, client)
|
|
286
|
-
|
|
313
|
+
if pid != Process.pid
|
|
314
|
+
@mutex.synchronize { @waiting << pid }
|
|
315
|
+
end
|
|
287
316
|
|
|
288
317
|
# Wait in a separate thread so we can run multiple actions at once
|
|
289
318
|
Expedite.failsafe_thread {
|
|
290
319
|
begin
|
|
291
|
-
|
|
292
|
-
|
|
320
|
+
exitstatue = if pid == Process.pid
|
|
321
|
+
log "#{pid} is current process"
|
|
322
|
+
0
|
|
323
|
+
else
|
|
324
|
+
_, status = Process.wait2 pid
|
|
325
|
+
log "#{pid} exited with #{status.exitstatus}"
|
|
326
|
+
end
|
|
293
327
|
|
|
294
328
|
streams.each(&:close)
|
|
295
|
-
client.puts(
|
|
329
|
+
client.puts(exitstatus)
|
|
296
330
|
client.close
|
|
297
331
|
ensure
|
|
298
|
-
|
|
332
|
+
if pid != Process.pid
|
|
333
|
+
@mutex.synchronize { @waiting.delete pid }
|
|
334
|
+
end
|
|
299
335
|
exit_if_finished
|
|
300
336
|
end
|
|
301
337
|
}
|
|
@@ -7,6 +7,7 @@ require 'expedite/agents'
|
|
|
7
7
|
|
|
8
8
|
module Expedite
|
|
9
9
|
module Server
|
|
10
|
+
# Locates agent processes and spawns them if necessary
|
|
10
11
|
class AgentManager
|
|
11
12
|
attr_reader :pid, :child, :name, :env, :status, :agent
|
|
12
13
|
|
|
@@ -79,6 +80,10 @@ module Expedite
|
|
|
79
80
|
log "got worker pid #{pid}"
|
|
80
81
|
pid
|
|
81
82
|
end
|
|
83
|
+
rescue Exception => e
|
|
84
|
+
# NotImplementedError is an Exception, not StandardError
|
|
85
|
+
client.send_object({"exception" => e}, env)
|
|
86
|
+
return Process.pid
|
|
82
87
|
rescue Errno::ECONNRESET, Errno::EPIPE => e
|
|
83
88
|
log "#{e} while reading from child; returning no pid"
|
|
84
89
|
nil
|
|
@@ -116,6 +121,7 @@ module Expedite
|
|
|
116
121
|
end
|
|
117
122
|
end
|
|
118
123
|
|
|
124
|
+
# Creates a child that is forked from a parent
|
|
119
125
|
def fork_child(preload = false)
|
|
120
126
|
@child, child_socket = UNIXSocket.pair
|
|
121
127
|
|
|
@@ -125,42 +131,43 @@ module Expedite
|
|
|
125
131
|
wr.send_io STDERR
|
|
126
132
|
wr.send_io STDIN
|
|
127
133
|
|
|
128
|
-
wr.send_object(
|
|
134
|
+
wr.send_object({
|
|
129
135
|
'args' => ['expedite/boot', name],
|
|
130
|
-
'env' => {}
|
|
131
|
-
|
|
136
|
+
'env' => {},
|
|
137
|
+
'method' => "fork",
|
|
138
|
+
}, env)
|
|
132
139
|
|
|
133
140
|
wr.send_io child_socket
|
|
134
141
|
wr.send_io env.log_file
|
|
135
142
|
wr.close
|
|
136
143
|
|
|
137
|
-
@pid = env.applications
|
|
144
|
+
@pid = env.applications.with(parent) do |target|
|
|
145
|
+
target.run(rd)
|
|
146
|
+
end
|
|
138
147
|
|
|
139
148
|
start_wait_thread(pid, child) if child.gets
|
|
140
149
|
child_socket.close
|
|
141
150
|
end
|
|
142
151
|
|
|
152
|
+
# Creates a child that is started from scratch
|
|
143
153
|
def spawn_child(preload = false)
|
|
144
154
|
@child, child_socket = UNIXSocket.pair
|
|
145
155
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
4 => env.log_file,
|
|
160
|
-
)
|
|
161
|
-
end
|
|
156
|
+
bundler_dir = File.expand_path("../..", $LOADED_FEATURES.grep(/bundler\/setup\.rb$/).first)
|
|
157
|
+
@pid = Process.spawn(
|
|
158
|
+
{
|
|
159
|
+
"EXPEDITE_VARIANT" => name,
|
|
160
|
+
"EXPEDITE_ROOT" => env.root,
|
|
161
|
+
},
|
|
162
|
+
"ruby",
|
|
163
|
+
*(bundler_dir != RbConfig::CONFIG["rubylibdir"] ? ["-I", bundler_dir] : []),
|
|
164
|
+
"-I", File.expand_path("../../..", __FILE__),
|
|
165
|
+
"-e", "require 'expedite/server/agent_boot'",
|
|
166
|
+
3 => child_socket,
|
|
167
|
+
4 => env.log_file,
|
|
168
|
+
)
|
|
162
169
|
|
|
163
|
-
start_wait_thread(pid, child) if child.gets
|
|
170
|
+
start_wait_thread(@pid, child) if child.gets
|
|
164
171
|
child_socket.close
|
|
165
172
|
end
|
|
166
173
|
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
require 'set'
|
|
2
|
+
require 'expedite/server/agent_manager'
|
|
3
|
+
|
|
4
|
+
module Expedite
|
|
5
|
+
module Server
|
|
6
|
+
class AgentPool
|
|
7
|
+
def initialize(name, env)
|
|
8
|
+
@name = name
|
|
9
|
+
@env = env
|
|
10
|
+
@checked_in = []
|
|
11
|
+
@checked_out = Set.new
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Get a free agent from the pool
|
|
15
|
+
def checkout
|
|
16
|
+
agent = @checked_in.pop
|
|
17
|
+
|
|
18
|
+
agent = build_agent if agent.nil?
|
|
19
|
+
@checked_out.add(agent)
|
|
20
|
+
|
|
21
|
+
agent
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def checkin(agent)
|
|
25
|
+
@checked_out.delete(agent)
|
|
26
|
+
@checked_in.push(agent)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def build_agent
|
|
30
|
+
Server::AgentManager.new(@name, @env)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Returns all agents, both checked in and checked out
|
|
34
|
+
def all
|
|
35
|
+
@checked_in + @checked_out.to_a
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require 'expedite/server/agent_pool'
|
|
2
|
+
|
|
3
|
+
module Expedite
|
|
4
|
+
module Server
|
|
5
|
+
class ApplicationManager
|
|
6
|
+
attr_reader :pools
|
|
7
|
+
|
|
8
|
+
def initialize(env)
|
|
9
|
+
@env = env
|
|
10
|
+
@pools = Hash.new do |h, k|
|
|
11
|
+
h[k] = AgentPool.new(k, @env)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def with(name)
|
|
16
|
+
pool = @pools[name]
|
|
17
|
+
target = pool.checkout
|
|
18
|
+
begin
|
|
19
|
+
ret = yield target
|
|
20
|
+
ensure
|
|
21
|
+
pool.checkin(target)
|
|
22
|
+
end
|
|
23
|
+
ret
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -97,42 +97,69 @@ module Expedite
|
|
|
97
97
|
log "accepted client"
|
|
98
98
|
client.puts env.version
|
|
99
99
|
|
|
100
|
+
# Corresponds to Client::Invoke#connect_to_agent
|
|
100
101
|
app_client = client.recv_io
|
|
101
102
|
command = client.recv_object
|
|
102
103
|
|
|
103
|
-
args, agent = command.values_at(
|
|
104
|
+
args, agent = command.values_at("args", "agent")
|
|
104
105
|
cmd = args.first
|
|
105
106
|
|
|
106
|
-
if agent ==
|
|
107
|
+
if agent == "__server__"
|
|
107
108
|
case cmd
|
|
108
|
-
when
|
|
109
|
+
when "application_pids"
|
|
110
|
+
# Corresponds to Client::Invoke#run_command
|
|
109
111
|
client.puts
|
|
112
|
+
|
|
110
113
|
unix_socket = UNIXSocket.for_fd(app_client.fileno)
|
|
111
|
-
_stdout
|
|
112
|
-
|
|
113
|
-
|
|
114
|
+
_stdout = unix_socket.recv_io
|
|
115
|
+
_stderr = unix_socket.recv_io
|
|
116
|
+
_stdin = unix_socket.recv_io
|
|
117
|
+
|
|
114
118
|
client.puts Process.pid
|
|
115
119
|
|
|
116
120
|
application_pids = []
|
|
117
|
-
env.applications.each do |k,
|
|
118
|
-
application_pids
|
|
121
|
+
env.applications.pools.each do |k, pool|
|
|
122
|
+
application_pids.concat(pool.all.map(&:pid))
|
|
119
123
|
end
|
|
120
|
-
unix_socket.send_object("return" => application_pids)
|
|
124
|
+
unix_socket.send_object({"return" => application_pids}, env)
|
|
121
125
|
|
|
122
126
|
unix_socket.close
|
|
123
127
|
client.close
|
|
124
128
|
else
|
|
125
129
|
end
|
|
126
130
|
elsif Expedite::Actions.lookup(cmd)
|
|
131
|
+
# Corresponds to Client::Invoke#run_command
|
|
127
132
|
log "running command #{cmd}: #{args}"
|
|
133
|
+
|
|
128
134
|
client.puts
|
|
129
135
|
|
|
130
|
-
|
|
131
|
-
|
|
136
|
+
begin
|
|
137
|
+
env.applications.with(agent) do |target|
|
|
138
|
+
client.puts target.run(app_client)
|
|
139
|
+
end
|
|
140
|
+
rescue AgentNotFoundError => e
|
|
141
|
+
unix_socket = UNIXSocket.for_fd(app_client.fileno)
|
|
142
|
+
_stdout = unix_socket.recv_io
|
|
143
|
+
_stderr = unix_socket.recv_io
|
|
144
|
+
_stdin = unix_socket.recv_io
|
|
145
|
+
|
|
146
|
+
args, env = unix_socket.recv_object.values_at("args", "env")
|
|
147
|
+
|
|
148
|
+
client.puts Process.pid
|
|
149
|
+
|
|
150
|
+
# boot only
|
|
151
|
+
#@child_socket = client.recv_io
|
|
152
|
+
#@log_file = client.recv_io
|
|
153
|
+
unix_socket.send_object({"exception" => e}, env)
|
|
154
|
+
|
|
155
|
+
unix_socket.close
|
|
156
|
+
client.close
|
|
157
|
+
end
|
|
132
158
|
else
|
|
133
159
|
log "command not found #{cmd}"
|
|
134
160
|
client.close
|
|
135
161
|
end
|
|
162
|
+
rescue AgentNotFoundError => e
|
|
136
163
|
rescue SocketError => e
|
|
137
164
|
raise e unless client.eof?
|
|
138
165
|
ensure
|
|
@@ -168,7 +195,13 @@ module Expedite
|
|
|
168
195
|
end
|
|
169
196
|
end
|
|
170
197
|
|
|
171
|
-
|
|
198
|
+
thrs = []
|
|
199
|
+
env.applications.pools.each do |k, pool|
|
|
200
|
+
pool.all.each do |a|
|
|
201
|
+
thrs << Expedite.failsafe_thread { a.stop }
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
thrs.map(&:join)
|
|
172
205
|
end
|
|
173
206
|
|
|
174
207
|
def write_pidfile
|
|
@@ -201,11 +234,20 @@ module Expedite
|
|
|
201
234
|
|
|
202
235
|
def default_log_file
|
|
203
236
|
if foreground? && !ENV["SPRING_LOG"]
|
|
204
|
-
$
|
|
237
|
+
$stderr
|
|
205
238
|
else
|
|
206
239
|
nil
|
|
207
240
|
end
|
|
208
241
|
end
|
|
242
|
+
|
|
243
|
+
# Server command
|
|
244
|
+
def application_pids
|
|
245
|
+
pids = []
|
|
246
|
+
env.applications.each do |k, v|
|
|
247
|
+
pids << v.pid if v.pid
|
|
248
|
+
end
|
|
249
|
+
return pids
|
|
250
|
+
end
|
|
209
251
|
end
|
|
210
252
|
end
|
|
211
253
|
end
|
data/lib/expedite/version.rb
CHANGED
data/lib/expedite.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: expedite
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Bing-Chang Lai
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2022-12-
|
|
11
|
+
date: 2022-12-16 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: Manages Ruby processes that can be used to spawn child processes faster.
|
|
14
14
|
email: johnny.lai@me.com
|
|
@@ -25,6 +25,7 @@ files:
|
|
|
25
25
|
- lib/expedite/actions.rb
|
|
26
26
|
- lib/expedite/agents.rb
|
|
27
27
|
- lib/expedite/cli.rb
|
|
28
|
+
- lib/expedite/cli/rails.rb
|
|
28
29
|
- lib/expedite/cli/server.rb
|
|
29
30
|
- lib/expedite/cli/status.rb
|
|
30
31
|
- lib/expedite/cli/stop.rb
|
|
@@ -33,10 +34,13 @@ files:
|
|
|
33
34
|
- lib/expedite/env.rb
|
|
34
35
|
- lib/expedite/errors.rb
|
|
35
36
|
- lib/expedite/failsafe_thread.rb
|
|
37
|
+
- lib/expedite/helper/rails.rb
|
|
36
38
|
- lib/expedite/protocol.rb
|
|
37
39
|
- lib/expedite/server/agent.rb
|
|
38
40
|
- lib/expedite/server/agent_boot.rb
|
|
39
41
|
- lib/expedite/server/agent_manager.rb
|
|
42
|
+
- lib/expedite/server/agent_pool.rb
|
|
43
|
+
- lib/expedite/server/application_manager.rb
|
|
40
44
|
- lib/expedite/server/controller.rb
|
|
41
45
|
- lib/expedite/signals.rb
|
|
42
46
|
- lib/expedite/syntax.rb
|