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