Class: MiGA::Lair

Inherits:
MiGA
  • Object
show all
Extended by:
Common::WithDaemonClass
Includes:
Common::WithDaemon
Defined in:
lib/miga/lair.rb

Overview

Lair of MiGA Daemons handling job submissions

Constant Summary

Constants included from MiGA

CITATION, VERSION, VERSION_DATE, VERSION_NAME

Instance Attribute Summary collapse

Attributes included from Common::WithDaemon

#declare_alive_pid, #loop_i

Instance Method Summary collapse

Methods included from Common::WithDaemonClass

alive_file, last_alive, terminated_file

Methods included from Common::WithDaemon

#active?, #alive_file, #daemon, #declare_alive, #declare_alive_loop, #default_options, #in_loop, #last_alive, #launch_daemon_proc, #output_file, #pid_file, #process_alive?, #run, #start, #status, #stop, #terminate, #terminate_file, #terminated_file, #termination_file?, #write_alive_file

Methods inherited from MiGA

CITATION, CITATION_ARRAY, DEBUG, DEBUG_OFF, DEBUG_ON, DEBUG_TRACE_OFF, DEBUG_TRACE_ON, FULL_VERSION, LONG_VERSION, VERSION, VERSION_DATE, #advance, debug?, debug_trace?, initialized?, #like_io?, #num_suffix, rc_path, #result_files_exist?, #say

Methods included from Common::Path

#root_path, #script_path

Methods included from Common::Format

#clean_fasta_file, #seqs_length, #tabulate

Methods included from Common::Net

#download_file_ftp, #known_hosts, #remote_connection

Methods included from Common::SystemCall

#run_cmd, #run_cmd_opts

Constructor Details

#initialize(path, opts = {}) ⇒ Lair

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



35
36
37
38
39
40
41
42
43
44
45
46
47
48
# 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

Instance Attribute Details

#optionsObject

Options used to setup the chief daemon



17
18
19
# File 'lib/miga/lair.rb', line 17

def options
  @options
end

#pathObject (readonly) Also known as: daemon_home

Absolute path to the directory where the projects are located



14
15
16
# File 'lib/miga/lair.rb', line 14

def path
  @path
end

Instance Method Details

#check_directoriesObject

Traverse directories checking MiGA projects



131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/miga/lair.rb', line 131

def check_directories
  each_project do |project|
    d = MiGA::Daemon.new(project)
    next if d.active?

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

#daemon_first_loopObject

First loop of the lair’s chief daemon



62
63
64
65
66
67
68
# File 'lib/miga/lair.rb', line 62

def daemon_first_loop
  say '-----------------------------------'
  say '%s launched' % daemon_name
  say '-----------------------------------'
  say 'Configuration options:'
  say options.to_s
end

#daemon_loopObject

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



72
73
74
75
76
77
78
# File 'lib/miga/lair.rb', line 72

def daemon_loop
  check_directories
  return false if options[:dry]

  sleep(options[:latency])
  true
end

#daemon_nameObject

Name of the lair’s chief daemon



56
57
58
# File 'lib/miga/lair.rb', line 56

def daemon_name
  "MiGA:#{options[:name]}"
end

#each_daemon(include_self = true) {|_self| ... } ⇒ Object

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

Yields:

  • (_self)

Yield Parameters:

  • _self (MiGA::Lair)

    the object that the method was called on



124
125
126
127
# File 'lib/miga/lair.rb', line 124

def each_daemon(include_self = true)
  yield(self) if include_self
  each_project { |project| yield(MiGA::Daemon.new(project)) }
end

#each_project(dir = path) ⇒ Object

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.



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/miga/lair.rb', line 105

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) ⇒ Object

Launch daemon for the MiGA::Project project



147
148
149
150
151
152
153
154
155
# File 'lib/miga/lair.rb', line 147

def launch_daemon(project)
  say "Launching daemon: #{project.path}"
  d = MiGA::Daemon.new(project, options[:json])
  d.runopts(:shutdown_when_done, true) unless options[:keep_inactive]
  unless options[:dry]
    d.start
    sleep(1) # <- to make sure the daemon started up (it takes about 0.1 secs)
  end
end

#terminate_daemon(daemon) ⇒ Object

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



92
93
94
95
96
97
98
# File 'lib/miga/lair.rb', line 92

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_daemonsObject

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



82
83
84
85
86
87
# File 'lib/miga/lair.rb', line 82

def terminate_daemons
  terminate_daemon(self)
  each_project do |project|
    terminate_daemon(MiGA::Daemon.new(project))
  end
end