@rip-lang/swarm 1.0.0 → 1.0.2
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 +42 -3
package/package.json
CHANGED
package/swarm.rip
CHANGED
|
@@ -214,6 +214,7 @@ export swarm = (opts = {}) ->
|
|
|
214
214
|
info = {}
|
|
215
215
|
taskIdx = 0
|
|
216
216
|
inflight = {} # slot → taskPath (track in-flight tasks for crash recovery)
|
|
217
|
+
lastTask = {} # slot → last completed task name (for display)
|
|
217
218
|
|
|
218
219
|
# signal handlers
|
|
219
220
|
process.on 'SIGINT', ->
|
|
@@ -239,7 +240,7 @@ export swarm = (opts = {}) ->
|
|
|
239
240
|
if not finished and done + died >= jobs
|
|
240
241
|
finished = true
|
|
241
242
|
for wk in allWorkers
|
|
242
|
-
try wk.
|
|
243
|
+
try wk.unref()
|
|
243
244
|
catch then null
|
|
244
245
|
resolveAll()
|
|
245
246
|
|
|
@@ -265,10 +266,13 @@ export swarm = (opts = {}) ->
|
|
|
265
266
|
|
|
266
267
|
w.on 'message', (msg) ->
|
|
267
268
|
switch msg.type
|
|
269
|
+
when 'error'
|
|
270
|
+
writeFileSync('.swarm/errors.log', "worker #{slot} startup: #{msg.error}\n", { flag: 'a' }) if existsSync(_dir)
|
|
268
271
|
when 'ready'
|
|
269
272
|
dispatchNext(w, slot)
|
|
270
273
|
when 'done'
|
|
271
274
|
move(msg.taskPath, _done)
|
|
275
|
+
lastTask[slot] = msg.taskPath.split('/').pop()
|
|
272
276
|
inflight[slot] = null
|
|
273
277
|
live--
|
|
274
278
|
done++
|
|
@@ -277,6 +281,8 @@ export swarm = (opts = {}) ->
|
|
|
277
281
|
dispatchNext(w, slot)
|
|
278
282
|
when 'failed'
|
|
279
283
|
move(msg.taskPath, _died)
|
|
284
|
+
lastTask[slot] = msg.taskPath.split('/').pop()
|
|
285
|
+
writeFileSync('.swarm/errors.log', "#{msg.taskPath.split('/').pop()}: #{msg.error or 'unknown'}\n", { flag: 'a' }) if existsSync(_dir)
|
|
280
286
|
inflight[slot] = null
|
|
281
287
|
live--
|
|
282
288
|
died++
|
|
@@ -285,9 +291,10 @@ export swarm = (opts = {}) ->
|
|
|
285
291
|
dispatchNext(w, slot)
|
|
286
292
|
|
|
287
293
|
w.on 'error', (err) ->
|
|
288
|
-
|
|
294
|
+
writeFileSync('.swarm/errors.log', "worker #{slot} error: #{err.message}\n", { flag: 'a' }) if existsSync(_dir)
|
|
289
295
|
|
|
290
296
|
w.on 'exit', (code) ->
|
|
297
|
+
writeFileSync('.swarm/errors.log', "worker #{slot} exited with code #{code}, inflight: #{inflight[slot]}\n", { flag: 'a' }) if existsSync(_dir)
|
|
291
298
|
# if worker crashed mid-task, count the in-flight task as died
|
|
292
299
|
if inflight[slot]
|
|
293
300
|
move(inflight[slot], _died)
|
|
@@ -307,9 +314,17 @@ export swarm = (opts = {}) ->
|
|
|
307
314
|
for slot in [1..count]
|
|
308
315
|
spawnWorker(slot)
|
|
309
316
|
|
|
317
|
+
# final redraw — fill all worker bars and show per-worker stats
|
|
318
|
+
secs = (Date.now() - startTime) / 1000
|
|
319
|
+
for slot of info
|
|
320
|
+
s = parseInt(slot)
|
|
321
|
+
n = info[slot]
|
|
322
|
+
rate = if secs > 0 then (n / secs).toFixed(1) else '—'
|
|
323
|
+
write go(s + 1, _len + 5) + bg("5383ec") + _char.repeat(_wide) + bg() + " │ #{n} jobs @ #{rate}/sec" + clear(true)
|
|
324
|
+
draw({ live: 0, done, died, jobs, workers, info })
|
|
325
|
+
|
|
310
326
|
# summary
|
|
311
327
|
cursor(true)
|
|
312
|
-
secs = (Date.now() - startTime) / 1000
|
|
313
328
|
write go(workers + 5, 1)
|
|
314
329
|
write "#{secs.toFixed(2)} secs"
|
|
315
330
|
write " for #{jobs} jobs"
|
|
@@ -321,6 +336,11 @@ export swarm = (opts = {}) ->
|
|
|
321
336
|
# CLI helpers
|
|
322
337
|
# ==============================================================================
|
|
323
338
|
|
|
339
|
+
# flags that swarm consumes (with value)
|
|
340
|
+
_flagsWithValue = ['-w', '--workers', '-b', '--bar', '-c', '--char']
|
|
341
|
+
# flags that swarm consumes (standalone)
|
|
342
|
+
_flagsAlone = ['-r', '--reset', '-h', '--help', '-v', '--version']
|
|
343
|
+
|
|
324
344
|
findArg = (args, short, long) ->
|
|
325
345
|
for arg, i in args
|
|
326
346
|
if arg is short or arg is long
|
|
@@ -330,3 +350,22 @@ findArg = (args, short, long) ->
|
|
|
330
350
|
if arg.startsWith("#{short}=")
|
|
331
351
|
return arg.split('=')[1]
|
|
332
352
|
null
|
|
353
|
+
|
|
354
|
+
# return process.argv with swarm's flags stripped — only your args remain
|
|
355
|
+
export args = ->
|
|
356
|
+
result = []
|
|
357
|
+
list = process.argv.slice(2)
|
|
358
|
+
skip = false
|
|
359
|
+
for arg in list
|
|
360
|
+
if skip
|
|
361
|
+
skip = false
|
|
362
|
+
continue
|
|
363
|
+
if arg in _flagsWithValue
|
|
364
|
+
skip = true
|
|
365
|
+
continue
|
|
366
|
+
if arg in _flagsAlone
|
|
367
|
+
continue
|
|
368
|
+
if _flagsWithValue.some((f) -> arg.startsWith("#{f}="))
|
|
369
|
+
continue
|
|
370
|
+
result.push(arg)
|
|
371
|
+
result
|