Merge remote-tracking branch 'origin/master' into 2042-new-collection-from-selected...
[arvados.git] / apps / workbench / app / helpers / pipeline_instances_helper.rb
1 module PipelineInstancesHelper
2   def pipeline_summary object=nil
3     object ||= @object
4     ret = {todo:0, running:0, queued:0, done:0, failed:0, total:0}
5     object.components.values.each do |c|
6       ret[:total] += 1
7       case
8       when !c[:job]
9         ret[:todo] += 1
10       when c[:job][:success]
11         ret[:done] += 1
12       when c[:job][:failed]
13         ret[:failed] += 1
14       when c[:job][:finished_at]
15         ret[:running] += 1      # XXX finished but !success and !failed??
16       when c[:job][:started_at]
17         ret[:running] += 1
18       else
19         ret[:queued] += 1
20       end
21     end
22     ret.merge! Hash[ret.collect do |k,v|
23                       [('percent_' + k.to_s).to_sym,
24                        ret[:total]<1 ? 0 : (100.0*v/ret[:total]).floor]
25                     end]
26     ret
27   end
28
29   def pipeline_jobs object=nil
30     object ||= @object
31     if object.components[:steps].is_a? Array
32       pipeline_jobs_oldschool object
33     elsif object.components.is_a? Hash
34       pipeline_jobs_newschool object
35     end
36   end
37
38   def render_pipeline_jobs
39     pipeline_jobs.collect do |pj|
40       render_pipeline_job pj
41     end
42   end
43
44   def render_pipeline_job pj
45     if pj[:percent_done]
46       pj[:progress_bar] = raw <<EOF
47 <div class="progress" style="width:100px">
48   <span class="progress-bar progress-bar-success" style="width:#{pj[:percent_done]}%"></span>
49   <span class="progress-bar" style="width:#{pj[:percent_running]}%"></span>
50 </div>
51 EOF
52     elsif pj[:progress]
53       raw <<EOF
54 <div class="progress" style="width:100px">
55 <span class="progress-bar" style="width:#{pj[:progress]*100}%">
56 </span>
57 </div>
58 EOF
59     end
60     pj[:output_link] = link_to_if_arvados_object pj[:output]
61     pj[:job_link] = link_to_if_arvados_object pj[:job][:uuid]
62     pj
63   end
64
65   protected
66
67   def pipeline_jobs_newschool object
68     ret = []
69     i = -1
70     object.components.each do |cname, c|
71       i += 1
72       pj = {index: i, name: cname}
73       pj[:job] = c[:job].is_a?(Hash) ? c[:job] : {}
74       pj[:percent_done] = 0
75       pj[:percent_running] = 0
76       if pj[:job][:success]
77         if pj[:job][:output]
78           pj[:progress] = 1.0
79           pj[:percent_done] = 100
80         else
81           pj[:progress] = 0.0
82         end
83       else
84         if pj[:job][:tasks_summary]
85           begin
86             ts = pj[:job][:tasks_summary]
87             denom = ts[:done].to_f + ts[:running].to_f + ts[:todo].to_f
88             pj[:progress] = (ts[:done].to_f + ts[:running].to_f/2) / denom
89             pj[:percent_done] = 100.0 * ts[:done].to_f / denom
90             pj[:percent_running] = 100.0 * ts[:running].to_f / denom
91             pj[:progress_detail] = "#{ts[:done]} done #{ts[:running]} run #{ts[:todo]} todo"
92           rescue
93             pj[:progress] = 0.5
94             pj[:percent_done] = 0.0
95             pj[:percent_running] = 100.0
96           end
97         else
98           pj[:progress] = 0.0
99         end
100       end
101       if pj[:job][:success]
102         pj[:result] = 'complete'
103         pj[:complete] = true
104         pj[:progress] = 1.0
105       elsif pj[:job][:finished_at]
106         pj[:result] = 'failed'
107         pj[:failed] = true
108       elsif pj[:job][:started_at]
109         pj[:result] = 'running'
110       elsif pj[:job][:uuid]
111         pj[:result] = 'queued'
112       else
113         pj[:result] = 'none'
114       end
115       pj[:job_id] = pj[:job][:uuid]
116       pj[:script] = pj[:job][:script] || c[:script]
117       pj[:script_parameters] = pj[:job][:script_parameters] || c[:script_parameters]
118       pj[:script_version] = pj[:job][:script_version] || c[:script_version]
119       pj[:output] = pj[:job][:output]
120       pj[:finished_at] = (Time.parse(pj[:job][:finished_at]) rescue nil)
121       ret << pj
122     end
123     ret
124   end
125
126   def pipeline_jobs_oldschool object
127     ret = []
128     object.components[:steps].each_with_index do |step, i|
129       pj = {index: i, name: step[:name]}
130       if step[:complete] and step[:complete] != 0
131         if step[:output_data_locator]
132           pj[:progress] = 1.0
133         else
134           pj[:progress] = 0.0
135         end
136       else
137         if step[:progress] and
138             (re = step[:progress].match /^(\d+)\+(\d+)\/(\d+)$/)
139           pj[:progress] = (((re[1].to_f + re[2].to_f/2) / re[3].to_f) rescue 0.5)
140         else
141           pj[:progress] = 0.0
142         end
143         if step[:failed]
144           pj[:result] = 'failed'
145           pj[:failed] = true
146         end
147       end
148       if step[:warehousejob]
149         if step[:complete]
150           pj[:result] = 'complete'
151           pj[:complete] = true
152           pj[:progress] = 1.0
153         elsif step[:warehousejob][:finishtime]
154           pj[:result] = 'failed'
155           pj[:failed] = true
156         elsif step[:warehousejob][:starttime]
157           pj[:result] = 'running'
158         else
159           pj[:result] = 'queued'
160         end
161       end
162       pj[:progress_detail] = (step[:progress] rescue nil)
163       pj[:job_id] = (step[:warehousejob][:id] rescue nil)
164       pj[:job_link] = pj[:job_id]
165       pj[:script] = step[:function]
166       pj[:script_version] = (step[:warehousejob][:revision] rescue nil)
167       pj[:output] = step[:output_data_locator]
168       pj[:finished_at] = (Time.parse(step[:warehousejob][:finishtime]) rescue nil)
169       ret << pj
170     end
171     ret
172   end
173 end