@@ -7,7 +7,7 @@ require "log"
7
7
require " yaml"
8
8
9
9
module Croupier
10
- VERSION = " 0.3.2 "
10
+ VERSION = " 0.3.3 "
11
11
12
12
# A Task is an object that may generate output
13
13
#
@@ -107,7 +107,11 @@ module Croupier
107
107
call_results = Array (String | Nil ).new
108
108
@procs .each do |proc |
109
109
Fiber .yield
110
- result = proc.call
110
+ begin
111
+ result = proc.call
112
+ rescue ex
113
+ raise " Task #{ self } failed: #{ ex } "
114
+ end
111
115
if result.nil?
112
116
call_results << nil
113
117
elsif result.is_a?(String )
@@ -380,33 +384,49 @@ module Croupier
380
384
#
381
385
# If `run_all` is true, run non-stale tasks too
382
386
# If `dry_run` is true, only log what would be done, but don't do it
383
- def run_tasks (run_all : Bool = false , dry_run : Bool = false , parallel : Bool = false )
387
+ # If `parallel` is true, run tasks in parallel
388
+ # If `keep_going` is true, keep going even if a task fails
389
+ def run_tasks (
390
+ run_all : Bool = false ,
391
+ dry_run : Bool = false ,
392
+ parallel : Bool = false ,
393
+ keep_going : Bool = false
394
+ )
384
395
mark_stale_inputs
385
396
_, tasks = sorted_task_graph
386
397
check_dependencies
387
- run_tasks(tasks, run_all, dry_run, parallel)
398
+ run_tasks(tasks, run_all, dry_run, parallel, keep_going )
388
399
end
389
400
390
401
# Run the tasks needed to create or update the requested targets
391
- # run_all will run all tasks, not just the ones that are stale
392
- # dry_run will only log what would be done, but not actually do it
402
+ #
403
+ # If `run_all` is true, run non-stale tasks too
404
+ # If `dry_run` is true, only log what would be done, but don't do it
405
+ # If `parallel` is true, run tasks in parallel
406
+ # If `keep_going` is true, keep going even if a task fails
393
407
def run_tasks (
394
408
targets : Array (String ),
395
409
run_all : Bool = false ,
396
410
dry_run : Bool = false ,
397
- parallel : Bool = false
411
+ parallel : Bool = false ,
412
+ keep_going : Bool = false
398
413
)
399
414
mark_stale_inputs
400
415
tasks = dependencies(targets)
401
416
if parallel
402
- _run_tasks_parallel(tasks, run_all, dry_run)
417
+ _run_tasks_parallel(tasks, run_all, dry_run, keep_going )
403
418
else
404
- _run_tasks(tasks, run_all, dry_run)
419
+ _run_tasks(tasks, run_all, dry_run, keep_going )
405
420
end
406
421
end
407
422
408
- # Helper to run tasks
409
- def _run_tasks (outputs, run_all : Bool = false , dry_run : Bool = false )
423
+ # Internal helper to run tasks serially
424
+ def _run_tasks (
425
+ outputs,
426
+ run_all : Bool = false ,
427
+ dry_run : Bool = false ,
428
+ keep_going : Bool = false
429
+ )
410
430
finished = Set (Task ).new
411
431
outputs.each do |output |
412
432
next unless tasks.has_key?(output)
@@ -415,13 +435,18 @@ module Croupier
415
435
next unless run_all || t.stale? || t.@always_run
416
436
417
437
Log .debug { " Running task for #{ output } " }
418
- t.run unless dry_run
438
+ begin
439
+ t.run unless dry_run
440
+ rescue ex
441
+ Log .error { " Error running task for #{ output } : #{ ex } " }
442
+ raise ex unless keep_going
443
+ end
419
444
finished << t
420
445
end
421
446
save_run
422
447
end
423
448
424
- # Run all stale tasks as concurrently as possible.
449
+ # Internal helper to run tasks concurrently
425
450
#
426
451
# Whenever a task is ready, launch it in a separate fiber
427
452
# This is only concurrency, not parallelism, but on tests
@@ -431,18 +456,20 @@ module Croupier
431
456
def _run_tasks_parallel (
432
457
targets : Array (String ) = [] of String ,
433
458
run_all : Bool = false ,
434
- dry_run : Bool = false
459
+ dry_run : Bool = false ,
460
+ keep_going : Bool = false # FIXME: implement
435
461
)
436
462
mark_stale_inputs
437
463
438
464
targets = tasks.keys if targets.empty?
439
465
_tasks = dependencies(targets)
440
466
finished_tasks = Set (Task ).new
467
+ failed_tasks = Set (Task ).new
441
468
errors = [] of String
442
469
443
470
loop do
444
471
stale_tasks = (_tasks.map { |t | tasks[t] }).select(& .stale?).reject { |t |
445
- finished_tasks.includes?(t)
472
+ finished_tasks.includes?(t) || failed_tasks.includes?(t)
446
473
}
447
474
448
475
break if stale_tasks.empty?
@@ -456,6 +483,7 @@ module Croupier
456
483
begin
457
484
t.run unless dry_run
458
485
rescue ex
486
+ failed_tasks << t
459
487
errors << ex.message.to_s
460
488
ensure
461
489
# Task is done, do not run again
@@ -466,7 +494,7 @@ module Croupier
466
494
end
467
495
sleep(0.001 )
468
496
end
469
- raise errors.join(" \n " ) unless errors.empty?
497
+ raise errors.join(" \n " ) unless errors.empty? unless keep_going
470
498
# FIXME It's losing outputs for some reason
471
499
save_run
472
500
end
0 commit comments