Class: Ibex::Watch::Runner
- Inherits:
-
Object
- Object
- Ibex::Watch::Runner
- Defined in:
- lib/ibex/watch/runner.rb,
sig/ibex/watch/runner.rbs
Overview
Polls source fingerprints, debounces changes, and publishes stable builds.
Constant Summary collapse
- DEFAULT_INTERVAL =
0.25- DEFAULT_DEBOUNCE =
0.05
Instance Method Summary collapse
- #build_once(before) ⇒ [ SourceSnapshot, bool ]
- #debounce(changed) ⇒ SourceSnapshot
- #failed_build(before, error) ⇒ [ SourceSnapshot, bool ]
-
#initialize(paths:, build:, publish:, failure_paths:, stderr:, clock:, sleeper:, iteration_hook:, interval: DEFAULT_INTERVAL, debounce: DEFAULT_DEBOUNCE) ⇒ Runner
constructor
rubocop:disable Layout/LineLength.
- #normalize_paths(paths) ⇒ Array[String]
- #report_failure(error) ⇒ void
- #report_failure_once(error, snapshot) ⇒ void
- #run ⇒ Integer
- #stop_status(event) ⇒ Integer?
- #wait_for_change(snapshot) ⇒ SourceSnapshot
- #with_signal_handlers { ... } ⇒ Integer
Constructor Details
#initialize(paths:, build:, publish:, failure_paths:, stderr:, clock:, sleeper:, iteration_hook:, interval: DEFAULT_INTERVAL, debounce: DEFAULT_DEBOUNCE) ⇒ Runner
rubocop:disable Layout/LineLength
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/ibex/watch/runner.rb', line 22 def initialize(paths:, build:, publish:, failure_paths:, stderr:, clock:, sleeper:, iteration_hook:, interval: DEFAULT_INTERVAL, debounce: DEFAULT_DEBOUNCE) @fixed_paths = normalize_paths(paths) @successful_paths = [] #: Array[String] @paths = @fixed_paths @build = build @publish = publish @failure_paths = failure_paths @stderr = stderr @clock = clock @sleeper = sleeper @iteration_hook = iteration_hook @interval = interval @debounce = debounce @signal_status = nil #: Integer? @requested_status = nil #: Integer? @last_failure_message = nil #: String? @last_failure_snapshot = nil #: SourceSnapshot? @iteration = 0 end |
Instance Method Details
#build_once(before) ⇒ [ SourceSnapshot, bool ]
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/ibex/watch/runner.rb', line 74 def build_once(before) @iteration += 1 result = @build.call @paths = normalize_paths(@fixed_paths + result.source_paths + result.attempted_paths) rendered = SourceSnapshot.new(@paths) return [rendered, true] unless rendered.unchanged_since?(before) return [rendered, false] if @signal_status @publish.call(result, rendered, -> { @signal_status.nil? }) @last_failure_message = nil @last_failure_snapshot = nil @successful_paths = @paths - @fixed_paths published = SourceSnapshot.new(@paths) [published, published != rendered] rescue GenerationTransaction::SourceChanged [SourceSnapshot.new(@paths), true] rescue GenerationTransaction::Error => e raise if e.rollback_failed failed_build(before, e) rescue Ibex::Error, SystemCallError, SystemStackError => e failed_build(before, e) end |
#debounce(changed) ⇒ SourceSnapshot
115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/ibex/watch/runner.rb', line 115 def debounce(changed) loop do @clock.call @sleeper.call(@debounce) return changed if @signal_status settled = SourceSnapshot.new(@paths) return settled if settled == changed changed = settled end end |
#failed_build(before, error) ⇒ [ SourceSnapshot, bool ]
134 135 136 137 138 139 140 141 |
# File 'lib/ibex/watch/runner.rb', line 134 def failed_build(before, error) previous_paths = @paths @paths = normalize_paths(@fixed_paths + @successful_paths + @failure_paths.call) current = SourceSnapshot.new(@paths) retry_build = @paths != previous_paths || !current.unchanged_since?(before) report_failure_once(error, current) [current, retry_build] end |
#normalize_paths(paths) ⇒ Array[String]
164 165 166 |
# File 'lib/ibex/watch/runner.rb', line 164 def normalize_paths(paths) paths.map { |path| File.(path) }.uniq.sort end |
#report_failure(error) ⇒ void
This method returns an undefined value.
129 130 131 |
# File 'lib/ibex/watch/runner.rb', line 129 def report_failure(error) @stderr.puts(error.) end |
#report_failure_once(error, snapshot) ⇒ void
This method returns an undefined value.
144 145 146 147 148 149 |
# File 'lib/ibex/watch/runner.rb', line 144 def report_failure_once(error, snapshot) duplicate = @last_failure_message == error. && @last_failure_snapshot == snapshot report_failure(error) unless duplicate @last_failure_message = error. @last_failure_snapshot = snapshot end |
#run ⇒ Integer
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/ibex/watch/runner.rb', line 45 def run with_signal_handlers do snapshot = SourceSnapshot.new(@paths) loop do status = stop_status(:before_build) return status if status snapshot, retry_build = build_once(snapshot) status = stop_status(:after_build) return status if status if retry_build snapshot = debounce(snapshot) status = @signal_status || @requested_status return status if status next end snapshot = wait_for_change(snapshot) status = @signal_status || @requested_status return status if status end end end |
#stop_status(event) ⇒ Integer?
152 153 154 155 156 157 158 159 160 161 |
# File 'lib/ibex/watch/runner.rb', line 152 def stop_status(event) return @signal_status if @signal_status result = @iteration_hook.call(event, @iteration, @paths.dup) @requested_status = result if result.is_a?(Integer) @requested_status = 0 if result == :stop return @requested_status if @requested_status nil end |
#wait_for_change(snapshot) ⇒ SourceSnapshot
99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/ibex/watch/runner.rb', line 99 def wait_for_change(snapshot) loop do @sleeper.call(@interval) return snapshot if @signal_status status = stop_status(:poll) return snapshot if status changed = SourceSnapshot.new(@paths) next if changed == snapshot return debounce(changed) end end |
#with_signal_handlers { ... } ⇒ Integer
169 170 171 172 173 174 175 176 177 178 |
# File 'lib/ibex/watch/runner.rb', line 169 def with_signal_handlers previous = {} #: Hash[String, untyped] if Thread.current == Thread.main previous["INT"] = Signal.trap("INT") { @signal_status = 130 } previous["TERM"] = Signal.trap("TERM") { @signal_status = 143 } end yield ensure previous&.each { |signal, handler| Signal.trap(signal, handler) } end |