Class: WorkerKiller::PumaPlugin

Inherits:
Object
  • Object
show all
Includes:
Singleton
Defined in:
lib/worker_killer/puma_plugin.rb

Defined Under Namespace

Classes: PumaLogWrapper

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializePumaPlugin

Returns a new instance of PumaPlugin.



27
28
29
30
31
32
33
# File 'lib/worker_killer/puma_plugin.rb', line 27

def initialize
  @killer = ::WorkerKiller::Killer::Puma.new(worker_num: nil, puma_plugin: self)
  @worker_num = nil
  @debug = false

  @ipc_path = File.join('tmp', "puma_worker_killer_#{Process.pid}.socket")
end

Instance Attribute Details

#ipc_pathObject

Returns the value of attribute ipc_path.



25
26
27
# File 'lib/worker_killer/puma_plugin.rb', line 25

def ipc_path
  @ipc_path
end

#killerObject

Returns the value of attribute killer.



25
26
27
# File 'lib/worker_killer/puma_plugin.rb', line 25

def killer
  @killer
end

#threadObject

Returns the value of attribute thread.



25
26
27
# File 'lib/worker_killer/puma_plugin.rb', line 25

def thread
  @thread
end

Instance Method Details

#config(dsl) ⇒ Object

Этот метод зовётся при ИНИЦИАЛИЗАЦИИ плагина внути master-процесса, в самомо начале тут можно выполнить конфигурацию чегоднибудь нужного



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/worker_killer/puma_plugin.rb', line 37

def config(dsl)
  if %w[t 1].include?(ENV.fetch('WORKER_KILLER_DEBUG', 'false').to_s.downcase[0].to_s)
    @debug = true
  end

  cb = if dsl.respond_to?(:before_worker_boot)
    :before_worker_boot
  else
    # DEPRECATED
    :on_worker_boot
  end

  dsl.send(cb) do |num|
    @killer.worker_num = num
    @worker_num = num
    @tag = nil
    log "Set worker_num: #{num}"
  end
end

#debug(msg) ⇒ Object



150
151
152
153
154
155
156
157
158
# File 'lib/worker_killer/puma_plugin.rb', line 150

def debug(msg)
  return unless @debug

  if @logger
    @logger.warn("#{tag} (DEBUG) #{msg}")
  else
    warn("[#{Process.pid}] #{tag} (DEBUG) #{msg}")
  end
end

#find_worker(worker_num) ⇒ Object



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/worker_killer/puma_plugin.rb', line 118

def find_worker(worker_num)
  worker = @runner.worker_at(worker_num)
  unless worker
    log "Unknown worker index: #{worker_num.inspect}. Skipping."
    return nil
  end

  unless worker.booted?
    log "Worker #{worker_num.inspect} is not booted yet. Skipping."
    return nil
  end

  if worker.term?
    log "Worker #{worker_num.inspect} already terminating. Skipping."
    return nil
  end

  worker
end

#inhibit_restart(_worker_num) ⇒ Object

Этот метод зовётся из Middleware внтури воркера



90
91
92
# File 'lib/worker_killer/puma_plugin.rb', line 90

def inhibit_restart(_worker_num)
  nil
end

#log(msg) ⇒ Object



138
139
140
141
142
143
144
# File 'lib/worker_killer/puma_plugin.rb', line 138

def log(msg)
  if @logger
    @logger.warn("#{tag} #{msg}")
  else
    warn("[#{Process.pid}] #{tag} #{msg}")
  end
end

#release_restart(_worker_num) ⇒ Object

Этот метод зовётся из Middleware внтури воркера



95
96
97
# File 'lib/worker_killer/puma_plugin.rb', line 95

def release_restart(_worker_num)
  nil
end

#request_restart_server(worker_num) ⇒ Object

Этот метод зовётся из Middleware внтури воркера



82
83
84
85
86
87
# File 'lib/worker_killer/puma_plugin.rb', line 82

def request_restart_server(worker_num)
  log("Equeue worker #{worker_num} for restarting...")
  Socket.unix(ipc_path) do |sock|
    sock.puts Integer(worker_num).to_s
  end
end

#set_logger!(logger) ⇒ Object



77
78
79
# File 'lib/worker_killer/puma_plugin.rb', line 77

def set_logger!(logger)
  @logger = logger
end

#start(launcher) ⇒ Object

Этот метод зовётся при ИНИЦИАЛИЗАЦИИ плагина внути master-процесса, контролирующего кластер Puma псле форка данные сохранённые тут также доступны (например logger)



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/worker_killer/puma_plugin.rb', line 59

def start(launcher)
  set_logger!(PumaLogWrapper.new(launcher.log_writer))

  log "Initializing IPC: #{@ipc_path}"
  @runner = launcher.instance_variable_get('@runner')

  cb = if launcher.events.respond_to?(:after_booted)
    :after_booted
  else
    # DEPRECATED
    :on_booted
  end

  launcher.events.send(cb) do
    @thread ||= start_ipc_listener
  end
end

#start_ipc_listenerObject



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/worker_killer/puma_plugin.rb', line 99

def start_ipc_listener
  log "Start IPC listener on #{@ipc_path}"
  Thread.new do
    Socket.unix_server_loop(ipc_path) do |sock, *_args|
      if (line = sock.gets)
        worker_num = Integer(line.strip)
        if (worker = find_worker(worker_num))
          log "Killing worker #{worker_num}"
          worker.term!
        end
      end
    rescue StandardError => e
      log("Exception: #{e.inspect}")
    ensure
      sock.close
    end
  end
end

#tagObject



146
147
148
# File 'lib/worker_killer/puma_plugin.rb', line 146

def tag
  @tag ||= "[#{self.class}] #{@worker_num.nil? ? '[M]' : "[W#{@worker_num}]"}"
end