rukawa 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|