lib/einhorn/command/interface.rb in einhorn-0.3.2 vs lib/einhorn/command/interface.rb in einhorn-0.4.0
- old
+ new
@@ -146,34 +146,34 @@
end
## Signals
def self.install_handlers
Signal.trap("INT") do
- Einhorn::Command.signal_all("USR2", Einhorn::State.children.keys)
+ Einhorn::Command.signal_all("USR2", Einhorn::WorkerPool.workers)
Einhorn::State.respawn = false
end
Signal.trap("TERM") do
- Einhorn::Command.signal_all("TERM", Einhorn::State.children.keys)
+ Einhorn::Command.signal_all("TERM", Einhorn::WorkerPool.workers)
Einhorn::State.respawn = false
end
# Note that quit is a bit different, in that it will actually
# make Einhorn quit without waiting for children to exit.
Signal.trap("QUIT") do
- Einhorn::Command.signal_all("QUIT", Einhorn::State.children.keys)
+ Einhorn::Command.signal_all("QUIT", Einhorn::WorkerPool.workers)
Einhorn::State.respawn = false
exit(1)
end
Signal.trap("HUP") {Einhorn::Command.reload}
Signal.trap("ALRM") {Einhorn::Command.full_upgrade}
Signal.trap("CHLD") {Einhorn::Event.break_loop}
Signal.trap("USR2") do
- Einhorn::Command.signal_all("USR2", Einhorn::State.children.keys)
+ Einhorn::Command.signal_all("USR2", Einhorn::WorkerPool.workers)
Einhorn::State.respawn = false
end
at_exit do
if Einhorn::State.kill_children_on_exit && Einhorn::TransientState.whatami == :master
- Einhorn::Command.signal_all("USR2", Einhorn::State.children.keys)
+ Einhorn::Command.signal_all("USR2", Einhorn::WorkerPool.workers)
Einhorn::State.respawn = false
end
end
end
@@ -199,18 +199,17 @@
def self.send_message(conn, response)
if response.kind_of?(String)
response = {'message' => response}
end
- message = pack_message(response)
- conn.write(message)
+ Einhorn::Client::Transport.send_message(conn, response)
end
def self.generate_response(conn, command)
begin
- request = JSON.parse(command)
- rescue JSON::ParserError => e
+ request = Einhorn::Client::Transport.deserialize_message(command)
+ rescue ArgumentError => e
return {
'message' => "Could not parse command: #{e}"
}
end
@@ -233,21 +232,10 @@
conn.log_debug("Received unrecognized command: #{command.inspect}")
return unrecognized_command(conn, request)
end
end
- def self.pack_message(message_struct)
- begin
- JSON.generate(message_struct) + "\n"
- rescue JSON::GeneratorError => e
- response = {
- 'message' => "Error generating JSON message for #{message_struct.inspect} (this indicates a bug): #{e}"
- }
- JSON.generate(response) + "\n"
- end
- end
-
def self.command_descriptions
command_specs = @@commands.select do |_, spec|
spec[:description]
end.sort_by {|name, _| name}
@@ -289,11 +277,11 @@
#{command_descriptions}
"
end
command 'state', "Get a dump of Einhorn's current state" do
- Einhorn::Command.dumpable_state.pretty_inspect
+ YAML.dump(Einhorn::Command.dumpable_state)
end
command 'reload', 'Reload Einhorn' do |conn, _|
# TODO: make reload actually work (command socket reopening is
# an issue). Would also be nice if user got a confirmation that
@@ -329,8 +317,77 @@
# TODO: send confirmation when this is done
send_message(conn, 'Upgrading, as commanded')
# This or may not return
Einhorn::Command.full_upgrade
nil
+ end
+
+ command 'signal', 'Send one or more signals to all workers (args: SIG1 [SIG2 ...])' do |conn, request|
+ args = request['args']
+ if message = validate_args(args)
+ next message
+ end
+
+ args = normalize_signals(args)
+
+ if message = validate_signals(args)
+ next message
+ end
+
+ results = args.map do |signal|
+ Einhorn::Command.signal_all(signal, nil, false)
+ end
+
+ results.join("\n")
+ end
+
+ command 'die', 'Send SIGNAL (default: SIGUSR2) to all workers, stop spawning new ones, and exit once all workers die (args: [SIGNAL])' do |conn, request|
+ # TODO: dedup this code with signal
+ args = request['args']
+ if message = validate_args(args)
+ next message
+ end
+
+ args = normalize_signals(args)
+
+ if message = validate_signals(args)
+ next message
+ end
+
+ signal = args[0] || "USR2"
+
+ response = Einhorn::Command.signal_all(signal, Einhorn::WorkerPool.workers)
+ Einhorn::State.respawn = false
+
+ "Einhorn is going down! #{response}"
+ end
+
+ def self.validate_args(args)
+ return 'No args provided' unless args
+ return 'Args must be an array' unless args.kind_of?(Array)
+
+ args.each do |arg|
+ return "Argument is a #{arg.class}, not a string: #{arg.inspect}" unless arg.kind_of?(String)
+ end
+
+ nil
+ end
+
+ def self.validate_signals(args)
+ args.each do |signal|
+ unless Signal.list.include?(signal)
+ return "Invalid signal: #{signal.inspect}"
+ end
+ end
+
+ nil
+ end
+
+ def self.normalize_signals(args)
+ args.map do |signal|
+ signal = signal.upcase
+ signal = $1 if signal =~ /\ASIG(.*)\Z/
+ signal
+ end
end
end
end