Class: Lipsiadmin::Loops::ProcessManager

Inherits:
Object
  • Object
show all
Defined in:
lib/loops/process_manager.rb

Overview

:nodoc:

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config, logger) ⇒ ProcessManager

Returns a new instance of ProcessManager.



9
10
11
12
13
14
15
16
17
18
# File 'lib/loops/process_manager.rb', line 9

def initialize(config, logger)
  @config = {
    'poll_period' => 1,
    'workers_engine' => 'fork'
  }.merge(config)

  @logger = logger
  @worker_pools = {}
  @shutdown = false
end

Instance Attribute Details

#loggerObject (readonly)

Returns the value of attribute logger.



7
8
9
# File 'lib/loops/process_manager.rb', line 7

def logger
  @logger
end

Instance Method Details

#monitor_workersObject



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/loops/process_manager.rb', line 28

def monitor_workers
  setup_signals

  logger.debug('Starting workers monitoring code...')
  loop do
    logger.debug('Checking workers\' health...')
    @worker_pools.each do |name, pool|
      break if @shutdown
      pool.check_workers
    end

    break if @shutdown
    logger.debug("Sleeping for #{@config['poll_period']} seconds...")
    sleep(@config['poll_period'])
  end
ensure
  unless wait_for_workers(10)
    logger.debug("Some workers are still alive after 10 seconds of waiting. Killing them...")
    stop_workers(true)
    wait_for_workers(5)
  end
end

#setup_signalsObject



51
52
53
54
55
# File 'lib/loops/process_manager.rb', line 51

def setup_signals
  # Zombie rippers
  trap('CHLD') {}
  trap('EXIT') {}
end

#start_shutdownObject



95
96
97
98
# File 'lib/loops/process_manager.rb', line 95

def start_shutdown
  return false if @shutdown
  @shutdown = true
end

#start_workers(name, number, &blk) ⇒ Object



20
21
22
23
24
25
26
# File 'lib/loops/process_manager.rb', line 20

def start_workers(name, number, &blk)
  raise "Need a worker block!" unless block_given?

  logger.debug("Creating a workers pool of #{number} workers for #{name} loop...")
  @worker_pools[name] = Lipsiadmin::Loops::WorkerPool.new(name, logger, @config['workers_engine'], &blk)
  @worker_pools[name].start_workers(number)
end

#stop_workers(force = false) ⇒ Object



78
79
80
81
82
83
84
85
86
# File 'lib/loops/process_manager.rb', line 78

def stop_workers(force = false)
  return unless start_shutdown || force
  logger.debug("Stopping workers#{force ? '(forced)' : ''}...")

  # Termination loop
  @worker_pools.each do |name, pool|
    pool.stop_workers(force)
  end
end

#stop_workers!Object



88
89
90
91
92
93
# File 'lib/loops/process_manager.rb', line 88

def stop_workers!
  return unless start_shutdown
  stop_workers(false)
  sleep(1)
  stop_workers(true)
end

#wait_for_workers(seconds) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/loops/process_manager.rb', line 57

def wait_for_workers(seconds)
  seconds.times do
    logger.debug("Shutting down... waiting for workers to die (we have #{seconds} seconds)...")
    running_total = 0

    @worker_pools.each do |name, pool|
      running_total += pool.wait_workers
    end

    if running_total.zero?
      logger.debug("All workers are dead. Exiting...")
      return true
    end

    logger.debug("#{running_total} workers are still running! Sleeping for a second...")
    sleep(1)
  end

  return false
end