module Katello module EventDaemon class Runner STATUS_CACHE_KEY = "katello_event_daemon_status".freeze @services = {} @cache = ActiveSupport::Cache::MemoryStore.new class << self def settings SETTINGS[:katello][:event_daemon] end def pid return unless pid_file File.read(pid_file)&.to_i rescue Errno::ENOENT nil end def pid_file pid_dir.join('katello_event_daemon.pid') end def tmp_dir Rails.root.join('tmp') end def pid_dir tmp_dir.join('pids') end def lock_file tmp_dir.join('katello_event_daemon.lock') end def write_pid_file return unless pid_file FileUtils.mkdir_p(pid_dir) File.write(pid_file, Process.pid) end def stop return unless pid == Process.pid @monitor_thread.kill @cache.clear @services.values.each(&:close) FileUtils.rm_f(pid_file) if pid_file end def start return unless runnable? FileUtils.mkdir_p(tmp_dir) FileUtils.touch(lock_file) File.open(lock_file, 'r') do |lockfile| lockfile.flock(File::LOCK_EX) return nil if started? # ensure it wasn't started while we waited for the lock start_monitor_thread write_pid_file at_exit do stop end Rails.logger.info("Katello event daemon started process=#{Process.pid}") ensure lockfile.flock(File::LOCK_UN) end end def started? Process.kill(0, pid) true rescue Errno::ESRCH, TypeError # process no longer exists or we had no PID cached false end def start_monitor_thread @monitor_thread = Thread.new do Rails.application.executor.wrap do Katello::EventDaemon::Monitor.new(@services).start end end end def runnable? # avoid accessing the disk on each request @cache.fetch('katello_event_daemon_runnable', expires_in: 1.minute) do !started? && settings[:enabled] && !::Foreman.in_rake? && !Rails.env.test? end end def register_service(name, klass) @services[name] = klass end def service_status(service_name = nil) Rails.cache.read(STATUS_CACHE_KEY)&.dig(service_name) end end end end end