[ARVADOS] created: aadca3ff41a12a7a52a2a072696564b90537b9b3
git at public.curoverse.com
git at public.curoverse.com
Wed Sep 10 17:12:28 EDT 2014
at aadca3ff41a12a7a52a2a072696564b90537b9b3 (commit)
commit aadca3ff41a12a7a52a2a072696564b90537b9b3
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date: Wed Sep 10 17:12:09 2014 -0400
3187: Lots of work on presentation of job details, calculating time and
concurrency factors.
diff --git a/apps/workbench/app/controllers/jobs_controller.rb b/apps/workbench/app/controllers/jobs_controller.rb
index b3204bf..40f4378 100644
--- a/apps/workbench/app/controllers/jobs_controller.rb
+++ b/apps/workbench/app/controllers/jobs_controller.rb
@@ -36,7 +36,11 @@ class JobsController < ApplicationController
def cancel
@object.cancel
- redirect_to @object
+ if params[:return_to]
+ redirect_to params[:return_to]
+ else
+ redirect_to @object
+ end
end
def show
diff --git a/apps/workbench/app/controllers/pipeline_instances_controller.rb b/apps/workbench/app/controllers/pipeline_instances_controller.rb
index 9b31912..72af56a 100644
--- a/apps/workbench/app/controllers/pipeline_instances_controller.rb
+++ b/apps/workbench/app/controllers/pipeline_instances_controller.rb
@@ -5,7 +5,40 @@ class PipelineInstancesController < ApplicationController
include PipelineComponentsHelper
def copy
- @object = @object.dup
+ template = PipelineTemplate.find?(@object.pipeline_template_uuid)
+
+ source = @object
+ @object = PipelineInstance.new
+ @object.pipeline_template_uuid = source.pipeline_template_uuid
+
+ if params['components'] == 'use_latest' and template
+ @object.components = template.components.deep_dup
+ @object.components.each do |cname, component|
+ # Go through the script parameters of each component
+ # that are marked as user input and copy them over.
+ component[:script_parameters].each do |pname, val|
+ if val.is_a? Hash and val[:dataclass]
+ # this is user-inputtable, so check the value from the source pipeline
+ srcvalue = source.components[cname][:script_parameters][pname]
+ if not srcvalue.nil?
+ component[:script_parameters][pname] = srcvalue
+ end
+ end
+ end
+ end
+ else
+ @object.components = source.components.deep_dup
+ end
+
+ if params['script'] == 'use_same'
+ # Go through each component and copy the script_version from each job.
+ @object.components.each do |cname, component|
+ if source.components['cname'][:job]
+ component.script_version = source.components[cname][:job].script_version
+ end
+ end
+ end
+
@object.components.each do |cname, component|
component.delete :job
end
diff --git a/apps/workbench/app/helpers/jobs_helper.rb b/apps/workbench/app/helpers/jobs_helper.rb
index 60268cb..06c3d0d 100644
--- a/apps/workbench/app/helpers/jobs_helper.rb
+++ b/apps/workbench/app/helpers/jobs_helper.rb
@@ -18,4 +18,5 @@ module JobsHelper
end
return results
end
+
end
diff --git a/apps/workbench/app/helpers/pipeline_components_helper.rb b/apps/workbench/app/helpers/pipeline_components_helper.rb
index 7584011..28adfa9 100644
--- a/apps/workbench/app/helpers/pipeline_components_helper.rb
+++ b/apps/workbench/app/helpers/pipeline_components_helper.rb
@@ -4,6 +4,7 @@ module PipelineComponentsHelper
render(partial: "pipeline_instances/show_components_#{template_suffix}",
locals: locals)
rescue Exception => e
+ logger.error "#{e.inspect}"
logger.error "#{e.backtrace.join("\n\t")}"
case fallback
when :json
diff --git a/apps/workbench/app/helpers/pipeline_instances_helper.rb b/apps/workbench/app/helpers/pipeline_instances_helper.rb
index b6df82f..d2b3a85 100644
--- a/apps/workbench/app/helpers/pipeline_instances_helper.rb
+++ b/apps/workbench/app/helpers/pipeline_instances_helper.rb
@@ -94,10 +94,13 @@ module PipelineInstancesHelper
pj[:result] = 'none'
pj[:labeltype] = 'default'
end
+
pj[:job_id] = pj[:job][:uuid]
pj[:script] = pj[:job][:script] || c[:script]
+ pj[:repository] = pj[:job][:script] || c[:repository]
pj[:script_parameters] = pj[:job][:script_parameters] || c[:script_parameters]
pj[:script_version] = pj[:job][:script_version] || c[:script_version]
+ pj[:nondeterministic] = pj[:job][:nondeterministic] || c[:nondeterministic]
pj[:output] = pj[:job][:output]
pj[:output_uuid] = c[:output_uuid]
pj[:finished_at] = (Time.parse(pj[:job][:finished_at]) rescue nil)
@@ -153,4 +156,33 @@ module PipelineInstancesHelper
end
ret
end
+
+ def runtime duration, long
+ hours = 0
+ minutes = 0
+ seconds = 0
+ if duration >= 3600
+ hours = (duration / 3600).floor
+ duration -= hours * 3600
+ end
+ if duration >= 60
+ minutes = (duration / 60).floor
+ duration -= minutes * 60
+ end
+ duration = duration.floor
+
+ if long
+ s = ""
+ if hours > 0 then
+ s += "#{hours} hour#{'s' if hours != 1} "
+ end
+ if minutes > 0 then
+ s += "#{minutes} minute#{'s' if minutes != 1} "
+ end
+ s += "#{duration} second#{'s' if duration != 1}"
+ else
+ s = "#{hours}:#{minutes.to_s.rjust(2, '0')}:#{duration.to_s.rjust(2, '0')}"
+ end
+ s
+ end
end
diff --git a/apps/workbench/app/models/job.rb b/apps/workbench/app/models/job.rb
index aac6168..309cade 100644
--- a/apps/workbench/app/models/job.rb
+++ b/apps/workbench/app/models/job.rb
@@ -33,4 +33,25 @@ class Job < ArvadosBase
def cancel
arvados_api_client.api "jobs/#{self.uuid}/", "cancel", {}
end
+
+ def state
+ Job::state(self)
+ end
+
+ def self.state job
+ if not job[:cancelled_at].nil?
+ "Canceled"
+ elsif not job[:finished_at].nil? or not job[:success].nil?
+ if job[:success]
+ "Completed"
+ else
+ "Failed"
+ end
+ elsif job[:running]
+ "Running"
+ else
+ "Queued"
+ end
+ end
+
end
diff --git a/apps/workbench/app/views/application/_job_status_label.html.erb b/apps/workbench/app/views/application/_job_status_label.html.erb
index ae00e3a..c6ab8e4 100644
--- a/apps/workbench/app/views/application/_job_status_label.html.erb
+++ b/apps/workbench/app/views/application/_job_status_label.html.erb
@@ -1,13 +1,11 @@
-<% if j[:success] %>
- <span class="label label-success"><%= if defined? title then title else 'success' end %></span>
-<% elsif j[:success] == false %>
- <span class="label label-danger"><%= if defined? title then title else 'failed' end %></span>
-<% elsif j[:finished_at] %>
- <span class="label label-default"><%= if defined? title then title else 'finished' end %></span>
-<% elsif j[:started_at] %>
- <span class="label label-info"><%= if defined? title then title else 'running' end %></span>
-<% elsif not j.nil? %>
- <span class="label label-default"><%= if defined? title then title else 'queued' end %></span>
-<% else %>
- <span class="label label-default"><%= if defined? title then title else 'not ready' end %></span>
-<% end %>
+<% status = Job.state j %>
+<% to_label = {
+ "Canceled" => "danger",
+ "Completed" => "success",
+ "Running" => "info",
+ "Failed" => "danger",
+ "Queued" => "default",
+ nil => "default"
+ } %>
+
+ <span class="label label-<%= to_label[status] %>"><%= if defined? title then title else status.downcase end %></span>
diff --git a/apps/workbench/app/views/application/_show_advanced.html.erb b/apps/workbench/app/views/application/_show_advanced.html.erb
index e8474f6..70dd96b 100644
--- a/apps/workbench/app/views/application/_show_advanced.html.erb
+++ b/apps/workbench/app/views/application/_show_advanced.html.erb
@@ -1,9 +1,9 @@
<div class="panel-group" id="arv-adv-accordion">
- <% ['Metadata',
- 'API response',
- 'Python example',
- 'CLI example',
- 'curl example'].each do |section| %>
+ <% ['API response',
+ 'Metadata',
+ 'Python example',
+ 'CLI example',
+ 'curl example'].each do |section| %>
<% section_id = section.gsub(" ","_").downcase %>
<div class="panel panel-default">
<div class="panel-heading">
@@ -13,7 +13,7 @@
</a>
</h4>
</div>
- <div id="advanced_<%=section_id%>" class="panel-collapse collapse">
+ <div id="advanced_<%=section_id%>" class="panel-collapse collapse <%#= 'in' if section == 'API response'%>">
<div class="panel-body">
<%= render partial: "show_advanced_#{section_id}", locals: {object: @object} %>
</div>
diff --git a/apps/workbench/app/views/pipeline_instances/_show_components.html.erb b/apps/workbench/app/views/pipeline_instances/_show_components.html.erb
index 786a8fd..649a119 100644
--- a/apps/workbench/app/views/pipeline_instances/_show_components.html.erb
+++ b/apps/workbench/app/views/pipeline_instances/_show_components.html.erb
@@ -1,7 +1,13 @@
<% if !@object.state.in? ['New', 'Ready'] %>
<div class="pull-right">
- Current state: <span class="badge badge-info" data-pipeline-state="<%= @object.state %>"><%= @object.state.sub('OnServer', '') %></span>
+ Current state: <span class="badge badge-info" data-pipeline-state="<%= @object.state %>">
+ <% if @object.state == "RunningOnServer" %>
+ Active
+ <% else %>
+ <%= @object.state %>
+ <% end %>
+ </span>
</div>
<%= render_pipeline_components("running", :json) %>
diff --git a/apps/workbench/app/views/pipeline_instances/_show_components_running.html.erb b/apps/workbench/app/views/pipeline_instances/_show_components_running.html.erb
index 9f46e3d..8fb263c 100644
--- a/apps/workbench/app/views/pipeline_instances/_show_components_running.html.erb
+++ b/apps/workbench/app/views/pipeline_instances/_show_components_running.html.erb
@@ -1,66 +1,227 @@
- <table class="table pipeline-components-table">
- <colgroup>
- <col style="width: 15%" />
- <col style="width: 25%" />
- <col style="width: 8%" />
- <col style="width: 13%" />
- <col style="width: 12%" />
- <col style="width: 14%" />
- <col style="width: 13%" />
- </colgroup>
- <thead>
- <tr>
- <th colspan="2">
- component
- </th><th colspan="5">
- job
- <%# format:'js' here helps browsers avoid using the cached js
- content in html context (e.g., duplicate tab -> see
- javascript) %>
- <%= link_to '(refresh)', {format: :js}, {class: 'refresh hide', remote: true, method: 'get'} %>
- </th>
- </tr>
- </thead>
- <tbody>
- <% render_pipeline_jobs.each do |pj| %>
- <tr data-object-uuid="<%= pj[:job].andand[:uuid] %>">
- <td>
- <%= pj[:name] %>
- </td><td>
- <%= pj[:script] %>
- <br /><span class="deemphasize"><%= pj[:script_version] %></span>
- </td><td>
- <%= render(partial: 'job_status_label', locals: { j: pj[:job] }) %>
- </td><td>
- <%= pj[:progress_bar] %>
- </td>
- <% current_job = pj[:job] rescue nil %>
- <td>
- <% if current_job.is_a? Job %>
- <%= render partial: 'show_object_button', locals: {object: current_job, size: 'xs', link_text: 'Show job details'} %>
- <% end %>
- </td><td>
- <% if current_job.andand[:log] %>
- <% fixup = /([a-f0-9]{32}\+\d+)(\+?.*)/.match(current_job[:log])%>
- <% Collection.limit(1).where(portable_data_hash: fixup[1]).each do |c| %>
- <% c.files.first.andand do |file| %>
- <%= link_to url_for(controller: 'collections', action: 'show_file', uuid: current_job[:log], file: "#{file[0]}/#{file[1]}", disposition: 'inline', size: file[2]), class: 'btn btn-default btn-xs' do %>
- <i class="fa fa-fw fa-info"></i> Show log messages
- <% end %>
- <% end %>
+<%# Summary %>
+
+<% if @object.state == 'Paused' %>
+ <p>
+ This pipeline is paused. Jobs that are
+ already running will continue to run, but no new jobs will be submitted.
+ </p>
+<% end %>
+
+<p>
+ This pipeline
+ <% if @object.state == 'Complete' %>
+ completed in
+ <% elsif @object.state == 'Failed' %>
+ failed after
+ <% else %>
+ has been active for
+ <% end %>
+ <% walltime = if @object.started_at
+ if @object.finished_at
+ @object.finished_at - @object.started_at
+ else
+ Time.now - @object.started_at
+ end
+ else
+ 0
+ end
+ %>
+ <%= runtime(walltime, true) %>, running for
+
+ <% tasks = JobTask.filter([['job_uuid', 'in', render_pipeline_jobs.map { |j| j[:job].andand[:uuid] }]]).results %>
+
+ <%# want to buy: algorithm that calculates wall clock runtime that takes into account
+ concurrent jobs. %>
+ <% runningtime = render_pipeline_jobs.map { |j|
+ if j[:job] and j[:job].started_at
+ (if j[:job].finished_at then j[:job].finished_at else Time.now() end) - j[:job].started_at
+ else
+ 0
+ end
+ }.reduce(:+) %>
+
+ <%= runtime(runningtime, true) %><% if tasks.size == 0 %>.<% else %>,
+ using
+ <% cputime = tasks.map { |task|
+ if task.started_at
+ (if task.finished_at then task.finished_at else Time.now() end) - task.started_at
+ else
+ 0
+ end
+ }.reduce(:+) %>
+ <%= runtime(cputime, true) %>
+ of CPU time (<%= (cputime/runningtime).round(1) %>⨯ scaling).
+ <% end %>
+</p>
+
+<%# Components %>
+
+<% render_pipeline_jobs.each_index do |i| %>
+ <% pj = render_pipeline_jobs[i] %>
+ <% current_job = pj[:job] if pj[:job] != {} %>
+ <div class="panel panel-default">
+ <div class="panel-heading">
+ <div class="container-fluid">
+ <div class="row">
+ <div class="col-md-3">
+ <h4 class="panel-title">
+ <a data-toggle="collapse" data-parent="#accordion" href="#collapse<%= i %>">
+ <%= pj[:name] %> <span class="caret"></span>
+ </a>
+ </h4>
+ </div>
+
+ <% puts current_job.inspect %>
+
+ <% if current_job %>
+ <div class="col-md-3">
+ <% if current_job.started_at %>
+ <% walltime = ((if current_job.finished_at then current_job.finished_at else Time.now() end) - current_job.started_at) %>
+ <% cputime = tasks.map { |task|
+ if task.started_at and task.job_uuid == current_job.uuid
+ (if task.finished_at then task.finished_at else Time.now() end) - task.started_at
+ else
+ 0
+ end
+ }.reduce(:+) %>
+ <%= runtime(walltime, false) %> / <%= runtime(cputime, false) %> (<%= (cputime/walltime).round(1) %>⨯)
<% end %>
+ </div>
+
+ <% if current_job.state.in? ["Completed", "Failed", "Canceled"] %>
+ <div class="col-md-3">
+ <%= render(partial: 'job_status_label', locals: { j: current_job }) %>
+ </div>
+ <div class="col-md-3">
+ <% if pj[:output_uuid] %>
+ <%= link_to_if_arvados_object pj[:output_uuid] %>
+ <% elsif current_job.andand[:output] %>
+ <%= link_to_if_arvados_object current_job[:output], link_text: "Output of #{pj[:name]}" %>
+ <% end %>
+ </div>
+ <% elsif current_job.state == "Running" %>
+ <div class="col-md-3">
+ <%= pj[:progress_bar] %>
+ </div>
+ <div class="col-md-3">
+ <%= form_tag "/jobs/#{current_job.uuid}/cancel", style: "display:inline; padding-left: 1em" do |f| %>
+ <%= hidden_field_tag :return_to, url_for(@object) %>
+ <%= button_tag "Cancel", {class: 'btn btn-danger', id: "cancel-job-button"} %>
+ </div>
<% end %>
- </td><td>
- <% if pj[:output_uuid] %>
- <%= link_to_if_arvados_object pj[:output_uuid], {thumbnail: true, link_text: raw('<i class="fa fa-fw fa-archive"></i> Show output files')}, {class: 'btn btn-default btn-xs'} %>
- <% elsif current_job.andand[:output] %>
- <%= link_to_if_arvados_object current_job[:output], {thumbnail: true, link_text: raw('<i class="fa fa-fw fa-archive"></i> Show output files')}, {class: 'btn btn-default btn-xs'} %>
- <% end %>
- </td>
- </tr>
- <% end %>
- </tbody>
- <tfoot>
- <tr><td colspan="7"></td></tr>
- </tfoot>
- </table>
+ <% elsif current_job.state == "Queued" %>
+ <div class="col-md-1">
+ <span class="label label-default">Queued</span>
+ </div>
+ <div class="col-md-5">
+ <% queuetime = Time.now - current_job.created_at %>
+ Queued for <%= runtime(queuetime, true) %>.
+ There
+ <% if current_job.queue_position == 0 %>
+ are no jobs
+ <% elsif current_job.queue_position == 1 %>
+ is 1 job
+ <% else %>
+ <%= current_job.queue_position %> jobs
+ <% end %>
+ ahead of this one.
+ </div>
+ <% end %>
+ <% else %>
+ <div class="col-md-3 col-md-offset-3">
+ <span class="label label-default">Not ready</span>
+ </div>
+<% end %>
+</div>
+</div>
+</div>
+
+<div id="collapse<%= i %>" class="panel-collapse collapse in">
+ <div class="panel-body">
+ <div class="container">
+ <% current_component = (if current_job then current_job else pj end) %>
+ <div class="row">
+ <div class="col-md-6">
+ <table>
+ <% [:script, :repository, :supplied_script_version, :script_version, :nondeterministic].each do |k| %>
+ <tr>
+ <td style="padding-right: 1em">
+ <%= k.to_s %>:
+ </td>
+ <td>
+ <%= current_component[k] %>
+ </td>
+ </tr>
+ <% end %>
+ <% if current_component[:runtime_constraints].andand[:docker_image] and current_component[:docker_image_locator] %>
+ <tr>
+ <td style="padding-right: 1em">
+ docker_image:
+ </td>
+ <td>
+ <%= current_component[:runtime_constraints][:docker_image] %>
+ </td>
+ </tr>
+ <tr>
+ <td style="padding-right: 1em">
+ docker_image_locator:
+ </td>
+ <td>
+ <%= link_to_if_arvados_object current_component[:docker_image_locator] %>
+ </td>
+ </tr>
+ <% else %>
+ <tr>
+ <td style="padding-right: 1em">
+ docker_image:
+ </td>
+ <td>
+ Not run in Docker
+ </td>
+ </tr>
+ <% end %>
+ </table>
+ </div>
+ <div class="col-md-5">
+ <table>
+ <% [:uuid, :modified_by_user_uuid, :priority, :created_at, :started_at, :finished_at].each do |k| %>
+ <tr>
+ <td style="padding-right: 1em">
+ <%= k.to_s %>:
+ </td>
+ <td>
+ <% if k.to_s.end_with? 'uuid' %>
+ <%= link_to_if_arvados_object current_component[k], friendly_name: true %>
+ <% else %>
+ <%= current_component[k] %>
+ <% end %>
+ </td>
+ </tr>
+ <% end %>
+ </table>
+ </div>
+ </div>
+ <div class="row">
+ <div class="col-md-6">
+ <p>script_parameters:</p>
+ <pre><%= JSON.pretty_generate(current_component[:script_parameters]) rescue nil %></pre>
+ </div>
+ <% if current_component[:tasks_summary] %>
+ <div class="col-md-3">
+ <table>
+ <% [:done, :running, :failed, :todo].each do |d| %>
+ <tr>
+ <td style="padding-right: 1em"><%= 'tasks:' if d == :done %></td>
+ <td style="padding-right: 1em"><%= d.to_s %></td>
+ <td><%= current_component[:tasks_summary][d] %></td>
+ </tr>
+ <% end %>
+ </table>
+ </div>
+ <% end %>
+ </div>
+ </div>
+ </div>
+</div>
+</div>
+<% end %>
diff --git a/apps/workbench/app/views/pipeline_instances/show.html.erb b/apps/workbench/app/views/pipeline_instances/show.html.erb
index b30db3b..f43369f 100644
--- a/apps/workbench/app/views/pipeline_instances/show.html.erb
+++ b/apps/workbench/app/views/pipeline_instances/show.html.erb
@@ -12,12 +12,21 @@
<% end %>
<% content_for :tab_line_buttons do %>
- <%= link_to(copy_pipeline_instance_path('id' => @object.uuid, 'pipeline_instance[state]' => 'New'),
+
+ <% if @object.state.in? ['Complete', 'Failed', 'Cancelled'] %>
+
+ <%= link_to(copy_pipeline_instance_path('id' => @object.uuid, 'script' => "use_latest", "components" => "use_latest", "pipeline_instance[state]" => "RunningOnServer"),
class: 'btn btn-primary',
- #data: {toggle: :tooltip, placement: :top}, title: 'copy and modify',
+ #data: {toggle: :tooltip, placement: :top}, title: 'Re-run',
method: :post,
) do %>
- Clone and edit <i class="fa fa-fw fa-copy"></i>
+ <i class="fa fa-fw fa-play"></i> Re-run with latest
+ <% end %>
+
+ <%= link_to raw('<i class="fa fa-fw fa-cogs"></i> Re-run options'),
+ "#",
+ {class: 'btn btn-primary', 'data-toggle' => "modal",
+ 'data-target' => '#clone-and-edit-modal-window'} %>
<% end %>
<% if @object.state.in? ['New', 'Ready'] %>
@@ -25,7 +34,7 @@
class: 'btn btn-primary run-pipeline-button',
method: :patch
) do %>
- Run <i class="fa fa-fw fa-play"></i>
+ <i class="fa fa-fw fa-play"></i> Run
<% end %>
<% else %>
<% if @object.state.in? ['RunningOnClient', 'RunningOnServer'] %>
@@ -33,17 +42,60 @@
class: 'btn btn-primary run-pipeline-button',
method: :patch
) do %>
- Stop <i class="fa fa-fw fa-stop"></i>
+ <i class="fa fa-fw fa-pause"></i> Pause
<% end %>
<% elsif @object.state == 'Paused' %>
<%= link_to(url_for('pipeline_instance[state]' => 'RunningOnServer'),
class: 'btn btn-primary run-pipeline-button',
method: :patch
) do %>
- Resume <i class="fa fa-fw fa-play"></i>
+ <i class="fa fa-fw fa-play"></i> Resume
<% end %>
<% end %>
<% end %>
<% end %>
<%= render partial: 'content', layout: 'content_layout', locals: {pane_list: controller.show_pane_list }%>
+
+<div id="clone-and-edit-modal-window" class="modal fade" role="dialog"
+ aria-labelledby="myModalLabel" aria-hidden="true">
+ <div class="modal-dialog">
+ <div class="modal-content">
+
+ <%= form_tag copy_pipeline_instance_path do |f| %>
+
+ <div class="modal-header">
+ <button type="button" class="close" onClick="reset_form()" data-dismiss="modal" aria-hidden="true">×</button>
+ <div>
+ <div class="col-sm-6"> <h4 class="modal-title">Re-run pipeline</h4> </div>
+ </div>
+ <br/>
+ </div>
+
+ <div class="modal-body">
+ <%= radio_button_tag(:script, "use_latest", true) %>
+ <%= label_tag(:script_use_latest, "Use latest script versions") %>
+ <br>
+ <%= radio_button_tag(:script, "use_same") %>
+ <%= label_tag(:script_use_same, "Use same script versions as this run") %>
+ <br>
+ <% if template %>
+ <br>
+ <%= radio_button_tag(:components, "use_latest", true) %>
+ <%= label_tag(:components_use_latest, "Update components against template") %>
+ <br>
+ <%= radio_button_tag(:components, "use_same") %>
+ <%= label_tag(:components_use_same, "Use same components as this run") %>
+ <% end %>
+ </div>
+
+ <div class="modal-footer">
+ <button type="submit" class="btn btn-primary" name="pipeline_instance[state]" value="New">Copy and edit inputs</button>
+ <button type="submit" class="btn btn-primary" name="pipeline_instance[state]" value="RunningOnServer">Run now</button>
+ <button class="btn btn-default" onClick="reset_form()" data-dismiss="modal" aria-hidden="true">Cancel</button>
+ </div>
+
+ </div>
+ <% end %>
+ </div>
+</div>
commit 0313c6ef5ac52fc483718690b1a5902ad1c11e16
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date: Wed Sep 10 17:01:01 2014 -0400
3187: Added queue_position field to job response.
diff --git a/services/api/app/models/job.rb b/services/api/app/models/job.rb
index 75de61c..6e87bda 100644
--- a/services/api/app/models/job.rb
+++ b/services/api/app/models/job.rb
@@ -40,6 +40,7 @@ class Job < ArvadosModel
t.add :repository
t.add :supplied_script_version
t.add :docker_image_locator
+ t.add :queue_position
end
def assert_finished
@@ -54,6 +55,16 @@ class Job < ArvadosModel
order('priority desc, created_at')
end
+ def queue_position
+ i = 0
+ Job::queue.each do |j|
+ if j[:uuid] == self.uuid
+ return i
+ end
+ end
+ nil
+ end
+
def self.running
self.where('running = ?', true).
order('priority desc, created_at')
commit 655d5ae89e941c8b11bd4ba795e9ef2168463881
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date: Tue Sep 9 15:39:55 2014 -0400
3187: Record started_at and finished_at for tasks and pipelines.
diff --git a/sdk/cli/bin/arv-run-pipeline-instance b/sdk/cli/bin/arv-run-pipeline-instance
index 7ce1fa9..b19bf04 100755
--- a/sdk/cli/bin/arv-run-pipeline-instance
+++ b/sdk/cli/bin/arv-run-pipeline-instance
@@ -495,6 +495,10 @@ class WhRunPipelineInstance
moretodo = true
interrupted = false
+ if @instance[:started_at].nil?
+ @instance[:started_at] = Time.now
+ end
+
job_creation_failed = 0
while moretodo
moretodo = false
@@ -598,7 +602,7 @@ class WhRunPipelineInstance
owner_uuid: owner_uuid,
name: name,
portable_data_hash: collections.first[:portable_data_hash],
- manifest_text: collections.first[:manifest_text]
+ manifest_text: collections.first[:manifest_text]
}
debuglog "Creating collection #{newcollection}", 0
newcollection_actual = $arv.collection.create collection: newcollection, ensure_unique_name: true
@@ -679,6 +683,10 @@ class WhRunPipelineInstance
end
end
+ if @instance[:finished_at].nil? and ['Complete', 'Failed'].include? @instance[:state]
+ @instance[:finished_at] = Time.now
+ end
+
debuglog "pipeline instance state is #{@instance[:state]}"
# set components_summary
@@ -742,6 +750,7 @@ class WhRunPipelineInstance
if ["New", "Ready", "RunningOnClient",
"RunningOnServer"].include?(@instance[:state])
@instance[:state] = "Failed"
+ @instance[:finished_at] = Time.now
@instance.save
end
@instance.log_stderr(msg)
diff --git a/sdk/cli/bin/crunch-job b/sdk/cli/bin/crunch-job
index a2c5512..06144fd 100755
--- a/sdk/cli/bin/crunch-job
+++ b/sdk/cli/bin/crunch-job
@@ -74,6 +74,7 @@ behavior (e.g., cancel job if cancelled_at becomes non-nil).
use strict;
use POSIX ':sys_wait_h';
+use POSIX qw(strftime);
use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK);
use Arvados;
use Digest::MD5 qw(md5_hex);
@@ -979,6 +980,9 @@ sub reapchildren
}
$Jobstep->{exitcode} = $childstatus;
$Jobstep->{finishtime} = time;
+ $Jobstep->{'arvados_task'}->{started_at} = strftime "Y%-%m-%dT%H:%M:%SZ", gmtime($Jobstep->{starttime});
+ $Jobstep->{'arvados_task'}->{finished_at} = strftime "Y%-%m-%dT%H:%M:%SZ", gmtime($Jobstep->{finishtime});
+ $Jobstep->{'arvados_task'}->save;
process_stderr ($jobstepid, $task_success);
Log ($jobstepid, "output " . $Jobstep->{'arvados_task'}->{output});
commit e5ab4ce19d5ace5e6dd5cd32c23f50b35d20c8ef
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date: Tue Sep 9 14:43:29 2014 -0400
3187: Migration to add started_at and finished_at to job_tasks and pipeline_instances.
diff --git a/services/api/app/models/job_task.rb b/services/api/app/models/job_task.rb
index 4dcf256..5f83fbe 100644
--- a/services/api/app/models/job_task.rb
+++ b/services/api/app/models/job_task.rb
@@ -15,6 +15,8 @@ class JobTask < ArvadosModel
t.add :output
t.add :progress
t.add :success
+ t.add :started_at
+ t.add :finished_at
end
protected
diff --git a/services/api/app/models/pipeline_instance.rb b/services/api/app/models/pipeline_instance.rb
index 354c892..7523918 100644
--- a/services/api/app/models/pipeline_instance.rb
+++ b/services/api/app/models/pipeline_instance.rb
@@ -22,6 +22,8 @@ class PipelineInstance < ArvadosModel
t.add :properties
t.add :state
t.add :components_summary
+ t.add :started_at
+ t.add :finished_at
end
# Supported states for a pipeline instance
diff --git a/services/api/db/migrate/20140909183946_add_start_finish_time_to_tasks_and_pipelines.rb b/services/api/db/migrate/20140909183946_add_start_finish_time_to_tasks_and_pipelines.rb
new file mode 100644
index 0000000..139cb8d
--- /dev/null
+++ b/services/api/db/migrate/20140909183946_add_start_finish_time_to_tasks_and_pipelines.rb
@@ -0,0 +1,15 @@
+class AddStartFinishTimeToTasksAndPipelines < ActiveRecord::Migration
+ def up
+ add_column :job_tasks, :started_at, :datetime
+ add_column :job_tasks, :finished_at, :datetime
+ add_column :pipeline_instances, :started_at, :datetime
+ add_column :pipeline_instances, :finished_at, :datetime
+ end
+
+ def down
+ remove_column :job_tasks, :started_at
+ remove_column :job_tasks, :finished_at
+ remove_column :pipeline_instances, :started_at
+ remove_column :pipeline_instances, :finished_at
+ end
+end
diff --git a/services/api/db/structure.sql b/services/api/db/structure.sql
index bd86826..2168739 100644
--- a/services/api/db/structure.sql
+++ b/services/api/db/structure.sql
@@ -353,7 +353,9 @@ CREATE TABLE job_tasks (
created_at timestamp without time zone NOT NULL,
updated_at timestamp without time zone NOT NULL,
created_by_job_task_uuid character varying(255),
- qsequence bigint
+ qsequence bigint,
+ started_at timestamp without time zone,
+ finished_at timestamp without time zone
);
@@ -678,7 +680,9 @@ CREATE TABLE pipeline_instances (
properties text,
state character varying(255),
components_summary text,
- description text
+ description text,
+ started_at timestamp without time zone,
+ finished_at timestamp without time zone
);
@@ -2012,3 +2016,5 @@ INSERT INTO schema_migrations (version) VALUES ('20140818125735');
INSERT INTO schema_migrations (version) VALUES ('20140826180337');
INSERT INTO schema_migrations (version) VALUES ('20140828141043');
+
+INSERT INTO schema_migrations (version) VALUES ('20140909183946');
\ No newline at end of file
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list