Class: Pione::Command::Spawner

Inherits:
Object
  • Object
show all
Defined in:
lib/pione/command/spawner.rb

Overview

Spawner is a utility class for calling pione commands as different process. We assume both caller and callee commands have front server.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model, name) ⇒ Spawner

Returns a new instance of Spawner.



10
11
12
13
14
# 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

Instance Attribute Details

#child_frontObject (readonly)

front URI of spawned child process



7
8
9
# File 'lib/pione/command/spawner.rb', line 7

def child_front
  @child_front
end

#pidObject (readonly)

PID of spawned child process



6
7
8
# File 'lib/pione/command/spawner.rb', line 6

def pid
  @pid
end

#threadObject (readonly)

watch thread for spawned child process



8
9
10
# File 'lib/pione/command/spawner.rb', line 8

def thread
  @thread
end

Instance Method Details

#option(*argv) ⇒ Object

Add arguments as command arguments.



62
63
64
# File 'lib/pione/command/spawner.rb', line 62

def option(*argv)
  @argv += argv.map {|val| val.to_s}
end

#option_from(table, key, option_name, converter = nil) ⇒ void

This method returns an undefined value.

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.

Parameters:

  • table (Hash)

    value table

  • key (Symbol)

    key of the value table

  • option_name (String)

    option name



85
86
87
88
89
90
91
# 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

#option_if(cond, *args) ⇒ Object

Add arguments if the condition is true.



67
68
69
70
71
# File 'lib/pione/command/spawner.rb', line 67

def option_if(cond, *args)
  if cond
    option(*args)
  end
end

#spawnObject

Spawn the command process.



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# 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

#when_terminated(&b) ⇒ Object

Register the block that is executed when the spawned process is terminated.



94
95
96
97
98
99
# File 'lib/pione/command/spawner.rb', line 94

def when_terminated(&b)
  Thread.new do
    @thread.join
    b.call
  end
end