vete 0.2.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. checksums.yaml +4 -4
  2. data/lib/vete.rb +64 -49
  3. data/test/example.rb +4 -2
  4. data/test/vete.gif +0 -0
  5. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1d1ef6e5614f544a633cfe36109f37ef7a37676b7ba276be48abcc40d6e9cf54
4
- data.tar.gz: a0036c27a47eddba9385673345f4456fbae869fa816c8c2c0d46ce92a0866d82
3
+ metadata.gz: 9e19484c6c02cd403365def0a14367e2c31f302edd7b56842e863162d0178730
4
+ data.tar.gz: 303793b8c478fe08733f2da221a325d66e68b2d3ab54c89105482ef612866953
5
5
  SHA512:
6
- metadata.gz: a0f287195bba7b81a368560aa3f0694b60e7afe8292957b9d947ca820291b603bdfc3d231bd9432c175a4f3df88714eba91b7a41db5dea744154e063000d2e42
7
- data.tar.gz: 0aeb6cfa54c5a55d6b822ce29e5045f78176b428bd2948fd039ea5dce5096d42a0d7dd6e8b04ce2c2631fb28bd02480f79e5c75fdb8a489e729f614ae191c428
6
+ metadata.gz: 59e65ecb548ffa4ccc95f4928f83cb036cefaae98e447801c03616627557614f871f24442b331fd1f6d1211beaf8559f7b98870ea3e31a316ab22af6041d438f
7
+ data.tar.gz: 03aef3e49b3ee52dbd6867adee656d67fb6124f3eabc027732d35be04e46b0db0139a59abfc00d64079d2f4ce95b6d2cb24cb7e1f752283168196f965e028adb
data/lib/vete.rb CHANGED
@@ -13,16 +13,20 @@ require "fileutils"
13
13
  require "optparse"
14
14
  require "thread"
15
15
 
16
- trap("INT" ) { print clear + go; abort "\n" }
16
+ @pid = Process.pid
17
+
18
+ trap("INT" ) { print clear + go; abort "\n" }
19
+ trap("WINCH") { print clear or draw if @pid == Process.pid }
17
20
 
18
21
  OptionParser.new.instance_eval do
19
- @version = "0.2.0"
22
+ @version = "0.6.0"
20
23
  @banner = "usage: #{program_name} [options]"
21
24
 
22
25
  on "-b", "--bar <width>" , "Progress bar width, in characters", Integer
23
26
  on "-c", "--char <character>" , "Character to use for progress bar", String
24
- on "-r", "--reset" , "Remove directory used for job processing and quit"
27
+ on "-d", "--delay <mode>" , "Delay mode (rand, task, numeric)"
25
28
  on "-h", "--help" , "Show help and command usage" do Kernel.abort to_s; end
29
+ on "-r", "--reset" , "Remove directory used for job processing and quit"
26
30
  on "-v", "--version" , "Show version number" do Kernel.abort "#{program_name} #{@version}"; end
27
31
  on "-w", "--workers <count>" , "Set the number of workers (default is 1)", Integer
28
32
 
@@ -31,17 +35,27 @@ end.parse!(into: opts={}) rescue abort($!.message)
31
35
 
32
36
  # populate CLI options
33
37
  @char = opts[:char ] || "•"; @char = @char[0]
38
+ @wait = opts[:delay ]
34
39
  @nuke = opts[:reset ]
35
40
  @wide = opts[:bar ] || 20
36
41
  @work = opts[:workers] || 1
37
42
 
43
+ # handle wait mode
44
+ case @wait
45
+ when "rand", "task", nil
46
+ when /\A(?:0|[1-9]\d*|(?:0?\.|[1-9]\d*\.)\d*)\z/
47
+ @wait = @wait.to_f
48
+ @wait > 0 or abort "invalid delay time (#{@wait.to_f} secs)"
49
+ else
50
+ abort "invalid delay mode '#{@wait}'"
51
+ end
52
+
38
53
  # define job directories
39
54
  @vete = File.expand_path(".vete")
40
55
  @todo = File.join(@vete, "todo")
41
56
  @live = File.join(@vete, "live")
42
57
  @done = File.join(@vete, "done")
43
- @bomb = File.join(@vete, "bomb")
44
-
58
+ @died = File.join(@vete, "died")
45
59
 
46
60
  def move(path, dest)
47
61
  dest = File.join(dest, File.basename(path))
@@ -59,27 +73,27 @@ end
59
73
 
60
74
  def vete_init
61
75
  nuke
62
- list = [@todo, @live, @done, @bomb]
63
- list.each {|path| File.mkdir_p(path, force: true, secure: true) }
76
+ list = [@todo, @live, @done, @died]
77
+ list.each {|path| FileUtils.mkdir_p(path) }
64
78
  end
65
79
 
66
80
  def vete_retry
67
- list = Dir.glob(File.join(@bomb, "*")).sort.each {|path| FileUtils.touch(path) }
81
+ list = Dir.glob(File.join(@died, "*")).sort.each {|path| FileUtils.touch(path) }
68
82
  move(list, @todo)
69
83
  end
70
84
 
71
85
  def vete_todo(path)
72
- FileUtils.touch(path, force: true, secure: true)
86
+ FileUtils.touch(File.join(@todo, path.to_s))
73
87
  end
74
88
 
75
89
  # ==[ Drawing ]===============================================================
76
90
 
77
91
  # https://www.cse.psu.edu/~kxc104/class/cmpen472/16f/hw/hw8/vt100ansi.htm
78
92
 
79
- def clear ; "\e[2J" ; end
80
- def cursor(on) ; print on ? "\e[?25h": "\e[?25l"; end
81
- def go(r=1,c=1); "\e[#{r};#{c}H" ; end
82
- def go!(...) ; print go(...) ; end
93
+ def clear(line=nil); line ? "\e[K" : "\e[2J" ; end
94
+ def cursor(on) ; print on ? "\e[?25h": "\e[?25l"; end
95
+ def go(r=1,c=1) ; "\e[#{r};#{c}H" ; end
96
+ def go!(...) ; print go(...) ; end
83
97
 
84
98
  def fg(rgb=nil); rgb ? "\e[38;2;#{hx(rgb)}m" : "\e[39m"; end
85
99
  def bg(rgb=nil); rgb ? "\e[48;2;#{hx(rgb)}m" : "\e[49m"; end
@@ -88,56 +102,49 @@ def hx(str=nil); str =~ /\A#?(?:(\h\h)(\h\h)(\h\h)|(\h)(\h)(\h))\z/ or return
88
102
  [r.hex, g.hex, b.hex] * ";"
89
103
  end
90
104
 
91
- def draw(rows, done=0, live=0, bomb=0, jobs=0, info=nil)
105
+ def draw(live=0, done=0, died=0, jobs=0, info=nil)
92
106
 
93
107
  # outer box
94
108
  unless info
95
109
  print [
96
110
  clear,
97
- go(2 + rows, @len + 3) + "└" + "─" * (@wide + 2) + "┘\n",
98
- go(1 , @len + 3) + "┌" + "─" * (@wide + 2) + "┐\n",
111
+ go(2 + @work, @len + 3) + "└" + "─" * (@wide + 2) + "┘\n",
112
+ go(1 , @len + 3) + "┌" + "─" * (@wide + 2) + "┐\n",
99
113
  ].join
100
- rows.times {|i| print " %*d │ %*s │\n" % [@len, i + 1, @wide, ""] }
114
+ @work.times {|i| print " %*d │ %*s │\n" % [@len, i + 1, @wide, ""] }
101
115
  return
102
116
  end
103
117
 
104
118
  # worker bars
105
- dpct = done.to_f / jobs
106
- lpct = live.to_f / jobs
119
+ ppct = (done + died).to_f / jobs
107
120
  most = info.values.max
108
121
  info.each do |slot, this|
109
122
  tpct = this.to_f / most
110
- cols = dpct * tpct * @wide
123
+ cols = ppct * tpct * @wide
111
124
  print go(slot + 1, @len + 5) + bg("5383ec") + @char * cols
112
125
  end
113
126
 
114
127
  # summary bar
128
+ dpct = done.to_f / jobs
129
+ lpct = live.to_f / jobs
115
130
  gcol = dpct * @wide
116
131
  ycol = lpct * @wide
117
132
  print [
118
- go(rows + 3, @len + 5),
133
+ go(@work + 3, @len + 5),
119
134
  fg("fff"),
120
135
  bg("58a65c") + @char * ( gcol ) , # green (done)
121
- bg("f1bf42") + @char * ( ycol) , # yellow (live) <= Add live
122
- bg("d85140") + " " * (@wide - gcol - ycol).ceil, # red (left)
123
- go(rows + 3, @len + 5 + @wide + 3) + " %.1f%% done " % [dpct * 100],
124
- bomb == 0 ? nil : (bg + " " + bg("f1bf42") + " #{bomb} bombed "),
136
+ bg("f1bf42") + @char * ( ycol) , # yellow (live)
137
+ bg("d85140") + " " * (@wide - gcol - ycol).ceil, # red (rest)
138
+ go(@work + 3, @len + 5 + @wide + 3) , # scoot over...
139
+ bg("5383ec") + " %.1f%% " % [ppct * 100], # blue (done + died)
140
+ done > 0 ? (bg + " " + bg("58a65c") + " #{done} done ") : nil,
141
+ died > 0 ? (bg + " " + bg("d85140") + " #{died} died ") : nil,
125
142
  ].join
126
143
 
127
144
  # clear colors
128
145
  print fg + bg
129
146
  end
130
147
 
131
- # ==[ Simulate job creation, add helpers so vete makes this easy ]============
132
-
133
- FileUtils.rm_rf @vete
134
- FileUtils.mkdir_p @todo
135
- FileUtils.mkdir_p @live
136
- FileUtils.mkdir_p @done
137
- FileUtils.mkdir_p @bomb
138
-
139
- 1.upto(100) {|i| FileUtils.touch(File.join(@todo, i.to_s)) }
140
-
141
148
  # ==[ Configure workers ]=====================================================
142
149
 
143
150
  @len = @work.to_s.size
@@ -145,47 +152,55 @@ FileUtils.mkdir_p @bomb
145
152
  @que = Thread::Queue.new; @work.times {|slot| @que << (slot + 1) }
146
153
 
147
154
  begin
155
+ setup if defined?(setup)
156
+
148
157
  list = Dir[File.join(@todo, "*")]
158
+
159
+ live = 0
160
+ done = 0
161
+ died = 0
149
162
  jobs = list.size
150
163
  info = Hash.new(0)
151
164
 
152
- setup
153
-
154
165
  cursor(false)
155
- draw(@work)
166
+ draw
156
167
 
157
168
  time = Time.now
158
- done = 0
159
- live = 0
160
- bomb = 0
161
169
  Thread.new do
162
- list.each do |path|
170
+ list.each_with_index do |path, task|
163
171
  slot = @que.pop
164
172
  @mtx.synchronize {
165
173
  live += 1
166
174
  }
167
175
  show = "Working on task " + File.basename(path)
168
- print go(slot + 1, @len + 5 + @wide + 3) + show
176
+ print go(slot + 1, @len + 5 + @wide + 3) + show + clear(true)
169
177
  if chld = fork # parent
170
178
  Thread.new do
171
179
  okay = Process.waitpid2(chld)[1] == 0
172
- move(path, okay ? @done : @bomb)
180
+ move(path, okay ? @done : @died)
173
181
  @que.push(slot)
174
182
  @mtx.synchronize {
175
- done += 1
176
183
  live -= 1
177
- bomb += 1 unless okay
184
+ okay ? (done += 1) : (died += 1)
178
185
  info[slot] += 1
179
186
  }
180
187
  end
181
- draw(@work, done, live, bomb, jobs, info.dup)
188
+ draw(live, done, died, jobs, info.dup)
182
189
  else
183
- perform(slot, path)
190
+ case @wait
191
+ when "rand" then sleep rand(@work)
192
+ when "task" then sleep task
193
+ when Numeric then sleep task * @wait
194
+ end if task < @work
195
+ perform(path)
184
196
  exit
185
197
  end
186
198
  end
199
+ while @que.size != @work
200
+ sleep 1
201
+ draw(live, done, died, jobs, info.dup)
202
+ end
187
203
  end.join
188
- draw(@work, done, live, bomb, jobs, info)
189
204
  secs = Time.now.to_f - time.to_f
190
205
 
191
206
  # summary
data/test/example.rb CHANGED
@@ -1,13 +1,15 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  def setup
4
+ vete_init
5
+ 100.times {|i| vete_todo(i + 1) }
4
6
  @time = Time.now
5
7
  end
6
8
 
7
- def perform(slot, task)
9
+ def perform(task)
8
10
  sleep rand
9
11
  secs = Time.now - @time
10
- exit 4 if rand < 0.02
12
+ exit 1 if rand < 0.03
11
13
  end
12
14
 
13
15
  require_relative "../lib/vete"
data/test/vete.gif CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vete
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steve Shreeve
@@ -42,7 +42,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
42
42
  - !ruby/object:Gem::Version
43
43
  version: '0'
44
44
  requirements: []
45
- rubygems_version: 3.4.8
45
+ rubygems_version: 3.4.9
46
46
  signing_key:
47
47
  specification_version: 4
48
48
  summary: Ruby CLI to spawn processes to get work done