attr_accessor :lbl
attr_accessor :proxied
+ attr_accessor :my_children
attr_accessor :unreadable_children
- def initialize proxied, label
- self.lbl = label
- self.proxied = proxied
+ def initialize proxied, label, parent
+ @lbl = label
+ @proxied = proxied
+ @parent = parent
end
def label
- self.lbl
+ @lbl
end
def uuid
get(:uuid)
end
+ def parent
+ @parent
+ end
+
def modified_by_user_uuid
get(:modified_by_user_uuid)
end
+ def owner_uuid
+ get(:owner_uuid)
+ end
+
def created_at
t = get(:created_at)
- if t.andand.class == String
- Time.parse t
- else
- t
- end
+ t = Time.parse(t) if (t.is_a? String)
+ t
end
def started_at
t = get(:started_at)
- if t.andand.class == String
- Time.parse t
- else
- t
- end
+ t = Time.parse(t) if (t.is_a? String)
+ t
+ end
+
+ def modified_at
+ t = get(:modified_at)
+ t = Time.parse(t) if (t.is_a? String)
+ t
end
def finished_at
t = get(:finished_at)
- if t.andand.class == String
- Time.parse t
- else
- t
- end
+ t = Time.parse(t) if (t.is_a? String)
+ t
end
def state_label
state = get(:state)
if ["Running", "RunningOnServer", "RunningOnClient"].include? state
"Running"
+ elsif state == 'New'
+ "Not started"
else
state
end
end
def state_bootstrap_class
- state = get(:state)
+ state = state_label
case state
when 'Complete'
'success'
end
def success?
- state = get(:state)
+ state = state_label
if state == 'Complete'
true
- elsif state == 'Failed'
+ elsif state == 'Failed' or state == 'Cancelled'
false
else
nil
end
end
- def parameters
- get(:script_parameters)
- end
+ def child_summary
+ done = 0
+ failed = 0
+ todo = 0
+ running = 0
+ children.each do |c|
+ case c.state_label
+ when 'Complete'
+ done = done+1
+ when 'Failed', 'Cancelled'
+ failed = failed+1
+ when 'Running'
+ running = running+1
+ else
+ todo = todo+1
+ end
+ end
- def repository
- get(:repository)
+ summary = {}
+ summary[:done] = done
+ summary[:failed] = failed
+ summary[:todo] = todo
+ summary[:running] = running
+ summary
end
- def script
- get(:script)
- end
+ def child_summary_str
+ summary = child_summary
+ summary_txt = ''
- def script_version
- get(:script_version)
- end
+ if state_label == 'Running'
+ done = summary[:done] || 0
+ running = summary[:running] || 0
+ failed = summary[:failed] || 0
+ todo = summary[:todo] || 0
+ total = done + running + failed + todo
- def supplied_script_version
- get(:supplied_script_version)
+ if total > 0
+ summary_txt += "#{summary[:done]} #{'child'.pluralize(summary[:done])} done,"
+ summary_txt += "#{summary[:failed]} failed,"
+ summary_txt += "#{summary[:running]} running,"
+ summary_txt += "#{summary[:todo]} pending"
+ end
+ end
+ summary_txt
end
- def runtime_constraints
- get(:runtime_constraints)
+ def progress
+ state = state_label
+ if state == 'Complete'
+ return 1.0
+ elsif state == 'Failed' or state == 'Cancelled'
+ return 0.0
+ end
+
+ summary = child_summary
+ return 0.0 if summary.nil?
+
+ done = summary[:done] || 0
+ running = summary[:running] || 0
+ failed = summary[:failed] || 0
+ todo = summary[:todo] || 0
+ total = done + running + failed + todo
+ if total > 0
+ (done+failed).to_f / total
+ else
+ 0.0
+ end
end
def children
[]
end
+ def outputs
+ []
+ end
+
def title
- "work unit"
+ "process"
end
def has_unreadable_children
- self.unreadable_children
+ @unreadable_children
+ end
+
+ def walltime
+ if state_label != "Queued"
+ if started_at
+ ((if finished_at then finished_at else Time.now() end) - started_at)
+ end
+ end
+ end
+
+ def cputime
+ if children.any?
+ children.map { |c|
+ c.cputime
+ }.reduce(:+) || 0
+ else
+ if started_at
+ (runtime_constraints.andand[:min_nodes] || 1).to_i * ((finished_at || Time.now()) - started_at)
+ else
+ 0
+ end
+ end
+ end
+
+ def queuedtime
+ if state_label == "Queued"
+ Time.now - Time.parse(created_at.to_s)
+ end
+ end
+
+ def is_running?
+ state_label == 'Running'
+ end
+
+ def is_paused?
+ state_label == 'Paused'
+ end
+
+ def is_finished?
+ state_label.in? ["Complete", "Failed", "Cancelled"]
+ end
+
+ def is_failed?
+ state_label == 'Failed'
+ end
+
+ def runtime_contributors
+ contributors = []
+ if children.any?
+ children.each{|c| contributors << c.runtime_contributors}
+ else
+ contributors << self
+ end
+ contributors.flatten
+ end
+
+ def runningtime
+ ApplicationController.helpers.determine_wallclock_runtime runtime_contributors
+ end
+
+ def show_runtime
+ walltime = 0
+ running_time = runningtime
+ if started_at
+ walltime = if finished_at then (finished_at - started_at) else (Time.now - started_at) end
+ end
+ resp = '<p>'
+
+ if started_at
+ resp << "This #{title} started at "
+ resp << ApplicationController.helpers.render_localized_date(started_at)
+ resp << ". It "
+ if state_label == 'Complete'
+ resp << "completed in "
+ elsif state_label == 'Failed'
+ resp << "failed after "
+ else
+ resp << "has been active for "
+ end
+
+ resp << ApplicationController.helpers.render_time(walltime, false)
+
+ if finished_at
+ resp << " at "
+ resp << ApplicationController.helpers.render_localized_date(finished_at)
+ end
+ resp << "."
+ else
+ if state_label
+ resp << "This #{title} is "
+ resp << if state_label == 'Running' then 'active' else state_label.downcase end
+ resp << "."
+ end
+ end
+
+ if is_failed?
+ resp << " Check the Log tab for more detail about why it failed."
+ end
+ resp << "</p>"
+
+ resp << "<p>"
+ if state_label
+ resp << "It has runtime of "
+
+ cpu_time = cputime
+
+ resp << ApplicationController.helpers.render_time(running_time, false)
+ if (walltime - running_time) > 0
+ resp << "("
+ resp << ApplicationController.helpers.render_time(walltime - running_time, false)
+ resp << "queued)"
+ end
+ if cpu_time == 0
+ resp << "."
+ else
+ resp << " and used "
+ resp << ApplicationController.helpers.render_time(cpu_time, false)
+ resp << " of node allocation time ("
+ resp << (cpu_time/running_time).round(1).to_s
+ resp << "⨯ scaling)."
+ end
+ end
+ resp << "</p>"
+
+ resp
+ end
+
+ def log_object_uuids
+ [uuid]
+ end
+
+ def live_log_lines(limit)
+ Log.where(object_uuid: log_object_uuids).
+ order("created_at DESC").
+ limit(limit).
+ with_count('none').
+ select { |log| log.properties[:text].is_a? String }.
+ reverse.
+ flat_map { |log| log.properties[:text].split("\n") }
end
protected
- def get key
- if self.proxied.respond_to? key
- self.proxied.send(key)
- elsif self.proxied.is_a?(Hash)
- self.proxied[key]
+ def get key, obj=@proxied
+ if obj.respond_to? key
+ obj.send(key)
+ elsif obj.is_a?(Hash)
+ obj[key] || obj[key.to_s]
end
end
end