vete 0.2.0 → 0.6.0

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.
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