Adding 'is_searchable' status for tables which should be full-text searchable.
[arvados.git] / services / api / app / models / pipeline_instance.rb
1 class PipelineInstance < ArvadosModel
2   include AssignUuid
3   include KindAndEtag
4   include CommonApiTemplate
5   serialize :components, Hash
6   serialize :properties, Hash
7   belongs_to :pipeline_template, :foreign_key => :pipeline_template_uuid, :primary_key => :uuid
8   attr_accessor :pipeline_template
9
10   before_validation :bootstrap_components
11   before_validation :update_success
12
13   api_accessible :user, extend: :common do |t|
14     t.add :pipeline_template_uuid
15     t.add :pipeline_template, :if => :pipeline_template
16     t.add :name
17     t.add :components
18     t.add :success
19     t.add :active
20     t.add :dependencies
21     t.add :properties
22   end
23
24   def is_searchable
25     true
26   end
27
28   def dependencies
29     dependency_search(self.components).keys
30   end
31
32   def progress_table
33     begin
34       # v0 pipeline format
35       nrow = -1
36       components['steps'].collect do |step|
37         nrow += 1
38         row = [nrow, step['name']]
39         if step['complete'] and step['complete'] != 0
40           if step['output_data_locator']
41             row << 1.0
42           else
43             row << 0.0
44           end
45         else
46           row << 0.0
47           if step['failed']
48             self.success = false
49           end
50         end
51         row << (step['warehousejob']['id'] rescue nil)
52         row << (step['warehousejob']['revision'] rescue nil)
53         row << step['output_data_locator']
54         row << (Time.parse(step['warehousejob']['finishtime']) rescue nil)
55         row
56       end
57     rescue
58       []
59     end
60   end
61
62   def progress_ratio
63     t = progress_table
64     return 0 if t.size < 1
65     t.collect { |r| r[2] }.inject(0.0) { |sum,a| sum += a } / t.size
66   end
67
68   protected
69   def bootstrap_components
70     if pipeline_template and (!components or components.empty?)
71       self.components = pipeline_template.components
72     end
73   end
74
75   def update_success
76     if components and progress_ratio == 1.0
77       self.success = true
78     end
79   end
80
81   def dependency_search(haystack)
82     if haystack.is_a? String
83       if (re = haystack.match /^([0-9a-f]{32}(\+[^,]+)*)+/)
84         {re[1] => true}
85       else
86         {}
87       end
88     elsif haystack.is_a? Array
89       deps = {}
90       haystack.each do |value|
91         deps.merge! dependency_search(value)
92       end
93       deps
94     elsif haystack.respond_to? :keys
95       deps = {}
96       haystack.each do |key, value|
97         deps.merge! dependency_search(value)
98       end
99       deps
100     else
101       {}
102     end
103   end
104 end