class Pione::Command::Spawner
Spawner
is a utility class for calling pione commands as different process. We assume both caller and callee commands have front server.
Attributes
Public Class Methods
# File lib/pione/command/spawner.rb, line 10 def initialize(model, name) @model = model # caller's model @name = name # callee command name @argv = [] # callee command arguments end
Public Instance Methods
Add arguments as command arguments.
# File lib/pione/command/spawner.rb, line 62 def option(*argv) @argv += argv.map {|val| val.to_s} end
Add the option name and the value as command arguments. If the value doesn’t exist in the table or the value is ‘nil`, no options are added. This is useful for the case a caller’s command option passes callee’s.
@param [Hash] table
value table
@param [Symbol] key
key of the value table
@param [String] option_name
option name
@return [void]
# File lib/pione/command/spawner.rb, line 85 def option_from(table, key, option_name, converter=nil) if table[key] val = table[key] val = converter.call(val) if converter option(option_name, val) end end
Add arguments if the condition is true.
# File lib/pione/command/spawner.rb, line 67 def option_if(cond, *args) if cond option(*args) end end
Spawn the command process.
# File lib/pione/command/spawner.rb, line 17 def spawn Log::Debug.system('process "%{name}" is spawned with arguments %{argv}' % {name: @name, argv: @argv}) # create a new process and watch it @pid = Process.spawn(@name, *@argv) # keep to watch child process @thread = Process.detach(@pid) # fail to spawn if the monitor thread is nil unless @thread return self end # find child front while child process is alive Timeout.timeout(10) do while @thread.alive? do # find front and save its uri and pid if child_front = find_child_front(@pid) @child_front = child_front return self else sleep 0.1 end end # error if the process has failed unless not(@thread.alive?) and @thread.value.success? raise SpawnError.child_process_is_dead(@model[:scenario_name], @name, @argv) end return self end rescue Timeout::Error raise SpawnError.new(@model[:scenario_name], @name, @argv, "timed out") rescue Object => e if e.kind_of?(SpawnError) raise else raise SpawnError.new(@model[:scenario_name], @name, @argv, e.message) end end
Register the block that is executed when the spawned process is terminated.
# File lib/pione/command/spawner.rb, line 94 def when_terminated(&b) Thread.new do @thread.join b.call end end
Private Instance Methods
Find child front by PID. Spawned child process sets the front server’s URI
to children table of my front, so we get it from my front and create the reference.
# File lib/pione/command/spawner.rb, line 106 def find_child_front(pid) if child_front_uri = @model[:front].child_front_uri(pid) return DRbObject.new_with_uri(child_front_uri.to_s).tap do |front| timeout(1) {front.ping} # test connection end end rescue Timeout::Error return nil end