vete 0.2.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/vete.rb +64 -49
- data/test/example.rb +4 -2
- data/test/vete.gif +0 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9e19484c6c02cd403365def0a14367e2c31f302edd7b56842e863162d0178730
|
4
|
+
data.tar.gz: 303793b8c478fe08733f2da221a325d66e68b2d3ab54c89105482ef612866953
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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.
|
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 "-
|
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
|
-
@
|
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, @
|
63
|
-
list.each {|path|
|
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(@
|
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(
|
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
|
80
|
-
def cursor(on)
|
81
|
-
def go(r=1,c=1); "\e[#{r};#{c}H" ; end
|
82
|
-
def go!(...)
|
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(
|
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 +
|
98
|
-
go(1
|
111
|
+
go(2 + @work, @len + 3) + "└" + "─" * (@wide + 2) + "┘\n",
|
112
|
+
go(1 , @len + 3) + "┌" + "─" * (@wide + 2) + "┐\n",
|
99
113
|
].join
|
100
|
-
|
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
|
-
|
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 =
|
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(
|
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)
|
122
|
-
bg("d85140") + " " * (@wide - gcol - ycol).ceil, # red (
|
123
|
-
go(
|
124
|
-
|
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
|
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.
|
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 : @
|
180
|
+
move(path, okay ? @done : @died)
|
173
181
|
@que.push(slot)
|
174
182
|
@mtx.synchronize {
|
175
|
-
done += 1
|
176
183
|
live -= 1
|
177
|
-
|
184
|
+
okay ? (done += 1) : (died += 1)
|
178
185
|
info[slot] += 1
|
179
186
|
}
|
180
187
|
end
|
181
|
-
draw(
|
188
|
+
draw(live, done, died, jobs, info.dup)
|
182
189
|
else
|
183
|
-
|
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(
|
9
|
+
def perform(task)
|
8
10
|
sleep rand
|
9
11
|
secs = Time.now - @time
|
10
|
-
exit
|
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.
|
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.
|
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
|