# frozen_string_literal: true module PumaWorkerKiller class PumaMemory def initialize(master = nil) @master = master || get_master @workers = nil end attr_reader :master def size workers.size end def term_worker(worker) worker.term end def term_largest_worker largest_worker.term end def workers_stopped? !running? end def running? @master && workers.any? end def smallest_worker smallest, = workers.to_a.first smallest end def smallest_worker_memory _, smallest_mem = workers.to_a.first smallest_mem end def largest_worker largest_worker, = workers.to_a.last largest_worker end def largest_worker_memory _, largest_memory_used = workers.to_a.last largest_memory_used end # Will refresh @workers def get_total(workers = set_workers) master_memory = GetProcessMem.new(Process.pid).mb worker_memory = workers.values.inject(:+) || 0 worker_memory + master_memory end alias_method :get_total_memory, :get_total def workers @workers || set_workers end private def get_master ObjectSpace.each_object(Puma::Cluster).map { |obj| obj }.first if defined?(Puma::Cluster) end # Returns sorted hash, keys are worker objects, values are memory used per worker # sorted by memory ascending (smallest first, largest last) def set_workers workers = {} @master.instance_variable_get(:@workers).each do |worker| workers[worker] = GetProcessMem.new(worker.pid).mb end if workers.any? @workers = workers.sort_by { |_, mem| mem }.to_h else {} end end end end