rukawa 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/rukawa/cli.rb +4 -3
- data/lib/rukawa/dag.rb +19 -16
- data/lib/rukawa/job.rb +8 -8
- data/lib/rukawa/job_net.rb +17 -16
- data/lib/rukawa/version.rb +1 -1
- data/sample/job_nets/sample_job_net.rb +12 -0
- data/sample/jobnet.png +0 -0
- data/sample/jobs/sample_job.rb +6 -0
- data/sample/result.png +0 -0
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 999a3ff79a503ecea000dd2bed167c22a449f8cf
|
4
|
+
data.tar.gz: 4fc79536e34bbe56be38e7761634ffaff46fa388
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d5cf437492c3461a218b817834fbd0d50cdcb613b06a587b5770458acd18fc0945f1640cd19447eacae2357003a1e371a605f77f7646c6032596b4ed7fdcc10e
|
7
|
+
data.tar.gz: b0c0649300511b87a1afe1d9ba04fbb2084169c718fdef5ef0f322333a7881204ff082717b871d495fd34f1f0da123c165d85213bd2f9dc29dc018dc169638ce
|
data/lib/rukawa/cli.rb
CHANGED
@@ -3,7 +3,7 @@ require 'rukawa/runner'
|
|
3
3
|
|
4
4
|
module Rukawa
|
5
5
|
class Cli < Thor
|
6
|
-
desc "run JOB_NET_NAME", "Run jobnet"
|
6
|
+
desc "run JOB_NET_NAME [JOB_NAME] [JOB_NAME] ...", "Run jobnet. If JOB_NET is set, resume from JOB_NAME"
|
7
7
|
map "run" => "_run"
|
8
8
|
method_option :concurrency, aliases: "-c", type: :numeric, default: nil, desc: "Default: cpu count"
|
9
9
|
method_option :variables, type: :hash, default: {}
|
@@ -14,7 +14,7 @@ module Rukawa
|
|
14
14
|
method_option :stdout, type: :boolean, default: false, desc: "Output log to stdout"
|
15
15
|
method_option :dot, aliases: "-d", type: :string, default: nil, desc: "Output job status by dot format"
|
16
16
|
method_option :refresh_interval, aliases: "-r", type: :numeric, default: 3, desc: "Refresh interval for running status information"
|
17
|
-
def _run(job_net_name)
|
17
|
+
def _run(job_net_name, *job_name)
|
18
18
|
load_config
|
19
19
|
Rukawa.configure do |c|
|
20
20
|
c.log_file = options[:stdout] ? $stdout : options[:log]
|
@@ -23,7 +23,8 @@ module Rukawa
|
|
23
23
|
load_job_definitions
|
24
24
|
|
25
25
|
job_net_class = Object.const_get(job_net_name)
|
26
|
-
|
26
|
+
job_classes = job_name.map { |name| Object.const_get(name) }
|
27
|
+
job_net = job_net_class.new(nil, *job_classes)
|
27
28
|
result = Runner.run(job_net, options[:batch], options[:refresh_interval])
|
28
29
|
|
29
30
|
if options[:dot]
|
data/lib/rukawa/dag.rb
CHANGED
@@ -4,21 +4,28 @@ module Rukawa
|
|
4
4
|
class Dag
|
5
5
|
include Enumerable
|
6
6
|
|
7
|
-
attr_reader :jobs, :edges
|
7
|
+
attr_reader :nodes, :jobs, :edges
|
8
8
|
|
9
|
-
def initialize
|
10
|
-
|
9
|
+
def initialize
|
10
|
+
@nodes = Set.new
|
11
11
|
@jobs = Set.new
|
12
12
|
@edges = Set.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def build(job_net, dependencies)
|
16
|
+
deps = tsortable_hash(dependencies).tsort
|
13
17
|
|
14
18
|
deps.each do |job_class|
|
15
19
|
job = job_class.new(job_net)
|
16
|
-
@
|
20
|
+
@nodes << job
|
21
|
+
@jobs << job if job.is_a?(Job)
|
17
22
|
|
18
23
|
dependencies[job_class].each do |depend_job_class|
|
19
|
-
depend_job = @
|
24
|
+
depend_job = @nodes.find { |j| j.instance_of?(depend_job_class) }
|
20
25
|
|
21
|
-
depend_job.
|
26
|
+
depend_job.jobs_as_from.product(job.jobs_as_to).each do |from, to|
|
27
|
+
@jobs << from
|
28
|
+
@jobs << to
|
22
29
|
edge = Edge.new(from, to, job_net)
|
23
30
|
@edges << edge
|
24
31
|
from.out_goings << edge
|
@@ -26,24 +33,20 @@ module Rukawa
|
|
26
33
|
end
|
27
34
|
end
|
28
35
|
end
|
36
|
+
|
37
|
+
if job_net.parent_job_net
|
38
|
+
job_net.parent_job_net.dag.jobs.merge(@jobs)
|
39
|
+
end
|
29
40
|
end
|
30
41
|
|
31
42
|
def each
|
32
43
|
if block_given?
|
33
|
-
@
|
44
|
+
@nodes.each { |j| yield j }
|
34
45
|
else
|
35
|
-
@
|
46
|
+
@nodes.each
|
36
47
|
end
|
37
48
|
end
|
38
49
|
|
39
|
-
def roots
|
40
|
-
select(&:root?)
|
41
|
-
end
|
42
|
-
|
43
|
-
def leaves
|
44
|
-
select(&:leaf?)
|
45
|
-
end
|
46
|
-
|
47
50
|
private
|
48
51
|
|
49
52
|
def tsortable_hash(hash)
|
data/lib/rukawa/job.rb
CHANGED
@@ -4,21 +4,21 @@ require 'rukawa/abstract_job'
|
|
4
4
|
module Rukawa
|
5
5
|
class Job < AbstractJob
|
6
6
|
attr_accessor :in_comings, :out_goings
|
7
|
-
attr_reader :state
|
7
|
+
attr_reader :parent_job_net, :state
|
8
8
|
|
9
|
-
def initialize(
|
10
|
-
@
|
9
|
+
def initialize(parent_job_net)
|
10
|
+
@parent_job_net = parent_job_net
|
11
11
|
@in_comings = Set.new
|
12
12
|
@out_goings = Set.new
|
13
13
|
set_state(:waiting)
|
14
14
|
end
|
15
15
|
|
16
16
|
def root?
|
17
|
-
in_comings.select { |edge| edge.cluster == @
|
17
|
+
in_comings.select { |edge| edge.cluster == @parent_job_net }.empty?
|
18
18
|
end
|
19
19
|
|
20
20
|
def leaf?
|
21
|
-
out_goings.select { |edge| edge.cluster == @
|
21
|
+
out_goings.select { |edge| edge.cluster == @parent_job_net }.empty?
|
22
22
|
end
|
23
23
|
|
24
24
|
def dataflow
|
@@ -28,7 +28,7 @@ module Rukawa
|
|
28
28
|
begin
|
29
29
|
raise DependentJobFailure unless results.all? { |r| !r.nil? }
|
30
30
|
|
31
|
-
if skip? || @
|
31
|
+
if skip? || @parent_job_net.skip? || results.any? { |r| r == Rukawa::State.get(:skipped) }
|
32
32
|
Rukawa.logger.info("Skip #{self.class}")
|
33
33
|
set_state(:skipped)
|
34
34
|
else
|
@@ -51,10 +51,10 @@ module Rukawa
|
|
51
51
|
def run
|
52
52
|
end
|
53
53
|
|
54
|
-
def
|
54
|
+
def jobs_as_from
|
55
55
|
[self]
|
56
56
|
end
|
57
|
-
alias :
|
57
|
+
alias :jobs_as_to :jobs_as_from
|
58
58
|
|
59
59
|
def to_dot_def
|
60
60
|
if state == Rukawa::State::Waiting
|
data/lib/rukawa/job_net.rb
CHANGED
@@ -3,7 +3,7 @@ require 'rukawa/abstract_job'
|
|
3
3
|
module Rukawa
|
4
4
|
class JobNet < AbstractJob
|
5
5
|
include Enumerable
|
6
|
-
attr_reader :dag
|
6
|
+
attr_reader :parent_job_net, :dag
|
7
7
|
|
8
8
|
class << self
|
9
9
|
def dependencies
|
@@ -11,9 +11,18 @@ module Rukawa
|
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
-
def initialize(
|
15
|
-
@
|
16
|
-
@dag = Dag.new
|
14
|
+
def initialize(parent_job_net, *resume_job_classes)
|
15
|
+
@parent_job_net = parent_job_net
|
16
|
+
@dag = Dag.new
|
17
|
+
@dag.build(self, self.class.dependencies)
|
18
|
+
end
|
19
|
+
|
20
|
+
def toplevel?
|
21
|
+
@parent_job_net.nil?
|
22
|
+
end
|
23
|
+
|
24
|
+
def subgraph?
|
25
|
+
!toplevel?
|
17
26
|
end
|
18
27
|
|
19
28
|
def dataflows
|
@@ -36,14 +45,6 @@ module Rukawa
|
|
36
45
|
File.open(filename, 'w') { |f| f.write(to_dot) }
|
37
46
|
end
|
38
47
|
|
39
|
-
def nodes_as_from
|
40
|
-
leaves
|
41
|
-
end
|
42
|
-
|
43
|
-
def nodes_as_to
|
44
|
-
roots
|
45
|
-
end
|
46
|
-
|
47
48
|
def to_dot(subgraph = false)
|
48
49
|
graphdef = subgraph ? "subgraph" : "digraph"
|
49
50
|
buf = %Q|#{graphdef} "#{subgraph ? "cluster_" : ""}#{name}" {\n|
|
@@ -65,12 +66,12 @@ module Rukawa
|
|
65
66
|
to_dot(true)
|
66
67
|
end
|
67
68
|
|
68
|
-
def
|
69
|
-
@dag.
|
69
|
+
def jobs_as_to
|
70
|
+
@dag.jobs.select { |j| j.in_comings.select { |edge| edge.cluster == self }.empty? && j.root? }
|
70
71
|
end
|
71
72
|
|
72
|
-
def
|
73
|
-
@dag.
|
73
|
+
def jobs_as_from
|
74
|
+
@dag.jobs.select { |j| j.out_goings.select { |edge| edge.cluster == self }.empty? && j.leaf? }
|
74
75
|
end
|
75
76
|
|
76
77
|
def each(&block)
|
data/lib/rukawa/version.rb
CHANGED
@@ -42,6 +42,18 @@ class InnerJobNet4 < Rukawa::JobNet
|
|
42
42
|
InnerJob11 => [],
|
43
43
|
InnerJob12 => [],
|
44
44
|
InnerJob13 => [],
|
45
|
+
NestedJobNet => [InnerJob11, InnerJob12],
|
46
|
+
}
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class NestedJobNet < Rukawa::JobNet
|
52
|
+
class << self
|
53
|
+
def dependencies
|
54
|
+
{
|
55
|
+
NestedJob1 => [],
|
56
|
+
NestedJob2 => [NestedJob1],
|
45
57
|
}
|
46
58
|
end
|
47
59
|
end
|
data/sample/jobnet.png
CHANGED
Binary file
|
data/sample/jobs/sample_job.rb
CHANGED
data/sample/result.png
CHANGED
Binary file
|