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