class MiGA::Lair

Lair of MiGA Daemons handling job submissions

Attributes

daemon_home[R]

Absolute path to the directory where the projects are located

options[RW]

Options used to setup the chief daemon

path[R]

Absolute path to the directory where the projects are located

Public Class Methods

new(path, opts = {}) click to toggle source

Initialize an inactive daemon for the directory at path. See daemon to wake the chief daemon. Supported options include:

  • json: json definition for all children daemons, by default: nil

  • latency: time to wait between iterations in seconds, by default: 120

  • wait_for: time to wait for a daemon to report being alive in seconds, by default: 30

  • keep_inactive: boolean indicating if daemons should stay alive even when inactive (when all tasks are complete), by default: false

  • name: A name for the chief daemon process, by default: basename of path

  • trust_timestamp: boolean indicating if the modified timestamp of the project is to be trusted to determine changes in the project, by default: true

  • dry: Only report when daemons would be launched, but don't actually launch them

  • exclude: Array of project names to be excluded from the lair

# File lib/miga/lair.rb, line 35
def initialize(path, opts = {})
  @path = File.expand_path(path)
  @options = opts
  {
    json: nil,
    latency: 30,
    wait_for: 30,
    keep_inactive: false,
    trust_timestamp: true,
    name: File.basename(@path),
    dry: false,
    exclude: []
  }.each { |k, v| @options[k] = v if @options[k].nil? }
end

Public Instance Methods

check_directories() click to toggle source

Traverse directories checking MiGA projects

# File lib/miga/lair.rb, line 137
def check_directories
  each_project do |project|
    d = project_daemon(project)
    next if d.active?

    l_alive = d.last_alive
    unless l_alive.nil?
      next if options[:trust_timestamp] && project.metadata.updated < l_alive
      next if l_alive > Time.now - options[:wait_for]
    end
    launch_daemon(project)
  end
end
daemon_first_loop() click to toggle source

First loop of the lair's chief daemon

# File lib/miga/lair.rb, line 68
def daemon_first_loop
  say '-----------------------------------'
  say '%s launched' % daemon_name
  say '-----------------------------------'
  say 'Configuration options:'
  say options.to_s
end
daemon_loop() click to toggle source

Run one loop step. Returns a Boolean indicating if the loop should continue.

# File lib/miga/lair.rb, line 78
def daemon_loop
  check_directories
  return false if options[:dry]

  sleep(options[:latency])
  true
end
daemon_name() click to toggle source

Name of the lair's chief daemon

# File lib/miga/lair.rb, line 56
def daemon_name
  "MiGA:#{options[:name]}"
end
each_daemon(include_self = true) { |self| ... } click to toggle source

Perform block for each daemon, including the chief daemon if include_self.

# File lib/miga/lair.rb, line 130
def each_daemon(include_self = true)
  yield(self) if include_self
  each_project { |project| yield(project_daemon(project)) }
end
each_project(dir = path) { |project| ... } click to toggle source

Perform block for each project in the dir directory, passing the absolute path of the project to the block. Searches for MiGA projects recursively in all subdirectories that are not MiGA projects.

# File lib/miga/lair.rb, line 111
def each_project(dir = path)
  Dir.entries(dir).each do |f|
    next if %w[. ..].include?(f) # Ruby <= 2.3 doesn't have Dir.children

    f = File.join(dir, f)
    if MiGA::Project.exist? f
      project = MiGA::Project.load(f)
      raise "Cannot load project: #{f}" if project.nil?

      yield(project) unless options[:exclude].include?(project.name)
    elsif Dir.exist? f
      each_project(f) { |p| yield(p) }
    end
  end
end
launch_daemon(project) click to toggle source

Launch daemon for the MiGA::Project project and returns the corresponding MiGA::Daemon object

# File lib/miga/lair.rb, line 154
def launch_daemon(project)
  say "Launching daemon: #{project.path}"
  daemon = project_daemon(project)
  daemon.runopts(:shutdown_when_done, true) unless options[:keep_inactive]
  unless options[:dry]
    daemon.start
    sleep(1) # <- to make sure the daemon started up (it takes about 0.1 secs)
  end
  daemon
end
project_daemon(project) click to toggle source

Return the daemon of project, a MiGA::Project object

# File lib/miga/lair.rb, line 62
def project_daemon(project)
  MiGA::Daemon.new(project, options[:json])
end
terminate_daemon(daemon) click to toggle source

Send termination message to daemon, an object implementing +MiGA::Common::WithDaemon+

# File lib/miga/lair.rb, line 98
def terminate_daemon(daemon)
  say "Probing #{daemon.class} #{daemon.daemon_home}"
  if daemon.active?
    say 'Sending termination message'
    FileUtils.touch(daemon.terminate_file)
  end
end
terminate_daemons() click to toggle source

Terminate all daemons in the lair (including the chief daemon)

# File lib/miga/lair.rb, line 88
def terminate_daemons
  terminate_daemon(self)
  each_project do |project|
    terminate_daemon(MiGA::Daemon.new(project))
  end
end