@rip-lang/swarm 1.2.3 → 1.2.5
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.
- package/package.json +1 -1
- package/swarm.rip +60 -57
package/package.json
CHANGED
package/swarm.rip
CHANGED
|
@@ -94,19 +94,18 @@ bg = (rgb) -> if rgb then "\x1b[48;2;#{hex(rgb)}m" else "\x1b[49m"
|
|
|
94
94
|
# Progress display
|
|
95
95
|
# ==============================================================================
|
|
96
96
|
|
|
97
|
-
|
|
97
|
+
char = wide = len = null
|
|
98
98
|
|
|
99
99
|
drawFrame = (workers) ->
|
|
100
|
-
|
|
100
|
+
len = String(workers).length
|
|
101
101
|
write clear()
|
|
102
|
-
write go(2 + workers,
|
|
103
|
-
write go(1,
|
|
102
|
+
write go(2 + workers, len + 3) + "╰" + "─".repeat(wide + 2) + "╯"
|
|
103
|
+
write go(1, len + 3) + "╭" + "─".repeat(wide + 2) + "╮"
|
|
104
104
|
for i in [0...workers]
|
|
105
105
|
write go(i + 2, 1)
|
|
106
|
-
label = String(i + 1).padStart(
|
|
107
|
-
write " #{label} │ " + " ".repeat(
|
|
108
|
-
|
|
109
|
-
write go(workers + 3, _len + 3) + "│ " + " ".repeat(_wide) + " │"
|
|
106
|
+
label = String(i + 1).padStart(len)
|
|
107
|
+
write " #{label} │ " + " ".repeat(wide) + " │"
|
|
108
|
+
write go(workers + 3, len + 3) + "│ " + " ".repeat(wide) + " │"
|
|
110
109
|
|
|
111
110
|
draw = (state) ->
|
|
112
111
|
{ live, done, died, jobs, workers, info } = state
|
|
@@ -117,27 +116,29 @@ draw = (state) ->
|
|
|
117
116
|
# worker bars
|
|
118
117
|
for slot, count of info
|
|
119
118
|
tpct = count / most
|
|
120
|
-
cols = Math.floor(ppct * tpct *
|
|
121
|
-
write go(parseInt(slot) + 1,
|
|
119
|
+
cols = Math.floor(ppct * tpct * wide)
|
|
120
|
+
write go(parseInt(slot) + 1, len + 5) + fg("fff") + bg("5383ec") + char.repeat(cols) + fg() + bg()
|
|
122
121
|
|
|
123
122
|
# summary bar
|
|
124
123
|
dpct = done / jobs
|
|
125
124
|
lpct = live / jobs
|
|
126
|
-
gcol = Math.floor(dpct *
|
|
127
|
-
ycol = Math.floor(lpct *
|
|
128
|
-
rcol = Math.max(0,
|
|
125
|
+
gcol = Math.floor(dpct * wide)
|
|
126
|
+
ycol = Math.floor(lpct * wide)
|
|
127
|
+
rcol = Math.max(0, wide - gcol - ycol)
|
|
129
128
|
row = workers + 3
|
|
130
129
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
130
|
+
out = [
|
|
131
|
+
go(row, len + 5)
|
|
132
|
+
fg("fff")
|
|
133
|
+
bg("58a65c") + char.repeat(gcol) # green (done)
|
|
134
|
+
bg("f1bf42") + char.repeat(ycol) # yellow (live)
|
|
135
|
+
bg("d85140") + " ".repeat(rcol) # red (rest)
|
|
136
|
+
go(row, len + 5 + wide + 3)
|
|
137
|
+
bg("5383ec") + " #{(ppct * 100).toFixed(1)}% " # blue (pct)
|
|
138
|
+
if done > 0 then bg() + " " + bg("58a65c") + " #{done}/#{jobs} done "
|
|
139
|
+
if died > 0 then bg() + " " + bg("d85140") + " #{died} died "
|
|
140
|
+
].filter(Boolean).join('') + fg() + bg()
|
|
141
|
+
write out
|
|
141
142
|
|
|
142
143
|
# ==============================================================================
|
|
143
144
|
# Worker orchestration
|
|
@@ -157,18 +158,16 @@ export swarm = (opts = {}) ->
|
|
|
157
158
|
# parse CLI options
|
|
158
159
|
args = process.argv.slice(2)
|
|
159
160
|
workers = parseInt(findArg(args, '-w', '--workers')) or opts.workers or cpus().length
|
|
160
|
-
|
|
161
|
-
char = findArg(args, '-c', '--char')
|
|
161
|
+
wide = parseInt(findArg(args, '-b', '--bar')) or opts.bar or 20
|
|
162
|
+
char = (findArg(args, '-c', '--char') or opts.char or '•')[0]
|
|
162
163
|
doreset = args.includes('-r') or args.includes('--reset')
|
|
163
164
|
dosafe = args.includes('-s') or args.includes('--safe')
|
|
165
|
+
quiet = args.includes('-q') or args.includes('--quiet')
|
|
164
166
|
|
|
165
167
|
if workers < 1
|
|
166
168
|
console.error 'error: workers must be at least 1'
|
|
167
169
|
process.exit(1)
|
|
168
170
|
|
|
169
|
-
_wide = barw
|
|
170
|
-
_char = char[0]
|
|
171
|
-
|
|
172
171
|
if doreset
|
|
173
172
|
rmSync(_dir, { recursive: true, force: true })
|
|
174
173
|
console.log 'removed .swarm directory'
|
|
@@ -225,17 +224,19 @@ export swarm = (opts = {}) ->
|
|
|
225
224
|
|
|
226
225
|
# signal handlers
|
|
227
226
|
process.on 'SIGINT', ->
|
|
228
|
-
cursor(true)
|
|
229
|
-
write go(workers + 5, 1) + "\n"
|
|
227
|
+
cursor(true) unless quiet
|
|
228
|
+
write go(workers + 5, 1) + "\n" unless quiet
|
|
230
229
|
process.exit(1)
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
230
|
+
unless quiet
|
|
231
|
+
process.on 'SIGWINCH', ->
|
|
232
|
+
drawFrame(workers)
|
|
233
|
+
draw({ live, done, died, jobs, workers, info })
|
|
234
234
|
|
|
235
235
|
# draw initial frame
|
|
236
236
|
startTime = Date.now()
|
|
237
|
-
|
|
238
|
-
|
|
237
|
+
unless quiet
|
|
238
|
+
cursor(false)
|
|
239
|
+
drawFrame(workers)
|
|
239
240
|
|
|
240
241
|
# create workers and dispatch tasks
|
|
241
242
|
allWorkers = []
|
|
@@ -256,8 +257,9 @@ export swarm = (opts = {}) ->
|
|
|
256
257
|
taskPath = tasks[taskIdx++]
|
|
257
258
|
inflight[slot] = taskPath
|
|
258
259
|
live++
|
|
259
|
-
|
|
260
|
-
|
|
260
|
+
unless quiet
|
|
261
|
+
write go(slot + 1, len + 5 + wide + 3) + " " + taskPath.split('/').pop() + clear(true)
|
|
262
|
+
draw({ live, done, died, jobs, workers, info })
|
|
261
263
|
worker.postMessage { type: 'task', taskPath }
|
|
262
264
|
else
|
|
263
265
|
inflight[slot] = null
|
|
@@ -284,7 +286,7 @@ export swarm = (opts = {}) ->
|
|
|
284
286
|
live--
|
|
285
287
|
done++
|
|
286
288
|
info[slot]++
|
|
287
|
-
draw({ live, done, died, jobs, workers, info })
|
|
289
|
+
draw({ live, done, died, jobs, workers, info }) unless quiet
|
|
288
290
|
dispatchNext(w, slot)
|
|
289
291
|
when 'failed'
|
|
290
292
|
move(msg.taskPath, _died)
|
|
@@ -294,7 +296,7 @@ export swarm = (opts = {}) ->
|
|
|
294
296
|
live--
|
|
295
297
|
died++
|
|
296
298
|
info[slot]++
|
|
297
|
-
draw({ live, done, died, jobs, workers, info })
|
|
299
|
+
draw({ live, done, died, jobs, workers, info }) unless quiet
|
|
298
300
|
dispatchNext(w, slot)
|
|
299
301
|
|
|
300
302
|
w.on 'error', (err) ->
|
|
@@ -309,7 +311,7 @@ export swarm = (opts = {}) ->
|
|
|
309
311
|
live--
|
|
310
312
|
died++
|
|
311
313
|
info[slot]++
|
|
312
|
-
draw({ live, done, died, jobs, workers, info })
|
|
314
|
+
draw({ live, done, died, jobs, workers, info }) unless quiet
|
|
313
315
|
# respawn if there's still work to do
|
|
314
316
|
if done + died < jobs
|
|
315
317
|
spawnWorker(slot)
|
|
@@ -321,23 +323,24 @@ export swarm = (opts = {}) ->
|
|
|
321
323
|
for slot in [1..count]
|
|
322
324
|
spawnWorker(slot)
|
|
323
325
|
|
|
324
|
-
# final redraw — fill all worker bars and show per-worker stats
|
|
325
|
-
secs = (Date.now() - startTime) / 1000
|
|
326
|
-
for slot of info
|
|
327
|
-
s = parseInt(slot)
|
|
328
|
-
n = info[slot]
|
|
329
|
-
rate = if secs > 0 then (n / secs).toFixed(1) else '—'
|
|
330
|
-
write go(s + 1, _len + 5) + bg("5383ec") + _char.repeat(_wide) + bg() + " │ #{n} jobs @ #{rate}/sec" + clear(true)
|
|
331
|
-
draw({ live: 0, done, died, jobs, workers, info })
|
|
332
|
-
|
|
333
326
|
# summary
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
327
|
+
secs = (Date.now() - startTime) / 1000
|
|
328
|
+
if quiet
|
|
329
|
+
p "#{secs.toFixed(2)} secs for #{jobs} jobs by #{workers} workers" + (if secs > 0 then " @ #{(jobs / secs).toFixed(2)} jobs/sec" else "")
|
|
330
|
+
else
|
|
331
|
+
for slot of info
|
|
332
|
+
s = parseInt(slot)
|
|
333
|
+
n = info[slot]
|
|
334
|
+
rate = if secs > 0 then (n / secs).toFixed(1) else '—'
|
|
335
|
+
write go(s + 1, len + 5) + fg("fff") + bg("5383ec") + char.repeat(wide) + fg() + bg() + " │ #{n} jobs @ #{rate}/sec" + clear(true)
|
|
336
|
+
draw({ live: 0, done, died, jobs, workers, info })
|
|
337
|
+
cursor(true)
|
|
338
|
+
write go(workers + 5, 1)
|
|
339
|
+
write "#{secs.toFixed(2)} secs"
|
|
340
|
+
write " for #{jobs} jobs"
|
|
341
|
+
write " by #{workers} workers"
|
|
342
|
+
write " @ #{(jobs / secs).toFixed(2)} jobs/sec" if secs > 0
|
|
343
|
+
write "\n\n"
|
|
341
344
|
|
|
342
345
|
# ==============================================================================
|
|
343
346
|
# CLI helpers
|
|
@@ -346,7 +349,7 @@ export swarm = (opts = {}) ->
|
|
|
346
349
|
# flags that swarm consumes (with value)
|
|
347
350
|
_flagsWithValue = ['-w', '--workers', '-b', '--bar', '-c', '--char']
|
|
348
351
|
# flags that swarm consumes (standalone)
|
|
349
|
-
_flagsAlone = ['-r', '--reset', '-s', '--safe', '-h', '--help', '-v', '--version']
|
|
352
|
+
_flagsAlone = ['-r', '--reset', '-s', '--safe', '-q', '--quiet', '-h', '--help', '-v', '--version']
|
|
350
353
|
|
|
351
354
|
findArg = (args, short, long) ->
|
|
352
355
|
for arg, i in args
|