Module: Polyrun::WorkerPing
- Defined in:
- lib/polyrun/worker_ping.rb
Overview
Writes a monotonic timestamp to POLYRUN_WORKER_PING_FILE when the test process advances (typically once per example). When location: is passed (path:line of the example), the file is two lines: timestamp, then that string. Parents use --worker-idle-timeout to detect a worker with no progress inside a single example—unlike a background thread, ping! does not run while Ruby is busy on the main thread, so a tight CPU loop or stuck native code leaves the timestamp stale.
Prefer framework installs (call from helpers after loading the runner):
require "polyrun/rspec"
Polyrun::RSpec.install_worker_ping!
require "polyrun/minitest"
Polyrun::Minitest.install_worker_ping!
Polyrun Quick runs ping! automatically when requiring the Quick stack.
Optional interval thread (+POLYRUN_WORKER_PING_THREAD=1+, POLYRUN_WORKER_PING_INTERVAL_SEC): call #ensure_interval_ping_thread! once at worker startup if you rely on periodic pings without per-example #ping!; installers call this so the env toggle works out of the box.
Class Method Summary collapse
-
.ensure_interval_ping_thread! ⇒ Object
Starts a periodic
ping!thread whenPOLYRUN_WORKER_PING_THREADis truthy andPOLYRUN_WORKER_PING_FILEis set. - .ping!(location: nil) ⇒ Object
- .ping_file_path ⇒ Object
Class Method Details
.ensure_interval_ping_thread! ⇒ Object
Starts a periodic ping! thread when POLYRUN_WORKER_PING_THREAD is truthy and POLYRUN_WORKER_PING_FILE is set. Prefer per-example #ping!; safe to call more than once (idempotent). rubocop:disable ThreadSafety/ClassInstanceVariable – idempotent once-per-process latch
42 43 44 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 70 |
# File 'lib/polyrun/worker_ping.rb', line 42 def ensure_interval_ping_thread! thread_flag = ENV["POLYRUN_WORKER_PING_THREAD"] return unless %w[1 true yes].include?(thread_flag&.downcase) path = ping_file_path return if path.empty? @interval_ping_mx ||= Mutex.new @interval_ping_mx.synchronize do return if @interval_ping_started raw = ENV["POLYRUN_WORKER_PING_INTERVAL_SEC"].to_s.strip interval = Float(raw.empty? ? "15" : raw, exception: false) || 15.0 interval = 1.0 if interval < 1.0 ping! # rubocop:disable ThreadSafety/NewThread -- optional periodic ping alongside per-example ping! Thread.new do loop do sleep(interval) ping! rescue SystemCallError, Interrupt break end end # rubocop:enable ThreadSafety/NewThread @interval_ping_started = true end end |
.ping!(location: nil) ⇒ Object
23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/polyrun/worker_ping.rb', line 23 def ping!(location: nil) path = ping_file_path return if path.empty? t = Process.clock_gettime(Process::CLOCK_MONOTONIC).to_s loc = location.to_s.strip payload = loc.empty? ? t : "#{t}\n#{loc}" File.binwrite(path, payload) rescue SystemCallError # best-effort end |
.ping_file_path ⇒ Object
35 36 37 |
# File 'lib/polyrun/worker_ping.rb', line 35 def ping_file_path ENV["POLYRUN_WORKER_PING_FILE"].to_s.strip end |