Merge branch 'master' into 3219-further-docker-improvements
[arvados.git] / apps / workbench / app / helpers / pipeline_instances_helper.rb
1 module PipelineInstancesHelper
2
3   def pipeline_jobs object=nil
4     object ||= @object
5     if object.components[:steps].is_a? Array
6       pipeline_jobs_oldschool object
7     elsif object.components.is_a? Hash
8       pipeline_jobs_newschool object
9     end
10   end
11
12   def render_pipeline_jobs
13     pipeline_jobs.collect do |pj|
14       render_pipeline_job pj
15     end
16   end
17
18   def render_pipeline_job pj
19     pj[:progress_bar] = render partial: 'job_progress', locals: {:j => pj[:job]}
20     pj[:output_link] = link_to_if_arvados_object pj[:output]
21     pj[:job_link] = link_to_if_arvados_object pj[:job][:uuid]
22     pj
23   end
24
25   def pipeline_log_history(job_uuids)
26     results = []
27
28     log_history = Log.where(event_type: 'stderr',
29                             object_uuid: job_uuids).order('id DESC')
30     if !log_history.results.empty?
31       reversed_results = log_history.results.reverse
32       reversed_results.each do |entry|
33         if entry.andand.properties
34           properties = entry.properties
35           text = properties[:text]
36           if text
37             results = results.concat text.split("\n")
38           end
39         end
40       end
41     end
42
43     return results
44   end
45
46   protected
47
48   def pipeline_jobs_newschool object
49     ret = []
50     i = -1
51
52     object.components.each do |cname, c|
53       i += 1
54       pj = {index: i, name: cname}
55       if not c.is_a?(Hash)
56         ret << pj
57         next
58       end
59       pj[:job] = c[:job].is_a?(Hash) ? c[:job] : {}
60       pj[:percent_done] = 0
61       pj[:percent_running] = 0
62       if pj[:job][:success]
63         if pj[:job][:output]
64           pj[:progress] = 1.0
65           pj[:percent_done] = 100
66         else
67           pj[:progress] = 0.0
68         end
69       else
70         if pj[:job][:tasks_summary]
71           begin
72             ts = pj[:job][:tasks_summary]
73             denom = ts[:done].to_f + ts[:running].to_f + ts[:todo].to_f
74             pj[:progress] = (ts[:done].to_f + ts[:running].to_f/2) / denom
75             pj[:percent_done] = 100.0 * ts[:done].to_f / denom
76             pj[:percent_running] = 100.0 * ts[:running].to_f / denom
77             pj[:progress_detail] = "#{ts[:done]} done #{ts[:running]} run #{ts[:todo]} todo"
78           rescue
79             pj[:progress] = 0.5
80             pj[:percent_done] = 0.0
81             pj[:percent_running] = 100.0
82           end
83         else
84           pj[:progress] = 0.0
85         end
86       end
87       if pj[:job][:success]
88         pj[:result] = 'complete'
89         pj[:labeltype] = 'success'
90         pj[:complete] = true
91         pj[:progress] = 1.0
92       elsif pj[:job][:finished_at]
93         pj[:result] = 'failed'
94         pj[:labeltype] = 'danger'
95         pj[:failed] = true
96       elsif pj[:job][:started_at]
97         pj[:result] = 'running'
98         pj[:labeltype] = 'primary'
99       elsif pj[:job][:uuid]
100         pj[:result] = 'queued'
101         pj[:labeltype] = 'default'
102       else
103         pj[:result] = 'none'
104         pj[:labeltype] = 'default'
105       end
106       pj[:job_id] = pj[:job][:uuid]
107       pj[:script] = pj[:job][:script] || c[:script]
108       pj[:script_parameters] = pj[:job][:script_parameters] || c[:script_parameters]
109       pj[:script_version] = pj[:job][:script_version] || c[:script_version]
110       pj[:output] = pj[:job][:output]
111       pj[:finished_at] = (Time.parse(pj[:job][:finished_at]) rescue nil)
112       ret << pj
113     end
114     ret
115   end
116
117   def pipeline_jobs_oldschool object
118     ret = []
119     object.components[:steps].each_with_index do |step, i|
120       pj = {index: i, name: step[:name]}
121       if step[:complete] and step[:complete] != 0
122         if step[:output_data_locator]
123           pj[:progress] = 1.0
124         else
125           pj[:progress] = 0.0
126         end
127       else
128         if step[:progress] and
129             (re = step[:progress].match /^(\d+)\+(\d+)\/(\d+)$/)
130           pj[:progress] = (((re[1].to_f + re[2].to_f/2) / re[3].to_f) rescue 0.5)
131         else
132           pj[:progress] = 0.0
133         end
134         if step[:failed]
135           pj[:result] = 'failed'
136           pj[:failed] = true
137         end
138       end
139       if step[:warehousejob]
140         if step[:complete]
141           pj[:result] = 'complete'
142           pj[:complete] = true
143           pj[:progress] = 1.0
144         elsif step[:warehousejob][:finishtime]
145           pj[:result] = 'failed'
146           pj[:failed] = true
147         elsif step[:warehousejob][:starttime]
148           pj[:result] = 'running'
149         else
150           pj[:result] = 'queued'
151         end
152       end
153       pj[:progress_detail] = (step[:progress] rescue nil)
154       pj[:job_id] = (step[:warehousejob][:id] rescue nil)
155       pj[:job_link] = pj[:job_id]
156       pj[:script] = step[:function]
157       pj[:script_version] = (step[:warehousejob][:revision] rescue nil)
158       pj[:output] = step[:output_data_locator]
159       pj[:finished_at] = (Time.parse(step[:warehousejob][:finishtime]) rescue nil)
160       ret << pj
161     end
162     ret
163   end
164 end