Module: Lich::Common::ShutdownScriptDrain
- Defined in:
- documented/common/shutdown_script_drain.rb
Overview
Tracks script teardown during process shutdown.
This helper keeps the shutdown orchestration in main.rb readable while
making the slow-script accounting independently testable.
Defined Under Namespace
Classes: Result
Constant Summary collapse
- DEFAULT_DRAIN_ATTEMPTS =
Maximum number of polling attempts while waiting for scripts to exit.
200- DEFAULT_DRAIN_INTERVAL =
Seconds slept between drain polling attempts.
0.1
Class Method Summary collapse
-
.run(initial_scripts:, remaining_scripts:, slow_threshold:, drain_attempts: DEFAULT_DRAIN_ATTEMPTS, drain_interval: DEFAULT_DRAIN_INTERVAL, clock: nil, sleeper: nil) ⇒ Result
Kills each supplied script with shutdown context and watches the existing bounded drain loop for scripts that exit slowly or not at all.
Class Method Details
.run(initial_scripts:, remaining_scripts:, slow_threshold:, drain_attempts: DEFAULT_DRAIN_ATTEMPTS, drain_interval: DEFAULT_DRAIN_INTERVAL, clock: nil, sleeper: nil) ⇒ Result
Kills each supplied script with shutdown context and watches the existing bounded drain loop for scripts that exit slowly or not at all.
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'documented/common/shutdown_script_drain.rb', line 56 def self.run(initial_scripts:, remaining_scripts:, slow_threshold:, drain_attempts: DEFAULT_DRAIN_ATTEMPTS, drain_interval: DEFAULT_DRAIN_INTERVAL, clock: nil, sleeper: nil) clock ||= proc { Process.clock_gettime(Process::CLOCK_MONOTONIC) } sleeper ||= proc { |duration| sleep duration } scripts = initial_scripts.uniq started_at = clock.call finished_at_by_script = {} remaining = [] scripts.each { |script| kill_script(script) } drain_attempts.times do remaining = remaining_scripts.call.uniq observe_scripts!(scripts, remaining) now = clock.call scripts.each do |script| next if finished_at_by_script.key?(script) next if remaining.include?(script) finished_at_by_script[script] = now end break if remaining.empty? sleeper.call(drain_interval) end remaining = remaining_scripts.call.uniq newly_observed = observe_scripts!(scripts, remaining) unless newly_observed.empty? remaining = remaining_scripts.call.uniq end finished_at = clock.call Result.new( scripts_started: scripts.length, slow_script_threshold: slow_threshold, slow_scripts: slow_script_names(scripts, finished_at_by_script, started_at, finished_at, slow_threshold), scripts_remaining: remaining.length, remaining_scripts: script_names(remaining) ) end |