Class: Henitai::SlotScheduler
- Inherits:
-
Object
- Object
- Henitai::SlotScheduler
- Includes:
- Draining, ProcessControl
- Defined in:
- lib/henitai/slot_scheduler.rb,
lib/henitai/slot_scheduler/draining.rb,
lib/henitai/slot_scheduler/process_control.rb
Overview
Owns the process-slot table for a single parallel mutation run.
ProcessWorkerRunner drives the event loop and OS signal handling and delegates every slot operation here: filling idle slots, reaping completed children, retrying flaky survivors, detecting timeouts and running the drain/broadcast state machine. Keeping the table behind one collaborator means Process.wait* has a single caller, so there are no races between threads reaping the same child.
The drain/timeout state machine lives in Draining; the low-level process and signal primitives live in ProcessControl. host is the owning ProcessWorkerRunner, which supplies runtime, wakeup, worker_count and the shutdown flag.
Defined Under Namespace
Modules: Draining, ProcessControl Classes: Slot
Constant Summary collapse
- PROCESS_DRAIN_WINDOW =
0.2
Instance Attribute Summary collapse
- #flaky_retry_count ⇒ Integer, Array<ScenarioExecutionResult> readonly
- #results ⇒ Integer, Array<ScenarioExecutionResult> readonly
Instance Method Summary collapse
- #done? ⇒ Boolean
-
#enqueue(mutants) ⇒ Object
Queues the mutants to be scheduled into worker slots.
- #fill_idle_slots ⇒ Object
-
#initialize(integration:, config:, progress_reporter:, options:, host:) ⇒ SlotScheduler
constructor
A new instance of SlotScheduler.
- #next_event_timeout ⇒ Object
- #reap_all_completed_children ⇒ Object
Methods included from Draining
#check_timeouts, #drain_draining_slots, #draining_slots?, #interrupt_active_slots
Constructor Details
#initialize(integration:, config:, progress_reporter:, options:, host:) ⇒ SlotScheduler
Returns a new instance of SlotScheduler.
37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/henitai/slot_scheduler.rb', line 37 def initialize(integration:, config:, progress_reporter:, options:, host:) @integration = integration @config = config @progress_reporter = progress_reporter @options = @host = host @pending = [] @slots = {} @pid_to_slot = {} @results = [] @flaky_retry_count = 0 @next_slot_id = 0 end |
Instance Attribute Details
#flaky_retry_count ⇒ Integer, Array<ScenarioExecutionResult> (readonly)
35 36 37 |
# File 'lib/henitai/slot_scheduler.rb', line 35 def flaky_retry_count @flaky_retry_count end |
#results ⇒ Integer, Array<ScenarioExecutionResult> (readonly)
35 36 37 |
# File 'lib/henitai/slot_scheduler.rb', line 35 def results @results end |
Instance Method Details
#done? ⇒ Boolean
56 57 58 |
# File 'lib/henitai/slot_scheduler.rb', line 56 def done? pending.empty? && slots.empty? end |
#enqueue(mutants) ⇒ Object
Queues the mutants to be scheduled into worker slots.
52 53 54 |
# File 'lib/henitai/slot_scheduler.rb', line 52 def enqueue(mutants) @pending = mutants.dup end |
#fill_idle_slots ⇒ Object
60 61 62 63 64 65 |
# File 'lib/henitai/slot_scheduler.rb', line 60 def fill_idle_slots while slots.size < worker_count && !pending.empty? mutant = pending.shift spawn_into_slot(mutant) end end |
#next_event_timeout ⇒ Object
78 79 80 81 82 83 84 85 |
# File 'lib/henitai/slot_scheduler.rb', line 78 def next_event_timeout now = monotonic_time slot_timeouts = slots.each_value.filter_map do |slot| remaining_slot_timeout(slot, now) end slot_timeouts.min end |
#reap_all_completed_children ⇒ Object
67 68 69 70 71 72 73 74 75 76 |
# File 'lib/henitai/slot_scheduler.rb', line 67 def reap_all_completed_children loop do pid, status = runtime.wait2(-1, Process::WNOHANG) break unless pid complete_slot(pid, status) end rescue Errno::ECHILD nil end |