class ProcessSettings::FileMonitor

Attributes

file_path[R]
untargeted_settings[R]

Public Class Methods

new(file_path, logger:, environment: nil) click to toggle source
Calls superclass method ProcessSettings::AbstractMonitor::new
# File lib/process_settings/file_monitor.rb, line 17
def initialize(file_path, logger:, environment: nil)
  super(logger: logger)

  @file_path = File.expand_path(file_path)
  @last_statically_targetted_settings = nil
  @untargeted_settings = nil
  @last_untargetted_settings = nil

  start_internal(enable_listen_thread?(environment))
end

Public Instance Methods

listen_thread_running?() click to toggle source
# File lib/process_settings/file_monitor.rb, line 55
def listen_thread_running?
  !@listener.nil?
end
restart_after_fork() click to toggle source
# File lib/process_settings/file_monitor.rb, line 51
def restart_after_fork
  start_internal(enable_listen_thread?)
end
start() click to toggle source
# File lib/process_settings/file_monitor.rb, line 46
def start
  start_internal(enable_listen_thread?)
end
start_watchdog_thread(file_path) click to toggle source
# File lib/process_settings/file_monitor.rb, line 28
def start_watchdog_thread(file_path)
  @watchdog_thread and raise ArgumentError, "watchdog thread already running!"
  @watchdog_thread = Thread.new do
    watchdog = Watchdog.new(file_path)
    loop do
      sleep(1.minute)
      watchdog.check
    rescue => ex
      logger.error("ProcessSettings::Watchdog thread: #{ex.class.name}: #{ex.message}")
    end
  end
end
stop_watchdog_thread() click to toggle source
# File lib/process_settings/file_monitor.rb, line 41
def stop_watchdog_thread
  @watchdog_thread&.kill
  @watchdog_thread = nil
end

Private Instance Methods

disable_listen_thread?(environment = nil) click to toggle source
# File lib/process_settings/file_monitor.rb, line 65
def disable_listen_thread?(environment = nil)
  case ENV['DISABLE_LISTEN_CHANGE_MONITORING']
  when 'true', '1'
    true
  when 'false', '0'
    false
  when nil
    (environment || service_env) == 'test'
  else
    raise ArgumentError, "DISABLE_LISTEN_CHANGE_MONITORING has unknown value #{ENV['DISABLE_LISTEN_CHANGE_MONITORING'].inspect}"
  end
end
enable_listen_thread?(environment = nil) click to toggle source
# File lib/process_settings/file_monitor.rb, line 61
def enable_listen_thread?(environment = nil)
  !disable_listen_thread?(environment)
end
file_change_notifier() click to toggle source
# File lib/process_settings/file_monitor.rb, line 150
def file_change_notifier
  Listen
end
load_file(file_path) click to toggle source
# File lib/process_settings/file_monitor.rb, line 146
def load_file(file_path)
  TargetedSettings.from_file(file_path)
end
load_statically_targeted_settings(force_retarget: false) click to toggle source

Loads the latest untargeted settings from disk. Returns the current process settings as a TargetAndProcessSettings given by applying the static context to the current untargeted settings from disk. If these have changed, borrows this thread to call notify_on_change and call_when_updated_blocks.

# File lib/process_settings/file_monitor.rb, line 133
def load_statically_targeted_settings(force_retarget: false)
  if force_retarget || @last_untargetted_settings != @untargeted_settings
    @last_untargetted_settings = @untargeted_settings
    @statically_targeted_settings = @untargeted_settings.with_static_context(@static_context)
    if @last_statically_targetted_settings != @statically_targeted_settings
      @last_statically_targetted_settings = @statically_targeted_settings

      notify_on_change
      call_when_updated_blocks
    end
  end
end
load_untargeted_settings() click to toggle source

Loads the most recent settings from disk

# File lib/process_settings/file_monitor.rb, line 122
def load_untargeted_settings
  new_untargeted_settings = load_file(file_path)
  old_version = @untargeted_settings&.version
  new_version = new_untargeted_settings.version
  @untargeted_settings = new_untargeted_settings
  logger.info("ProcessSettings::Monitor#load_untargeted_settings loaded version #{new_version}#{" to replace version #{old_version}" if old_version}")
end
service_env() click to toggle source
# File lib/process_settings/file_monitor.rb, line 115
def service_env
  if defined?(Rails) && Rails.respond_to?(:env)
    Rails.env
  end || ENV['RAILS_ENV'] || ENV['SERVICE_ENV']
end
start_internal(with_listen_thread) click to toggle source

optionally starts listening for changes, then loads current settings Note: If with_listen_thread is truthy, this method creates a new thread that will be

monitoring for changes.
Due to how the Listen gem works, there is no record of
existing threads; calling this multiple times will result in spinning off
multiple listen threads and will have unknown effects.
# File lib/process_settings/file_monitor.rb, line 84
def start_internal(with_listen_thread)
  if with_listen_thread
    path = File.dirname(file_path)

    # to eliminate any race condition:
    # 1. set up file watcher
    # 2. start it (this should trigger if any changes have been made since (1))
    # 3. load the file

    @listener = file_change_notifier.to(path) do |modified, added, _removed|
      if modified.include?(file_path) || added.include?(file_path)
        logger.info("ProcessSettings::Monitor file #{file_path} changed. Reloading.")
        load_untargeted_settings

        load_statically_targeted_settings
      end
    end

    @listener.start
  end

  load_untargeted_settings
  load_statically_targeted_settings
end
stop() click to toggle source

stops listening for changes

# File lib/process_settings/file_monitor.rb, line 110
def stop
  @listener&.stop
  @listener = nil
end