rukawa 0.3.2 → 0.3.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a662fb54093353cccddf1ea735d9599c9ab55868
4
- data.tar.gz: 1f860deaedc962f72de32f02b0760994aa5c41ba
3
+ metadata.gz: 13b76e6a6b3bab23573723fee0d2c9049d1b5052
4
+ data.tar.gz: f39e1766871bd26e710edd2868edf39c625f1a0f
5
5
  SHA512:
6
- metadata.gz: c9945a19a8990cc809d96e3c4f5ada00a8b56924234627250f7bfdcfe6562eb4d997240eb7aabe34434ce80abb47af0486ceb4c7e383d2a68652d2899218b8a3
7
- data.tar.gz: b1e02a5e7d17be36a7a658674834e89c9bf626948cb1a181e73d19a04c129cf58e3a19d347c56014a490abc4b665e187e19fc45988e8e80ffe1a327e792a6f58
6
+ metadata.gz: 9037f65f1a2c502a52cd53b3abc2758f2dcbb9deb43595f67687325c09924a298da2a7b79505a34bed2638128a278a8c5997efe07c4c4ee1884fb8f70620e19c
7
+ data.tar.gz: 42bb250a6a17de86a9d23f2343352d26426185a176313fdef7befcd4117aa4bac846be2d93393fac3e7970d1d18b115c2dadd87936a0512cb59ace0675b91d28
data/README.md CHANGED
@@ -227,6 +227,21 @@ Main usage is manual reentering.
227
227
  % dot -Tpng -o SampleJobNet.png SampleJobNet.dot
228
228
  ```
229
229
 
230
+ ### Config Example
231
+
232
+ ```
233
+ # rukawa.rb
234
+
235
+ Rukawa.configure do |c|
236
+ c.logger = OtherLogger.new
237
+ c.concurrency = 4
238
+ c.graph.concentrate = true
239
+ c.graph.nodesep = 0.8
240
+ end
241
+ ```
242
+
243
+ see. [Rukawa::Configuration](https://github.com/joker1007/rukawa/blob/master/lib/rukawa/configuration.rb)
244
+
230
245
  ### help
231
246
  ```
232
247
  % bundle exec rukawa help run
@@ -1,18 +1,28 @@
1
1
  require 'set'
2
2
  require 'rukawa/state'
3
+ require 'active_support/core_ext/class'
3
4
 
4
5
  module Rukawa
5
6
  class AbstractJob
6
7
  attr_reader :parent_job_net
8
+ extend ActiveSupport::DescendantsTracker
7
9
 
10
+ class_attribute :skip_rules, instance_writer: false
11
+ self.skip_rules = []
8
12
  class << self
9
- def skip_rules
10
- @skip_rules ||= []
13
+ def add_skip_rule(callable_or_symbol)
14
+ self.skip_rules = skip_rules + [callable_or_symbol]
11
15
  end
12
16
 
13
- def add_skip_rule(callable_or_symbol)
14
- skip_rules.push(callable_or_symbol)
17
+ def description
18
+ @description
19
+ end
20
+ alias :desc :description
21
+
22
+ def set_description(body)
23
+ @description = body
15
24
  end
25
+ alias :set_desc :set_description
16
26
  end
17
27
 
18
28
  def name
@@ -30,10 +40,6 @@ module Rukawa
30
40
  end
31
41
  end
32
42
 
33
- def skip_rules
34
- self.class.skip_rules
35
- end
36
-
37
43
  def elapsed_time_from(time = Time.now)
38
44
  return finished_at - started_at if started_at && finished_at
39
45
  return time - started_at if started_at
@@ -46,11 +52,11 @@ module Rukawa
46
52
  return "N/A" unless elapsed
47
53
 
48
54
  hour = elapsed.to_i / 3600
49
- min = elapsed.to_i / 60
55
+ min = (elapsed - hour * 3600).to_i / 60
50
56
  sec = (elapsed - hour * 3600 - min * 60).to_i
51
57
 
52
- hour_format = min > 0 ? "%dh " % hour : ""
53
- min_format = min > 0 ? "%dm " % min : ""
58
+ hour_format = hour > 0 ? "%dh " % hour : ""
59
+ min_format = hour > 0 || min > 0 ? "%dm " % min : ""
54
60
  sec_format = "#{sec}s"
55
61
  "#{hour_format}#{min_format}#{sec_format}"
56
62
  end
data/lib/rukawa/cli.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'thor'
2
2
  require 'rukawa/runner'
3
+ require 'rukawa/overview'
3
4
 
4
5
  module Rukawa
5
6
  class Cli < Thor
@@ -10,20 +11,19 @@ module Rukawa
10
11
  method_option :config, type: :string, default: nil, desc: "If this options is not set, try to load ./rukawa.rb"
11
12
  method_option :job_dirs, type: :array, default: [], desc: "Load job directories"
12
13
  method_option :batch, aliases: "-b", type: :boolean, default: false, desc: "If batch mode, not display running status"
13
- method_option :log, aliases: "-l", type: :string, default: "./rukawa.log"
14
+ method_option :log, aliases: "-l", type: :string, desc: "Default: ./rukawa.log"
14
15
  method_option :stdout, type: :boolean, default: false, desc: "Output log to stdout"
16
+ method_option :syslog, type: :boolean, default: false, desc: "Output log to syslog"
15
17
  method_option :dot, aliases: "-d", type: :string, default: nil, desc: "Output job status by dot format"
16
18
  method_option :refresh_interval, aliases: "-r", type: :numeric, default: 3, desc: "Refresh interval for running status information"
17
19
  def _run(job_net_name, *job_name)
18
20
  load_config
19
- Rukawa.configure do |c|
20
- c.log_file = options[:stdout] ? $stdout : options[:log]
21
- c.concurrency = options[:concurrency] if options[:concurrency]
22
- end
21
+ set_logger
22
+ set_concurrency
23
23
  load_job_definitions
24
24
 
25
- job_net_class = Object.const_get(job_net_name)
26
- job_classes = job_name.map { |name| Object.const_get(name) }
25
+ job_net_class = get_class(job_net_name)
26
+ job_classes = job_name.map { |name| get_class(name) }
27
27
  job_net = job_net_class.new(nil, *job_classes)
28
28
  result = Runner.run(job_net, options[:batch], options[:refresh_interval])
29
29
 
@@ -42,8 +42,8 @@ module Rukawa
42
42
  load_config
43
43
  load_job_definitions
44
44
 
45
- job_net_class = Object.const_get(job_net_name)
46
- job_classes = job_name.map { |name| Object.const_get(name) }
45
+ job_net_class = get_class(job_net_name)
46
+ job_classes = job_name.map { |name| get_class(name) }
47
47
  job_net = job_net_class.new(nil, *job_classes)
48
48
  job_net.output_dot(options[:output])
49
49
  end
@@ -60,13 +60,11 @@ module Rukawa
60
60
  method_option :refresh_interval, aliases: "-r", type: :numeric, default: 3, desc: "Refresh interval for running status information"
61
61
  def run_job(*job_name)
62
62
  load_config
63
- Rukawa.configure do |c|
64
- c.log_file = options[:stdout] ? $stdout : options[:log]
65
- c.concurrency = options[:concurrency] if options[:concurrency]
66
- end
63
+ set_logger
64
+ set_concurrency
67
65
  load_job_definitions
68
66
 
69
- job_classes = job_name.map { |name| Object.const_get(name) }
67
+ job_classes = job_name.map { |name| get_class(name) }
70
68
  job_net_class = anonymous_job_net_class(*job_classes)
71
69
  job_net = job_net_class.new(nil)
72
70
  result = Runner.run(job_net, options[:batch], options[:refresh_interval])
@@ -78,6 +76,25 @@ module Rukawa
78
76
  exit 1 unless result
79
77
  end
80
78
 
79
+ desc "list", "List JobNet"
80
+ method_option :config, type: :string, default: nil, desc: "If this options is not set, try to load ./rukawa.rb"
81
+ method_option :jobs, aliases: "-j", type: :boolean, desc: "Show jobs", default: false
82
+ method_option :job_dirs, type: :array, default: [], desc: "Load job directories"
83
+ def list
84
+ load_config
85
+ load_job_definitions
86
+ Rukawa::Overview.list_job_net(with_jobs: options[:jobs])
87
+ end
88
+
89
+ desc "list_job", "List Job"
90
+ method_option :config, type: :string, default: nil, desc: "If this options is not set, try to load ./rukawa.rb"
91
+ method_option :job_dirs, type: :array, default: [], desc: "Load job directories"
92
+ def list_job
93
+ load_config
94
+ load_job_definitions
95
+ Rukawa::Overview.list_job
96
+ end
97
+
81
98
  private
82
99
 
83
100
  def load_config
@@ -88,6 +105,27 @@ module Rukawa
88
105
  end
89
106
  end
90
107
 
108
+ def set_logger
109
+ Rukawa.configure do |c|
110
+ if options[:stdout]
111
+ c.logger = Logger.new($stdout)
112
+ elsif options[:syslog]
113
+ require 'syslog/logger'
114
+ c.logger = Syslog::Logger.new('rukawa')
115
+ elsif options[:log]
116
+ c.logger = Logger.new(options[:log])
117
+ else
118
+ c.logger ||= Logger.new('./rukawa.log');
119
+ end
120
+ end
121
+ end
122
+
123
+ def set_concurrency
124
+ Rukawa.configure do |c|
125
+ c.concurrency = options[:concurrency] if options[:concurrency]
126
+ end
127
+ end
128
+
91
129
  def default_config_file
92
130
  "./rukawa.rb"
93
131
  end
@@ -103,6 +141,13 @@ module Rukawa
103
141
  end
104
142
  end
105
143
 
144
+ def get_class(name)
145
+ Object.const_get(name)
146
+ rescue NameError
147
+ $stderr.puts("`#{name}` class is not found")
148
+ exit 1
149
+ end
150
+
106
151
  def anonymous_job_net_class(*job_classes)
107
152
  Class.new(JobNet) do
108
153
  self.singleton_class.send(:define_method, :dependencies) do
@@ -6,9 +6,12 @@ require 'concurrent'
6
6
  module Rukawa
7
7
  class Configuration < Delegator
8
8
  include Singleton
9
+ attr_accessor :logger
9
10
 
10
11
  def initialize
11
- @config = OpenStruct.new(log_file: "./rukawa.log", concurrency: Concurrent.processor_count)
12
+ @config = OpenStruct.new(
13
+ concurrency: Concurrent.processor_count
14
+ )
12
15
  @config.graph = GraphConfig.new.tap { |c| c.rankdir = "LR" }
13
16
  end
14
17
 
@@ -0,0 +1,59 @@
1
+ module Rukawa
2
+ module Dependency
3
+ def self.get(name)
4
+ const_get(name.to_s.split("_").map(&:capitalize).join)
5
+ end
6
+
7
+ class Base
8
+ def initialize(*results)
9
+ @results = results
10
+ end
11
+
12
+ def resolve
13
+ raise NotImplementedError
14
+ end
15
+ end
16
+
17
+ class AllSuccess < Base
18
+ def resolve
19
+ @results.all? { |r| r && r.success? }
20
+ end
21
+ end
22
+
23
+ class AllDone < Base
24
+ def resolve
25
+ true
26
+ end
27
+ end
28
+
29
+ class OneSuccess < Base
30
+ def resolve
31
+ @results.empty? || @results.any? { |r| r && r.success? }
32
+ end
33
+ end
34
+
35
+ class AllSuccessOrSkipped < Base
36
+ def resolve
37
+ @results.all? { |r| r && (r.success? || r.skipped?) }
38
+ end
39
+ end
40
+
41
+ class OneSuccessOrSkipped < Base
42
+ def resolve
43
+ @results.empty? || @results.any? { |r| r && (r.success? || r.skipped?) }
44
+ end
45
+ end
46
+
47
+ class AllFailed < Base
48
+ def resolve
49
+ @results.none? { |r| r }
50
+ end
51
+ end
52
+
53
+ class OneFailed < Base
54
+ def resolve
55
+ @results.empty? || @results.any? { |r| r.nil? }
56
+ end
57
+ end
58
+ end
59
+ end
data/lib/rukawa/errors.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Rukawa
2
- class DependentJobFailure < StandardError; end
2
+ class DependencyUnsatisfied < StandardError; end
3
3
  end
data/lib/rukawa/job.rb CHANGED
@@ -1,15 +1,37 @@
1
1
  require 'concurrent'
2
2
  require 'rukawa/abstract_job'
3
+ require 'rukawa/dependency'
4
+ require 'rukawa/state'
5
+ require 'active_support/core_ext/class'
3
6
 
4
7
  module Rukawa
5
8
  class Job < AbstractJob
6
9
  attr_accessor :in_comings, :out_goings
7
10
  attr_reader :state, :started_at, :finished_at
8
11
 
12
+ class_attribute :retryable, :retry_limit, :retry_exception_type, :retry_wait, instance_writer: false
13
+ class_attribute :dependency_type, instance_writer: false
14
+ self.dependency_type = Dependency::AllSuccess
15
+
16
+ class << self
17
+ def set_retryable(limit: 8, type: nil, wait: nil)
18
+ self.retryable = true
19
+ self.retry_limit = limit
20
+ self.retry_exception_type = type
21
+ self.retry_wait = wait
22
+ end
23
+
24
+ def set_dependency_type(name)
25
+ self.dependency_type = Rukawa::Dependency.get(name)
26
+ end
27
+ end
28
+
9
29
  def initialize(parent_job_net)
10
30
  @parent_job_net = parent_job_net
11
31
  @in_comings = Set.new
12
32
  @out_goings = Set.new
33
+ @retry_count = 0
34
+ @retry_wait = 1
13
35
  set_state(:waiting)
14
36
  end
15
37
 
@@ -42,7 +64,7 @@ module Rukawa
42
64
  @started_at = Time.now
43
65
  check_dependencies(results)
44
66
 
45
- if skip? || results.any?(&:skipped?)
67
+ if skip?
46
68
  Rukawa.logger.info("Skip #{self.class}")
47
69
  set_state(:skipped)
48
70
  else
@@ -54,7 +76,8 @@ module Rukawa
54
76
  end
55
77
  rescue => e
56
78
  handle_error(e)
57
- raise
79
+ Rukawa.logger.error("Retry #{self.class}")
80
+ retry
58
81
  ensure
59
82
  @finished_at = Time.now
60
83
  end
@@ -85,16 +108,44 @@ module Rukawa
85
108
  end
86
109
  end
87
110
 
111
+ def dependency_type
112
+ self.class.dependency_type
113
+ end
114
+
88
115
  def check_dependencies(results)
89
- unless results.all? { |r| !r.nil? }
116
+ dependency = dependency_type.new(*results)
117
+ unless dependency.resolve
90
118
  set_state(:aborted)
91
- raise DependentJobFailure
119
+ raise DependencyUnsatisfied
92
120
  end
93
121
  end
94
122
 
95
123
  def handle_error(e)
96
124
  Rukawa.logger.error("Error #{self.class} by #{e}")
97
- set_state(:error) unless e.is_a?(DependentJobFailure)
125
+ if retry?(e)
126
+ @retry_count += 1
127
+ set_state(:waiting)
128
+ sleep @retry_wait
129
+ @retry_wait = self.class.retry_wait ? self.class.retry_wait : @retry_wait * 2
130
+ else
131
+ set_state(:error) unless e.is_a?(DependencyUnsatisfied)
132
+ raise e
133
+ end
134
+ end
135
+
136
+ def retry?(e)
137
+ return false unless self.class.retryable
138
+
139
+ type_condition = case self.class.retry_exception_type
140
+ when Array
141
+ self.class.retry_exception_type.include?(e.class)
142
+ when Class
143
+ e.is_a?(self.class.retry_exception_type)
144
+ when nil
145
+ !e.is_a?(DependencyUnsatisfied)
146
+ end
147
+
148
+ type_condition && (self.class.retry_limit.nil? || self.class.retry_limit == 0 || @retry_count < self.class.retry_limit)
98
149
  end
99
150
 
100
151
  def store(key, value)
@@ -0,0 +1,58 @@
1
+ module Rukawa
2
+ module Overview
3
+ class << self
4
+ def list_job_net(with_jobs: false)
5
+ header = ["Job", "Desc"]
6
+ header << "Dependencies" if with_jobs
7
+ table = Terminal::Table.new headings: header do |t|
8
+ JobNet.descendants.each do |job_net|
9
+ list_table_row(t, job_net, job_net.dependencies, with_jobs: with_jobs)
10
+ end
11
+ end
12
+ puts table
13
+ end
14
+
15
+ def list_job
16
+ header = ["Job", "Desc"]
17
+ table = Terminal::Table.new headings: header do |t|
18
+ Job.descendants.each do |job|
19
+ row = [Paint[job.name, :bold, :underline], job.desc]
20
+ t << row
21
+ end
22
+ end
23
+ puts table
24
+ end
25
+
26
+ def list_table_row(table, job_net, level = 0, with_jobs: false)
27
+ row = [Paint[job_net.name, :bold, :underline], job_net.desc]
28
+ row << "" if with_jobs
29
+ table << row
30
+ if with_jobs
31
+ job_net.dependencies.each do |inner_j, deps|
32
+ table << [Paint["#{" "}#{inner_j.name}"], inner_j.desc, deps.join(", ")]
33
+ end
34
+ end
35
+ end
36
+
37
+ def display_running_status(root_job_net)
38
+ table = Terminal::Table.new headings: ["Job", "Status", "Elapsed Time"] do |t|
39
+ root_job_net.each_with_index do |j|
40
+ running_table_row(t, j)
41
+ end
42
+ end
43
+ puts table
44
+ end
45
+
46
+ def running_table_row(table, job, level = 0)
47
+ if job.is_a?(JobNet)
48
+ table << [Paint["#{" " * level}#{job.class}", :bold, :underline], Paint[job.state.colored, :bold, :underline], Paint[job.formatted_elapsed_time_from, :bold, :underline]]
49
+ job.each do |inner_j|
50
+ running_table_row(table, inner_j, level + 1)
51
+ end
52
+ else
53
+ table << [Paint["#{" " * level}#{job.class}", :bold], job.state.colored, job.formatted_elapsed_time_from]
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
data/lib/rukawa/runner.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'terminal-table'
2
2
  require 'paint'
3
+ require 'rukawa/overview'
3
4
 
4
5
  module Rukawa
5
6
  class Runner
@@ -18,19 +19,19 @@ module Rukawa
18
19
  Rukawa.logger.info("=== Start Rukawa ===")
19
20
  futures = @root_job_net.dataflows.each(&:execute)
20
21
  until futures.all?(&:complete?)
21
- display_table unless batch_mode
22
+ Overview.display_running_status(@root_job_net) unless batch_mode
22
23
  sleep refresh_interval
23
24
  end
24
25
  Rukawa.logger.info("=== Finish Rukawa ===")
25
26
 
26
- display_table unless batch_mode
27
+ Overview.display_running_status(@root_job_net) unless batch_mode
27
28
  puts "Finished #{@root_job_net.name} in #{@root_job_net.formatted_elapsed_time_from}"
28
29
 
29
30
  errors = futures.map(&:reason).compact
30
31
 
31
32
  unless errors.empty?
32
33
  errors.each do |err|
33
- next if err.is_a?(DependentJobFailure)
34
+ next if err.is_a?(DependencyUnsatisfied)
34
35
  Rukawa.logger.error(err)
35
36
  end
36
37
  return false
@@ -38,27 +39,5 @@ module Rukawa
38
39
 
39
40
  true
40
41
  end
41
-
42
- private
43
-
44
- def display_table
45
- table = Terminal::Table.new headings: ["Job", "Status", "Elapsed Time"] do |t|
46
- @root_job_net.each_with_index do |j|
47
- table_row(t, j)
48
- end
49
- end
50
- puts table
51
- end
52
-
53
- def table_row(table, job, level = 0)
54
- if job.is_a?(JobNet)
55
- table << [Paint["#{" " * level}#{job.class}", :bold, :underline], Paint[job.state.colored, :bold, :underline], Paint[job.formatted_elapsed_time_from, :bold, :underline]]
56
- job.each do |inner_j|
57
- table_row(table, inner_j, level + 1)
58
- end
59
- else
60
- table << [Paint["#{" " * level}#{job.class}", :bold], job.state.colored, job.formatted_elapsed_time_from]
61
- end
62
- end
63
42
  end
64
43
  end
data/lib/rukawa/state.rb CHANGED
@@ -16,6 +16,10 @@ module Rukawa::State
16
16
  other
17
17
  end
18
18
 
19
+ def success?
20
+ false
21
+ end
22
+
19
23
  %i(running? skipped? bypassed? error? aborted? waiting? finished?).each do |sym|
20
24
  define_method(sym) do
21
25
  false
@@ -66,6 +70,10 @@ module Rukawa::State
66
70
  :yellow
67
71
  end
68
72
 
73
+ def self.success?
74
+ true
75
+ end
76
+
69
77
  def self.bypassed?
70
78
  true
71
79
  end
@@ -138,6 +146,10 @@ module Rukawa::State
138
146
  :green
139
147
  end
140
148
 
149
+ def self.success?
150
+ true
151
+ end
152
+
141
153
  def self.finished?
142
154
  true
143
155
  end
@@ -1,3 +1,3 @@
1
1
  module Rukawa
2
- VERSION = "0.3.2"
2
+ VERSION = "0.3.3"
3
3
  end
data/lib/rukawa.rb CHANGED
@@ -3,7 +3,7 @@ require "concurrent"
3
3
  module Rukawa
4
4
  class << self
5
5
  def logger
6
- @logger ||= Logger.new(config.log_file)
6
+ config.logger
7
7
  end
8
8
 
9
9
  def store
@@ -24,9 +24,11 @@ module Rukawa
24
24
  end
25
25
  end
26
26
 
27
+ require 'active_support'
27
28
  require "rukawa/version"
28
29
  require 'rukawa/errors'
29
30
  require 'rukawa/state'
31
+ require 'rukawa/dependency'
30
32
  require 'rukawa/configuration'
31
33
  require 'rukawa/job_net'
32
34
  require 'rukawa/job'
data/rukawa.gemspec CHANGED
@@ -18,6 +18,7 @@ Gem::Specification.new do |spec|
18
18
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
19
  spec.require_paths = ["lib"]
20
20
 
21
+ spec.add_runtime_dependency "activesupport", ">= 4"
21
22
  spec.add_runtime_dependency "concurrent-ruby"
22
23
  spec.add_runtime_dependency "thor"
23
24
  spec.add_runtime_dependency "terminal-table"
@@ -27,4 +28,5 @@ Gem::Specification.new do |spec|
27
28
  spec.add_development_dependency "rake", "~> 10.0"
28
29
  spec.add_development_dependency "rspec", "~> 3.0"
29
30
  spec.add_development_dependency "rspec-power_assert"
31
+ spec.add_development_dependency "rspec-parameterized"
30
32
  end
@@ -12,19 +12,29 @@ class SampleJob < Rukawa::Job
12
12
  end
13
13
 
14
14
  class Job1 < SampleJob
15
+ set_description "Job1 description body"
15
16
  end
16
17
  class Job2 < SampleJob
18
+ def run
19
+ raise "job2 error"
20
+ end
17
21
  end
18
22
  class Job3 < SampleJob
19
23
  end
20
24
  class Job4 < SampleJob
25
+ # inherited by subclass
26
+ set_dependency_type :one_success
21
27
  end
22
28
  class Job5 < SampleJob
29
+ # inherited by subclass
30
+ set_retryable limit: 3, wait: 2, type: RuntimeError
31
+
23
32
  def run
24
33
  raise "job5 error"
25
34
  end
26
35
  end
27
36
  class Job6 < SampleJob
37
+ set_dependency_type :one_failed
28
38
  end
29
39
  class Job7 < SampleJob
30
40
  end
@@ -47,6 +57,7 @@ class InnerJob4 < SampleJob
47
57
  end
48
58
 
49
59
  class InnerJob5 < SampleJob
60
+ # inherited by subclass
50
61
  add_skip_rule ->(job) { job.is_a?(SampleJob) }
51
62
  end
52
63
 
data/sample/result.dot CHANGED
@@ -2,7 +2,7 @@ digraph "SampleJobNet" {
2
2
  label = "SampleJobNet";
3
3
  graph [rankdir = LR,nodesep = 0.8,concentrate = true];
4
4
  Job1 [style = filled,fillcolor = green];
5
- Job2 [style = filled,fillcolor = green];
5
+ Job2 [style = filled,fillcolor = red];
6
6
  Job3 [style = filled,fillcolor = green];
7
7
  Job4 [style = filled,fillcolor = green];
8
8
  subgraph "cluster_InnerJobNet" {
@@ -17,15 +17,15 @@ InnerJob2 [style = filled,fillcolor = red];
17
17
  }
18
18
  Job8 [style = filled,fillcolor = magenta];
19
19
  Job5 [style = filled,fillcolor = red];
20
- Job6 [style = filled,fillcolor = magenta];
21
- Job7 [style = filled,fillcolor = magenta];
20
+ Job6 [style = filled,fillcolor = green];
21
+ Job7 [style = filled,fillcolor = green];
22
22
  subgraph "cluster_InnerJobNet2" {
23
23
  label = "InnerJobNet2";
24
24
  graph [rankdir = LR,nodesep = 0.8,concentrate = true];
25
25
  color = blue;
26
26
  InnerJob4 [style = filled,fillcolor = green];
27
27
  InnerJob5 [style = filled,fillcolor = yellow];
28
- InnerJob6 [style = filled,fillcolor = yellow];
28
+ InnerJob6 [style = filled,fillcolor = magenta];
29
29
  "InnerJob4" -> "InnerJob5";
30
30
  "InnerJob4" -> "InnerJob6";
31
31
  "InnerJob5" -> "InnerJob6";
data/sample/result.png CHANGED
Binary file
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rukawa
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - joker1007
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-03-25 00:00:00.000000000 Z
11
+ date: 2016-04-10 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '4'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '4'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: concurrent-ruby
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -122,6 +136,20 @@ dependencies:
122
136
  - - ">="
123
137
  - !ruby/object:Gem::Version
124
138
  version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: rspec-parameterized
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
125
153
  description: Hyper simple job workflow engine
126
154
  email:
127
155
  - kakyoin.hierophant@gmail.com
@@ -144,9 +172,11 @@ files:
144
172
  - lib/rukawa/cli.rb
145
173
  - lib/rukawa/configuration.rb
146
174
  - lib/rukawa/dag.rb
175
+ - lib/rukawa/dependency.rb
147
176
  - lib/rukawa/errors.rb
148
177
  - lib/rukawa/job.rb
149
178
  - lib/rukawa/job_net.rb
179
+ - lib/rukawa/overview.rb
150
180
  - lib/rukawa/runner.rb
151
181
  - lib/rukawa/state.rb
152
182
  - lib/rukawa/version.rb