Class: Procodile::Supervisor

Inherits:
Object
  • Object
show all
Defined in:
lib/procodile/supervisor.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config, run_options = {}) ⇒ Supervisor

Returns a new instance of Supervisor.



9
10
11
12
13
14
15
16
17
18
19
20
# File 'lib/procodile/supervisor.rb', line 9

def initialize(config, run_options = {})
  @config = config
  @run_options = run_options
  @processes = {}
  @readers = {}
  @signal_handler = SignalHandler.new('TERM', 'USR1', 'USR2', 'INT', 'HUP')
  @signal_handler.register('TERM') { stop_supervisor }
  @signal_handler.register('INT') { stop }
  @signal_handler.register('USR1') { restart }
  @signal_handler.register('USR2') { status }
  @signal_handler.register('HUP') { reload_config }
end

Instance Attribute Details

#configObject (readonly)

Returns the value of attribute config.



6
7
8
# File 'lib/procodile/supervisor.rb', line 6

def config
  @config
end

#processesObject (readonly)

Returns the value of attribute processes.



7
8
9
# File 'lib/procodile/supervisor.rb', line 7

def processes
  @processes
end

Instance Method Details

#reload_configObject



126
127
128
129
130
# File 'lib/procodile/supervisor.rb', line 126

def reload_config
  Procodile.log nil, "system", "Reloading configuration"
  @config.reload
  check_instance_quantities
end

#restart(options = {}) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/procodile/supervisor.rb', line 70

def restart(options = {})
  @config.reload
  Array.new.tap do |instances_restarted|
    if options[:processes].nil?
      Procodile.log nil, "system", "Restarting all #{@config.app_name} processes"
      @processes.each do |_, instances|
        instances.each do |instance|
          instance.restart
          instances_restarted << instance
        end
      end
    else
      instances = process_names_to_instances(options[:processes])
      Procodile.log nil, "system", "Restarting #{instances.size} process(es)"
      instances.each do |instance|
        instance.restart
        instances_restarted << instance
      end
    end
  end
end

#start(options = {}) ⇒ Object



22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/procodile/supervisor.rb', line 22

def start(options = {})
  Procodile.log nil, "system", "#{@config.app_name} supervisor started with PID #{::Process.pid}"
  if @run_options[:brittle]
    Procodile.log nil, "system", "Running in brittle mode"
  end
  Thread.new do
    socket = ControlServer.new(self)
    socket.listen
  end
  start_processes(options[:processes])
  watch_for_output
  loop { supervise; sleep 3 }
end

#start_processes(types = []) ⇒ Object



36
37
38
39
40
41
42
43
44
45
# File 'lib/procodile/supervisor.rb', line 36

def start_processes(types = [])
  Array.new.tap do |instances_started|
    @config.processes.each do |name, process|
      next if types && !types.include?(name.to_s) # Not a process we want
      next if @processes[process] && !@processes[process].empty?   # Process type already running
      instances = start_instances(process.generate_instances)
      instances_started.push(*instances)
    end
  end
end

#stop(options = {}) ⇒ Object



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/procodile/supervisor.rb', line 47

def stop(options = {})
  Array.new.tap do |instances_stopped|
    if options[:processes].nil?
      return if @stopping
      @stopping = true
      Procodile.log nil, "system", "Stopping all #{@config.app_name} processes"
        @processes.each do |_, instances|
          instances.each do |instance|
            instance.stop
            instances_stopped << instance
          end
        end
    else
      instances = process_names_to_instances(options[:processes])
      Procodile.log nil, "system", "Stopping #{instances.size} process(es)"
      instances.each do |instance|
        instance.stop
        instances_stopped << instance
      end
    end
  end
end

#stop_supervisorObject



92
93
94
95
96
# File 'lib/procodile/supervisor.rb', line 92

def stop_supervisor
  Procodile.log nil, 'system', "Stopping #{@config.app_name} supervisor"
  FileUtils.rm_f(File.join(@config.pid_root, 'supervisor.pid'))
  ::Process.exit 0
end

#superviseObject



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/procodile/supervisor.rb', line 98

def supervise
  # Tidy up any instances that we no longer wish to be managed. They will
  # be removed from the list.
  remove_unmonitored_instances

  # Remove processes that have been stopped
  remove_stopped_instances

  # Check all instances that we manage and let them do their things.
  @processes.each do |_, instances|
    instances.each do |instance|
      instance.check
      if instance.unmonitored?
        if @run_options[:brittle]
          Procodile.log nil, "system", "Stopping everything because a process has died in brittle mode."
          return stop
        end
      end
    end
  end

  # If the processes go away, we can stop the supervisor now
  if @processes.all? { |_,instances| instances.size == 0 }
    Procodile.log nil, "system", "All processes have stopped"
    stop_supervisor
  end
end