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

Attributes included from Common::Net

#remote_connection_uri

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, #http_request, #known_hosts, #main_server, #net_method, #normalize_encoding, #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



137
138
139
140
141
142
143
144
145
146
147
148
149
# 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..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



68
69
70
71
72
73
74
# 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_loopObject

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



78
79
80
81
82
83
84
# File 'lib/miga/lair.rb', line 78

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



130
131
132
133
# 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) ⇒ 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.



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# 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) ⇒ Object

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



154
155
156
157
158
159
160
161
162
163
# 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) ⇒ Object

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



62
63
64
# File 'lib/miga/lair.rb', line 62

def project_daemon(project)
  MiGA::Daemon.new(project, options[:json])
end

#terminate_daemon(daemon) ⇒ Object

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



98
99
100
101
102
103
104
# 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_daemonsObject

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



88
89
90
91
92
93
# 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