Class: MainLoop::Dispatcher

Inherits:
Object
  • Object
show all
Includes:
MonitorMixin
Defined in:
lib/main_loop/dispatcher.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(bus, timeout: 5, logger: nil) ⇒ Dispatcher

Returns a new instance of Dispatcher.



11
12
13
14
15
16
17
18
# File 'lib/main_loop/dispatcher.rb', line 11

def initialize(bus, timeout: 5, logger: nil)
  super()
  @bus = bus
  @timeout = timeout
  @handlers = []
  @logger = logger || Logger.new(nil)
  @exit_code = 0
end

Instance Attribute Details

#busObject (readonly)

Returns the value of attribute bus.



9
10
11
# File 'lib/main_loop/dispatcher.rb', line 9

def bus
  @bus
end

#handlersObject (readonly)

Returns the value of attribute handlers.



9
10
11
# File 'lib/main_loop/dispatcher.rb', line 9

def handlers
  @handlers
end

#loggerObject (readonly)

Returns the value of attribute logger.



9
10
11
# File 'lib/main_loop/dispatcher.rb', line 9

def logger
  @logger
end

Instance Method Details

#add_handler(handler) ⇒ Object



37
38
39
40
41
42
# File 'lib/main_loop/dispatcher.rb', line 37

def add_handler(handler)
  synchronize do
    handler.term if terminating?
    handlers << handler
  end
end

#crashObject



61
62
63
64
# File 'lib/main_loop/dispatcher.rb', line 61

def crash
  @exit_code = 3
  term unless terminating?
end

#log_statusObject

:nocov:



101
102
103
104
105
106
107
# File 'lib/main_loop/dispatcher.rb', line 101

def log_status
  total = handlers.size
  running = handlers.count(&:running?)
  finihsed = handlers.count(&:finished?)
  term_text = terminating? ? 'TERM' : ''
  logger.debug("Total:#{total} Running:#{running} Finihsed:#{finihsed}. #{term_text}".strip)
end

#need_force_kill?Boolean

Returns:

  • (Boolean)


79
80
81
# File 'lib/main_loop/dispatcher.rb', line 79

def need_force_kill?
  @terminating_at && (Time.now - @terminating_at) >= @timeout
end

#pidsObject



83
84
85
# File 'lib/main_loop/dispatcher.rb', line 83

def pids
  handlers.map{|h| h.pid rescue nil }.compact
end

#reap(statuses) ⇒ Object



20
21
22
23
24
# File 'lib/main_loop/dispatcher.rb', line 20

def reap(statuses)
  statuses.each do |(pid, status)|
    reap_by_id(pid, status)
  end
end

#reap_by_id(id, status) ⇒ Object



26
27
28
29
30
31
32
33
34
35
# File 'lib/main_loop/dispatcher.rb', line 26

def reap_by_id(id, status)
  synchronize do
    if (handler = handlers.find {|h| h.id == id })
      logger.info("Reap handler #{handler.name.inspect}. Status: #{status.inspect}")
      handler.reap(status)
    else
      logger.debug("Reap unknown handler. Status: #{status.inspect}. Skipped")
    end
  end
end

#termObject



48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/main_loop/dispatcher.rb', line 48

def term
  synchronize do
    if terminating?
      logger.info('Terminate FORCE all handlers')
      handlers.each(&:kill)
    else
      @terminating_at ||= Time.now
      logger.info('Terminate all handlers')
      handlers.each(&:term)
    end
  end
end

#terminating?Boolean

Returns:

  • (Boolean)


44
45
46
# File 'lib/main_loop/dispatcher.rb', line 44

def terminating?
  @terminating_at
end

#tickObject



66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/main_loop/dispatcher.rb', line 66

def tick
  log_status if logger.debug?
  return unless terminating?

  try_exit!

  return if @killed || !need_force_kill?

  @killed = true
  logger.info('Killing all handlers by timeout')
  handlers.each(&:kill)
end

#try_exit!Object

:nocov:



88
89
90
91
92
93
94
95
96
97
# File 'lib/main_loop/dispatcher.rb', line 88

def try_exit!
  synchronize do
    return unless handlers.all?(&:finished?)

    logger.info('All handlers finished exiting...')
    status = handlers.all?(&:success?) ? @exit_code : 1
    logger.info("Exit: #{status}")
    exit status
  end
end