rukawa 0.3.2 → 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
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