fasten 0.7.2 → 0.7.4

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
  SHA256:
3
- metadata.gz: 11979aaa284fe109e187356c936bd43c51099e2cd19c2b2376b32bd272026940
4
- data.tar.gz: 1a3ac4ff25cf4beaf38e0964adf200a51c9556e3b743fd1074320a29d35eef99
3
+ metadata.gz: c4790a7db3f8bdbbaee848efc77a62dbc944338363a678c57b233e865df47b34
4
+ data.tar.gz: 87b97a2473f12e69ab2bd619264b25b7a01664997ee2ff140000d2ba7c68c5e7
5
5
  SHA512:
6
- metadata.gz: 616e6c45931550b4a9abd0b4484947758e3be7386d5a7ef53532b56f761cee58026978b71752f8631cd8ce8a105251a2736ecda0f0f5c9b3c83cf936669e8919
7
- data.tar.gz: bd0f916f1577983c3d5e51527a61c0e2f699c74c10706a94a3848339c65f784e66370fb6233631f4bd4bac1d6adb7171ec4bb0bca5aa9e50f4b12f6aed3c0014
6
+ metadata.gz: 4ac38b2b2b77e25c8b1911f41c94b091ccf48827b034c78ff9a939442a77004ca9821cd124aae32cc6ee099f344c605c70631ce6aaa5f2bd299150e9ae5a2149
7
+ data.tar.gz: 88294128e454055b9bd322ed3dfa9a7e86223ba191110041ab4ba55ab688ece163f549b470ae4fd58db4d6a16eb75aaf2b30ffb90f2e51f7288d410cb0e8a17a
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- fasten (0.7.2)
4
+ fasten (0.7.4)
5
5
  binding_of_caller
6
6
  hirb
7
7
  os
data/bin/console CHANGED
@@ -7,7 +7,7 @@ require 'fasten'
7
7
  # with your gem easier. You can also use a different console, if you like.
8
8
 
9
9
  # call reload! for reloading clases in development
10
- def reload!(base = 'fasten')
10
+ def reload!(base = 'a0-fasten-ruby')
11
11
  $LOADED_FEATURES.select { |feature| feature =~ %r{/#{base}/lib/} }.each do |feature|
12
12
  puts "Updating #{feature.gsub(/.*#{base}/, base)}: #{load feature}"
13
13
  end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fasten
4
+ class << self
5
+ def default_name
6
+ File.basename(Dir.getwd)
7
+ end
8
+
9
+ def default_stats
10
+ true
11
+ end
12
+
13
+ def default_summary
14
+ false
15
+ end
16
+
17
+ def default_workers
18
+ Parallel.physical_processor_count
19
+ end
20
+
21
+ def default_worker_class
22
+ Worker
23
+ end
24
+
25
+ def default_fasten_dir
26
+ 'fasten'
27
+ end
28
+
29
+ def default_use_threads
30
+ !OS.posix?
31
+ end
32
+
33
+ def default_ui_mode
34
+ return @default_ui_mode if defined? @default_ui_mode
35
+
36
+ require 'fasten/ui/curses'
37
+
38
+ @default_ui_mode = :curses
39
+ rescue StandardError, LoadError
40
+ @default_ui_mode = :console
41
+ end
42
+
43
+ def default_developer
44
+ STDIN.tty? && STDOUT.tty?
45
+ end
46
+ end
47
+ end
data/lib/fasten/runner.rb CHANGED
@@ -3,7 +3,6 @@ require 'parallel'
3
3
  require 'pry'
4
4
  require 'os'
5
5
 
6
- require 'fasten/support/dag'
7
6
  require 'fasten/support/logger'
8
7
  require 'fasten/support/state'
9
8
  require 'fasten/support/stats'
@@ -13,34 +12,29 @@ require 'fasten/timeout_queue'
13
12
 
14
13
  module Fasten
15
14
  class Runner
16
- include Fasten::Support::DAG
17
15
  include Fasten::Support::Logger
18
16
  include Fasten::Support::State
19
17
  include Fasten::Support::Stats
20
18
  include Fasten::Support::UI
21
19
  include Fasten::Support::Yaml
22
20
 
23
- attr_accessor :name, :workers, :worker_class, :fasten_dir, :developer, :stats, :summary, :ui_mode, :worker_list, :use_threads, :queue
21
+ attr_accessor :name, :stats, :summary, :workers, :worker_class, :fasten_dir, :use_threads, :ui_mode, :developer, :worker_list, :queue, :tasks
24
22
 
25
- def initialize(name: Fasten.default_name,
26
- developer: Fasten.default_developer, summary: nil, ui_mode: Fasten.default_ui_mode, workers: Fasten.default_workers,
27
- worker_class: Worker, fasten_dir: 'fasten', use_threads: !OS.posix?)
28
- reconfigure(name: name, developer: developer, summary: summary, ui_mode: ui_mode, workers: workers,
29
- worker_class: worker_class, fasten_dir: fasten_dir, use_threads: use_threads)
23
+ def initialize(**options)
24
+ %i[name stats summary workers worker_class fasten_dir use_threads ui_mode developer].each do |key|
25
+ options[key] = Fasten.send "default_#{key}" unless options.key? key
26
+ end
27
+
28
+ @tasks = TaskManager.new
29
+
30
+ reconfigure(options)
30
31
  end
31
32
 
32
33
  def reconfigure(**options)
33
- self.stats = options[:name] && true if options[:name] || options.key?(:stats)
34
- self.name = options[:name] || "#{self.class.to_s.gsub('::', '-')}-#{$PID}" if options.key?(:name)
35
- self.workers = options[:workers] if options.key?(:workers)
36
- self.worker_class = options[:worker_class] if options.key?(:worker_class)
37
- self.fasten_dir = options[:fasten_dir] if options.key?(:fasten_dir)
38
- self.developer = options[:developer] if options.key?(:developer)
39
- self.use_threads = options[:use_threads] if options.key?(:use_threads)
40
- self.summary = options[:summary] if options.key?(:summary)
41
- self.ui_mode = options[:ui_mode] if options.key?(:ui_mode)
42
-
43
- initialize_dag
34
+ %i[name stats summary workers worker_class fasten_dir use_threads ui_mode developer].each do |key|
35
+ send "#{key}=", options[key] if options.key? key
36
+ end
37
+
44
38
  initialize_stats
45
39
  initialize_logger
46
40
 
@@ -48,7 +42,9 @@ module Fasten
48
42
  end
49
43
 
50
44
  def task(name, **opts, &block)
51
- add Task.new(name: name, **opts, block: block)
45
+ tasks << task = Task.new(name: name, **opts, block: block)
46
+
47
+ task
52
48
  end
53
49
 
54
50
  def register(&block)
@@ -64,7 +60,7 @@ module Fasten
64
60
  perform_loop
65
61
  end
66
62
 
67
- self.state = task_list.map(&:state).all?(:DONE) ? :DONE : :FAIL
63
+ self.state = tasks.map(&:state).all?(:DONE) ? :DONE : :FAIL
68
64
  log_fin self, running_counters
69
65
 
70
66
  stats_add_entry(state, self)
@@ -76,20 +72,20 @@ module Fasten
76
72
 
77
73
  def map(list, &block)
78
74
  list.each do |item|
79
- add Fasten::Task.new name: item.to_s, request: item, block: block
75
+ task item.to_s, request: item, &block
80
76
  end
81
77
 
82
78
  perform
83
79
 
84
- task_list.map(&:response)
80
+ tasks.map(&:response)
85
81
  end
86
82
 
87
83
  def done_counters
88
- "#{task_done_list.count}/#{task_list.count}"
84
+ "#{tasks.done.count}/#{tasks.count}"
89
85
  end
90
86
 
91
87
  def running_counters
92
- "#{task_done_list.count + task_running_list.count}/#{task_list.count}"
88
+ "#{tasks.done.count + tasks.running.count}/#{tasks.count}"
93
89
  end
94
90
 
95
91
  def perform_loop
@@ -103,25 +99,25 @@ module Fasten
103
99
  dispatch_pending_tasks
104
100
  end
105
101
 
106
- break if no_running_tasks? && no_waiting_tasks? || state == :QUIT
102
+ break if tasks.no_running? && tasks.no_waiting? || state == :QUIT
107
103
  end
108
104
 
109
105
  remove_all_workers
110
106
  end
111
107
 
112
108
  def check_state
113
- if state == :PAUSING && no_running_tasks?
109
+ if state == :PAUSING && tasks.no_running?
114
110
  self.state = :PAUSED
115
111
  ui.message = nil
116
112
  ui.force_clear
117
- elsif state == :QUITTING && no_running_tasks?
113
+ elsif state == :QUITTING && tasks.no_running?
118
114
  self.state = :QUIT
119
115
  ui.force_clear
120
116
  end
121
117
  end
122
118
 
123
119
  def should_wait_for_running_tasks?
124
- tasks_running? && (no_waiting_tasks? || tasks_failed? || %i[PAUSING QUITTING].include?(state)) || task_running_list.count >= workers
120
+ tasks.running? && (tasks.no_waiting? || tasks.failed? || %i[PAUSING QUITTING].include?(state)) || tasks.running.count >= workers
125
121
  end
126
122
 
127
123
  def wait_for_running_tasks
@@ -134,21 +130,20 @@ module Fasten
134
130
  while should_wait_for_running_tasks?
135
131
  ui.update
136
132
 
137
- tasks = queue.receive_with_timeout(0.5)
138
-
139
- receive_workers_tasks_thread(tasks)
133
+ receive_workers_tasks_thread queue.receive_with_timeout(0.5)
140
134
  end
141
135
 
142
136
  ui.update
143
137
  end
144
138
 
145
- def receive_workers_tasks_thread(tasks)
146
- tasks&.each do |task|
147
- task_running_list.delete task
139
+ def receive_workers_tasks_thread(items)
140
+ items&.each do |task|
141
+ tasks.running.delete task
148
142
 
149
143
  task.worker.running_task = task.worker.state = nil
150
144
 
151
- update_task task
145
+ tasks.update task
146
+ stats_add_entry(task.state, task)
152
147
 
153
148
  log_fin task, done_counters
154
149
  ui.force_clear
@@ -173,9 +168,10 @@ module Fasten
173
168
 
174
169
  task = worker.receive_response_from_child
175
170
 
176
- task_running_list.delete task
171
+ tasks.running.delete task
177
172
 
178
- update_task task
173
+ tasks.update task
174
+ stats_add_entry(task.state, task)
179
175
 
180
176
  log_fin task, done_counters
181
177
  ui.force_clear
@@ -189,7 +185,7 @@ module Fasten
189
185
  end
190
186
 
191
187
  def raise_error_in_failure
192
- return unless tasks_failed?
188
+ return unless tasks.failed?
193
189
 
194
190
  show_error_tasks
195
191
 
@@ -238,13 +234,13 @@ module Fasten
238
234
  end
239
235
 
240
236
  def dispatch_pending_tasks
241
- while tasks_waiting? && task_running_list.count < workers
237
+ while tasks.waiting? && tasks.running.count < workers
242
238
  worker = find_or_create_worker
243
239
 
244
- task = next_task
240
+ task = tasks.next
245
241
  log_ini task, "on worker #{worker}"
246
242
  worker.send_request_to_child(task)
247
- task_running_list << task
243
+ tasks.running << task
248
244
 
249
245
  ui.force_clear
250
246
  end
@@ -25,7 +25,7 @@ module Fasten
25
25
  stats_data << row.to_h
26
26
  end
27
27
 
28
- @task_waiting_list = nil
28
+ @tasks.waiting = nil
29
29
  rescue StandardError
30
30
  nil
31
31
  end
@@ -127,10 +127,10 @@ module Fasten
127
127
  end
128
128
 
129
129
  def update_stats(history, entry)
130
- entry['cnt'] = count = history.size
131
- entry['avg'] = avg = history.sum.to_f / count
132
- entry['std'] = std = Math.sqrt(history.inject(0.0) { |v, x| v + (x - avg)**2 })
133
- entry['err'] = std / Math.sqrt(count) if count.positive?
130
+ entry['cnt'] = cnt = history.size
131
+ entry['avg'] = avg = history.sum.to_f / cnt
132
+ entry['std'] = std = Math.sqrt(history.map { |x| (x - avg)**2 }.sum / cnt)
133
+ entry['err'] = std / Math.sqrt(cnt) if cnt.positive?
134
134
  end
135
135
  end
136
136
  end
@@ -13,7 +13,7 @@ module Fasten
13
13
  params = {}
14
14
  end
15
15
 
16
- add Fasten::Task.new({ name: name }.merge(params))
16
+ task name, params
17
17
  end
18
18
 
19
19
  log_info "Loaded #{items.count} tasks from #{path}"
@@ -22,7 +22,7 @@ module Fasten
22
22
  def save_yaml(path)
23
23
  keys = %i[after shell]
24
24
 
25
- items = task_list.map do |task|
25
+ items = tasks.map do |task|
26
26
  data = task.to_h.select do |key, _val|
27
27
  keys.include? key
28
28
  end
data/lib/fasten/task.rb CHANGED
@@ -7,7 +7,7 @@ module Fasten
7
7
  attr_accessor :name, :after, :shell, :ruby
8
8
  attr_accessor :dependants, :depends, :request, :response, :worker, :run_score, :block
9
9
 
10
- def initialize(name: nil, shell: nil, ruby: nil, block: nil, request: nil, after: nil)
10
+ def initialize(name:, shell: nil, ruby: nil, block: nil, request: nil, after: nil)
11
11
  self.name = name
12
12
  self.shell = shell
13
13
  self.ruby = ruby
@@ -0,0 +1,130 @@
1
+ module Fasten
2
+ class TaskManager < Array
3
+ attr_reader :done, :failed, :pending, :running, :targets
4
+
5
+ def initialize(targets: nil)
6
+ super()
7
+
8
+ @map = {}
9
+ @done = []
10
+ @failed = []
11
+ @pending = []
12
+ @running = []
13
+ @targets = targets
14
+ @waiting = nil
15
+ end
16
+
17
+ def push(*items)
18
+ items.each do |item|
19
+ self << item
20
+ end
21
+
22
+ self
23
+ end
24
+
25
+ def <<(task)
26
+ raise "Object class #{task.class} not allowed" unless task.is_a? Task
27
+ raise "Task '#{task.name}' already defined" if @map[task.name]
28
+
29
+ @map[task.name] = task
30
+ @waiting = nil
31
+ super
32
+ end
33
+
34
+ def next
35
+ waiting.shift
36
+ end
37
+
38
+ def update(task)
39
+ pending.delete task
40
+
41
+ if task.state == :DONE
42
+ done << task
43
+ task.dependants.each { |dependant_task| dependant_task.depends.delete task }
44
+
45
+ move_pending_to_waiting
46
+ else
47
+ error << task
48
+ end
49
+ end
50
+
51
+ def waiting
52
+ return @waiting if @waiting
53
+
54
+ reset
55
+ setup_dependencies
56
+ setup_scores
57
+ move_pending_to_waiting
58
+ end
59
+
60
+ def no_waiting?
61
+ waiting.empty?
62
+ end
63
+
64
+ def no_running?
65
+ running.empty?
66
+ end
67
+
68
+ def waiting?
69
+ !waiting.empty?
70
+ end
71
+
72
+ def running?
73
+ !running.empty?
74
+ end
75
+
76
+ def failed?
77
+ !failed.empty?
78
+ end
79
+
80
+ protected
81
+
82
+ def reset
83
+ by_state = group_by(&:state)
84
+
85
+ @done = by_state.delete(:DONE) || []
86
+ @failed = by_state.delete(:FAIL) || []
87
+ @running = by_state.delete(:RUNNING) || []
88
+ @waiting = []
89
+
90
+ return unless @targets.nil? || @targets.empty?
91
+
92
+ @pending = by_state.values.flatten.each do |task|
93
+ task.depends = []
94
+ task.dependants = []
95
+ task.state = nil
96
+ end
97
+ end
98
+
99
+ def setup_dependencies
100
+ @pending.each do |task|
101
+ next unless task.after
102
+
103
+ [task.after].flatten.each do |after|
104
+ after_task = after.is_a?(Task) ? after : @map[after]
105
+ raise "Dependency task '#{after}' not found on task '#{task.name}'." unless after_task
106
+
107
+ task.depends << after_task
108
+ after_task.dependants << task
109
+ end
110
+ end
111
+ end
112
+
113
+ def setup_scores
114
+ @pending.each do |task|
115
+ task.run_score = task.dependants.count
116
+ end
117
+ end
118
+
119
+ def move_pending_to_waiting
120
+ to_move = pending.select { |task| task.depends.count.zero? }
121
+
122
+ @pending -= to_move
123
+ @waiting += to_move
124
+ @waiting.sort_by!.with_index do |x, index|
125
+ x.state = :WAIT
126
+ [-x.run_score, index]
127
+ end
128
+ end
129
+ end
130
+ end
@@ -5,17 +5,15 @@ module Fasten
5
5
  class Console
6
6
  extend Forwardable
7
7
 
8
- def_delegators :runner, :worker_list, :task_list, :task_done_list, :task_error_list, :task_running_list, :task_waiting_list, :worker_list
8
+ def_delegators :runner, :worker_list, :tasks, :worker_list
9
9
  def_delegators :runner, :name, :workers, :workers=, :state, :state=, :hformat
10
10
 
11
11
  attr_accessor :runner
12
12
 
13
13
  def initialize(runner:)
14
14
  @runner = runner
15
- @old = {
16
- task_done_list: [],
17
- task_error_list: []
18
- }
15
+ @old_done = []
16
+ @old_failed = []
19
17
  end
20
18
 
21
19
  def setup
@@ -33,8 +31,9 @@ module Fasten
33
31
 
34
32
  def update
35
33
  setup unless @setup_done
36
- display_task_message(task_done_list, @old[:task_done_list], 'Done in')
37
- display_task_message(task_error_list, @old[:task_error_list], 'Fail in')
34
+
35
+ display_task_message(tasks.done, @old_done, 'Done in')
36
+ display_task_message(tasks.failed, @old_failed, 'Fail in')
38
37
  end
39
38
 
40
39
  def cleanup
@@ -9,7 +9,7 @@ module Fasten
9
9
  include ::Curses
10
10
  extend Forwardable
11
11
 
12
- def_delegators :runner, :worker_list, :task_list, :task_done_list, :task_error_list, :task_running_list, :task_waiting_list, :worker_list
12
+ def_delegators :runner, :worker_list, :tasks, :worker_list
13
13
  def_delegators :runner, :name, :workers, :workers=, :state, :state=
14
14
 
15
15
  attr_accessor :n_rows, :n_cols, :selected, :sel_index, :clear_needed, :message, :runner
@@ -106,11 +106,11 @@ module Fasten
106
106
  self.workers += 1
107
107
  self.message = "Increasing workers to #{workers}"
108
108
  elsif key == Curses::Key::DOWN
109
- self.sel_index = sel_index ? [sel_index + 1, task_list.count - 1].min : 0
110
- self.selected = task_list[sel_index]
109
+ self.sel_index = sel_index ? [sel_index + 1, tasks.count - 1].min : 0
110
+ self.selected = tasks[sel_index]
111
111
  elsif key == Curses::Key::UP
112
- self.sel_index = sel_index ? [sel_index - 1, 0].max : task_list.count - 1
113
- self.selected = task_list[sel_index]
112
+ self.sel_index = sel_index ? [sel_index - 1, 0].max : tasks.count - 1
113
+ self.selected = tasks[sel_index]
114
114
  elsif key == 'q'
115
115
  self.message = 'Will quit when running tasks end'
116
116
  self.state = :QUITTING
@@ -125,8 +125,8 @@ module Fasten
125
125
  end
126
126
 
127
127
  def ui_workers_summary
128
- running_count = task_running_list.count
129
- waiting_count = task_waiting_list.count
128
+ running_count = tasks.running.count
129
+ waiting_count = tasks.waiting.count
130
130
  workers_count = worker_list.count
131
131
 
132
132
  "Procs running: #{running_count} idle: #{workers_count - running_count} waiting: #{waiting_count} #{runner.use_threads ? 'threads' : 'processes'}: #{workers}"
@@ -196,15 +196,18 @@ module Fasten
196
196
 
197
197
  def ui_task_color(task)
198
198
  rev = task == selected ? A_REVERSE : 0
199
+
199
200
  case task.state
200
201
  when :RUNNING
201
202
  color_pair(1) | A_TOP | rev
202
- when :FAIL
203
- color_pair(3) | A_TOP | rev
204
203
  when :DONE
205
204
  color_pair(2) | A_TOP | rev
205
+ when :FAIL
206
+ color_pair(3) | A_TOP | rev
207
+ when :WAIT
208
+ A_TOP | rev
206
209
  else
207
- task_waiting_list.include?(task) ? A_TOP | rev : color_pair(4) | A_DIM | rev
210
+ color_pair(4) | A_DIM | rev
208
211
  end
209
212
  end
210
213
 
@@ -228,8 +231,8 @@ module Fasten
228
231
  worker.spinner = (worker.spinner + 1) % SPINNER_LEN if worker.running?
229
232
  end
230
233
 
231
- count_done = task_done_list.count
232
- count_total = task_list.count
234
+ count_done = tasks.done.count
235
+ count_total = tasks.count
233
236
  tl = count_total.to_s.length
234
237
  col_ini = ui_text_aligned(2, :left, format("Tasks %#{tl}d/%d", count_done, count_total)) + 1
235
238
  col_fin = n_cols - 5
@@ -238,7 +241,7 @@ module Fasten
238
241
  ui_progressbar(2, col_ini, col_fin, count_done, count_total)
239
242
 
240
243
  max = 2
241
- list = task_list.sort_by.with_index { |x, index| [x.run_score, index] }
244
+ list = tasks.sort_by.with_index { |x, index| [x.run_score, index] }
242
245
  list.each_with_index do |task, index|
243
246
  next if 3 + index >= n_rows
244
247
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Fasten
4
- VERSION = '0.7.2'
4
+ VERSION = '0.7.4'
5
5
  end
data/lib/fasten.rb CHANGED
@@ -2,10 +2,13 @@
2
2
 
3
3
  require 'optparse'
4
4
  require 'fasten/task'
5
+ require 'fasten/task_manager'
5
6
  require 'fasten/runner'
6
7
  require 'fasten/worker'
7
8
  require 'fasten/version'
8
9
 
10
+ require 'fasten/defaults'
11
+
9
12
  module Fasten
10
13
  class << self
11
14
  def runner_from_yaml(path, **options)
@@ -35,28 +38,6 @@ module Fasten
35
38
  runner(**options).register(&block)
36
39
  end
37
40
 
38
- def default_name
39
- File.basename(Dir.getwd)
40
- end
41
-
42
- def default_workers
43
- Parallel.physical_processor_count
44
- end
45
-
46
- def default_developer
47
- STDIN.tty? && STDOUT.tty?
48
- end
49
-
50
- def default_ui_mode
51
- return @default_ui_mode if defined? @default_ui_mode
52
-
53
- require 'fasten/ui/curses'
54
-
55
- @default_ui_mode = :curses
56
- rescue StandardError, LoadError
57
- @default_ui_mode = :console
58
- end
59
-
60
41
  def load_fasten(args)
61
42
  args.each do |path|
62
43
  if File.directory? path
@@ -107,10 +88,10 @@ module Fasten
107
88
  opts.on '--ui=UI', String, "Type of UI: curses, console. (default: #{default_ui_mode} on this machine)" do |ui_mode|
108
89
  @options[:ui_mode] = ui_mode
109
90
  end
110
- opts.on '-t', '--threads', 'Use threads workers for parallel execution' do
91
+ opts.on '-t', '--threads', "Use threads workers for parallel execution#{default_use_threads && ' (default on this machine)' || nil}" do
111
92
  @options[:use_threads] = true
112
93
  end
113
- opts.on '-p', '--processes', 'Use process workers for parallel execution' do
94
+ opts.on '-p', '--processes', "Use process workers for parallel execution#{!default_use_threads && ' (default on this machine)' || nil}" do
114
95
  @options[:use_threads] = false
115
96
  end
116
97
  opts.on '-v', '--version', 'Display version info' do
@@ -118,15 +99,14 @@ module Fasten
118
99
  exit 0
119
100
  end
120
101
  opts.on_tail '-h', '--help', 'Shows this help' do
121
- puts opts
122
- exit 0
102
+ show_help
123
103
  end
124
104
  end
125
105
  end
126
106
 
127
- def show_help
107
+ def show_help(exit_code = 0)
128
108
  puts opt_parser
129
- exit 1
109
+ exit exit_code
130
110
  end
131
111
 
132
112
  def invoke
@@ -135,7 +115,7 @@ module Fasten
135
115
  runner @options
136
116
  load_fasten @load_path
137
117
 
138
- show_help if runner.task_list.empty?
118
+ show_help 1 if runner.tasks.empty?
139
119
 
140
120
  runner.perform
141
121
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fasten
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.2
4
+ version: 0.7.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aldrin Martoq
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-11-13 00:00:00.000000000 Z
11
+ date: 2018-11-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -175,9 +175,9 @@ files:
175
175
  - exe/fasten
176
176
  - fasten.gemspec
177
177
  - lib/fasten.rb
178
+ - lib/fasten/defaults.rb
178
179
  - lib/fasten/runner.rb
179
180
  - lib/fasten/std_thread_proxy.rb
180
- - lib/fasten/support/dag.rb
181
181
  - lib/fasten/support/fork_worker.rb
182
182
  - lib/fasten/support/logger.rb
183
183
  - lib/fasten/support/state.rb
@@ -186,6 +186,7 @@ files:
186
186
  - lib/fasten/support/ui.rb
187
187
  - lib/fasten/support/yaml.rb
188
188
  - lib/fasten/task.rb
189
+ - lib/fasten/task_manager.rb
189
190
  - lib/fasten/timeout_queue.rb
190
191
  - lib/fasten/ui/console.rb
191
192
  - lib/fasten/ui/curses.rb
@@ -1,130 +0,0 @@
1
- module Fasten
2
- module Support
3
- module DAG
4
- attr_reader :task_map, :task_list, :task_done_list, :task_error_list, :task_pending_list, :task_running_list
5
-
6
- def initialize_dag
7
- @task_map ||= {}
8
- @task_list ||= []
9
- @task_done_list ||= []
10
- @task_error_list ||= []
11
- @task_pending_list ||= []
12
- @task_running_list ||= []
13
-
14
- nil
15
- end
16
-
17
- def add(task)
18
- raise "Task '#{task.name}' already defined" if @task_map[task.name]
19
-
20
- @task_map[task.name] = task
21
- @task_list << task
22
- @task_waiting_list = nil
23
- end
24
-
25
- def update_task(task)
26
- task.state == :DONE ? update_done_task(task) : update_error_task(task)
27
-
28
- stats_add_entry(task.state, task)
29
- end
30
-
31
- def update_done_task(task)
32
- @task_done_list << task
33
- @task_pending_list.delete task
34
- task.dependants.each { |dependant_task| dependant_task.depends.delete task }
35
-
36
- move_pending_to_waiting
37
- end
38
-
39
- def update_error_task(task)
40
- @task_error_list << task
41
- @task_pending_list.delete task
42
- end
43
-
44
- def next_task
45
- task_waiting_list.shift
46
- end
47
-
48
- def task_waiting_list
49
- return @task_waiting_list if @task_waiting_list
50
-
51
- reset_tasks
52
- setup_tasks_dependencies
53
- setup_tasks_scores
54
- move_pending_to_waiting
55
- end
56
-
57
- protected
58
-
59
- def move_pending_to_waiting
60
- move_list = task_pending_list.select { |task| task.depends.count.zero? }
61
-
62
- @task_waiting_list ||= []
63
- @task_pending_list -= move_list
64
- @task_waiting_list += move_list
65
- @task_waiting_list.sort_by!.with_index do |x, index|
66
- x.state = :WAIT
67
- [-x.run_score, index]
68
- end
69
- end
70
-
71
- def reset_tasks
72
- @task_pending_list.clear
73
- @task_done_list.clear
74
- @task_error_list.clear
75
-
76
- @task_list.each do |task|
77
- task.dependants = []
78
- task.depends = []
79
-
80
- if task.state == :DONE
81
- @task_done_list << task
82
- elsif task.state == :FAIL
83
- @task_error_list << task
84
- else
85
- task.state = :IDLE
86
- @task_pending_list << task
87
- end
88
- end
89
- end
90
-
91
- def setup_tasks_dependencies
92
- @task_pending_list.each do |task|
93
- next unless task.after
94
-
95
- [task.after].flatten.each do |after|
96
- after_task = after.is_a?(Task) ? after : @task_map[after]
97
- raise "Dependency task '#{after}' not found on task '#{task.name}'." unless after_task
98
-
99
- task.depends << after_task
100
- after_task.dependants << task
101
- end
102
- end
103
- end
104
-
105
- def setup_tasks_scores
106
- @task_pending_list.each { |task| task.run_score = task.dependants.count }
107
- end
108
-
109
- def no_waiting_tasks?
110
- task_waiting_list.empty?
111
- end
112
-
113
- def no_running_tasks?
114
- task_running_list.empty?
115
- end
116
-
117
- def tasks_waiting?
118
- !task_waiting_list.empty?
119
- end
120
-
121
- def tasks_running?
122
- !task_running_list.empty?
123
- end
124
-
125
- def tasks_failed?
126
- !task_error_list.empty?
127
- end
128
- end
129
- end
130
- end