Merge branch 'master' into 1786-replace-jekyll-with-zenweb
[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("<div class=\"progress\" style=\"width:100px\"><span class=\"progress-bar progress-bar-success\" style=\"width:#{pj[:percent_done]}%\"></span><span class=\"progress-bar\" style=\"width:#{pj[:percent_running]}%\"></span></div>")
47     elsif pj[:progress]
48       raw("<div class=\"progress\" style=\"width:100px\"><span class=\"progress-bar\" style=\"width:#{pj[:progress]*100}%\"></span></div>")
49     end
50     pj[:output_link] = link_to_if_arvados_object pj[:output]
51     pj[:job_link] = link_to_if_arvados_object pj[:job][:uuid]
52     pj
53   end
54
55   protected
56
57   def pipeline_jobs_newschool object
58     ret = []
59     i = -1
60     object.components.each do |cname, c|
61       i += 1
62       pj = {index: i, name: cname}
63       pj[:job] = c[:job].is_a?(Hash) ? c[:job] : {}
64       pj[:percent_done] = 0
65       pj[:percent_running] = 0
66       if pj[:job][:success]
67         if pj[:job][:output]
68           pj[:progress] = 1.0
69           pj[:percent_done] = 100
70         else
71           pj[:progress] = 0.0
72         end
73       else
74         if pj[:job][:tasks_summary]
75           begin
76             ts = pj[:job][:tasks_summary]
77             denom = ts[:done].to_f + ts[:running].to_f + ts[:todo].to_f
78             pj[:progress] = (ts[:done].to_f + ts[:running].to_f/2) / denom
79             pj[:percent_done] = 100.0 * ts[:done].to_f / denom
80             pj[:percent_running] = 100.0 * ts[:running].to_f / denom
81             pj[:progress_detail] = "#{ts[:done]} done #{ts[:running]} run #{ts[:todo]} todo"
82           rescue
83             pj[:progress] = 0.5
84             pj[:percent_done] = 0.0
85             pj[:percent_running] = 100.0
86           end
87         else
88           pj[:progress] = 0.0
89         end
90       end
91       if pj[:job][:success]
92         pj[:result] = 'complete'
93         pj[:complete] = true
94         pj[:progress] = 1.0
95       elsif pj[:job][:finished_at]
96         pj[:result] = 'failed'
97         pj[:failed] = true
98       elsif pj[:job][:started_at]
99         pj[:result] = 'running'
100       elsif pj[:job][:uuid]
101         pj[:result] = 'queued'
102       else
103         pj[:result] = 'none'
104       end
105       pj[:job_id] = pj[:job][:uuid]
106       pj[:script] = pj[:job][:script] || c[:script]
107       pj[:script_parameters] = pj[:job][:script_parameters] || c[:script_parameters]
108       pj[:script_version] = pj[:job][:script_version] || c[:script_version]
109       pj[:output] = pj[:job][:output]
110       pj[:finished_at] = (Time.parse(pj[:job][:finished_at]) rescue nil)
111       ret << pj
112     end
113     ret
114   end
115
116   def pipeline_jobs_oldschool object
117     ret = []
118     object.components[:steps].each_with_index do |step, i|
119       pj = {index: i, name: step[:name]}
120       if step[:complete] and step[:complete] != 0
121         if step[:output_data_locator]
122           pj[:progress] = 1.0
123         else
124           pj[:progress] = 0.0
125         end
126       else
127         if step[:progress] and
128             (re = step[:progress].match /^(\d+)\+(\d+)\/(\d+)$/)
129           pj[:progress] = (((re[1].to_f + re[2].to_f/2) / re[3].to_f) rescue 0.5)
130         else
131           pj[:progress] = 0.0
132         end
133         if step[:failed]
134           pj[:result] = 'failed'
135           pj[:failed] = true
136         end
137       end
138       if step[:warehousejob]
139         if step[:complete]
140           pj[:result] = 'complete'
141           pj[:complete] = true
142           pj[:progress] = 1.0
143         elsif step[:warehousejob][:finishtime]
144           pj[:result] = 'failed'
145           pj[:failed] = true
146         elsif step[:warehousejob][:starttime]
147           pj[:result] = 'running'
148         else
149           pj[:result] = 'queued'
150         end
151       end
152       pj[:progress_detail] = (step[:progress] rescue nil)
153       pj[:job_id] = (step[:warehousejob][:id] rescue nil)
154       pj[:job_link] = pj[:job_id]
155       pj[:script] = step[:function]
156       pj[:script_version] = (step[:warehousejob][:revision] rescue nil)
157       pj[:output] = step[:output_data_locator]
158       pj[:finished_at] = (Time.parse(step[:warehousejob][:finishtime]) rescue nil)
159       ret << pj
160     end
161     ret
162   end
163 end