Class: Coatepec::WorkerManager
- Inherits:
-
Object
- Object
- Coatepec::WorkerManager
- Defined in:
- lib/coatepec/worker_manager.rb
Overview
Owns the single warm Worker::Client for a project: lazily starts it, restarts it when ChangeDetector flags a boot-file change, escalates a Gemfile change to :sidecar_restart_required, and retries a request once if the worker had died since the last dispatch.
Instance Method Summary collapse
- #check_flaky(paths:, example:, timeout_seconds:, runs:) ⇒ Object
-
#initialize(project) ⇒ WorkerManager
constructor
A new instance of WorkerManager.
- #model(name:) ⇒ Object
-
#restart! ⇒ Object
Unconditionally tears down and respawns the worker, bypassing the usual "only restart if #ensure_worker! thinks it's needed" check.
- #routes(query: nil, limit: 50, offset: 0) ⇒ Object
- #run_spec(paths:, example:, seed:, fail_fast:, timeout_seconds:) ⇒ Object
- #status ⇒ Object
- #stop ⇒ Object
Constructor Details
#initialize(project) ⇒ WorkerManager
Returns a new instance of WorkerManager.
11 12 13 14 15 16 17 |
# File 'lib/coatepec/worker_manager.rb', line 11 def initialize(project) @project = project @change_detector = Worker::ChangeDetector.new(project.root) @client = nil @snapshot = nil @lock = Monitor.new end |
Instance Method Details
#check_flaky(paths:, example:, timeout_seconds:, runs:) ⇒ Object
31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/coatepec/worker_manager.rb', line 31 def check_flaky(paths:, example:, timeout_seconds:, runs:) dispatch( "flaky_check", { paths: paths, example: example, timeout_seconds: timeout_seconds, runs: runs }, # Each round costs timeout_seconds *plus* real per-round overhead (process # termination/spawn/result-parsing -- roughly 0.6s+ per round from # ProcessStrategy#terminate's own escalation sleeps alone), so the flat # base slack below is scaled by an extra ~2s per round on top of it. timeout: (timeout_seconds * runs) + (2 * runs) + 10 ) end |
#model(name:) ⇒ Object
47 48 49 |
# File 'lib/coatepec/worker_manager.rb', line 47 def model(name:) dispatch("model", { name: name }, timeout: 30) end |
#restart! ⇒ Object
Unconditionally tears down and respawns the worker, bypassing the usual "only restart if #ensure_worker! thinks it's needed" check. Manual escape hatch for rails_runtime_restart, independent of whatever #perform's rescue below already recovers from automatically.
Still honors the sidecar-restart invariant: if the Gemfile changed since boot, a worker-only respawn would silently adopt the new bundle in the worker while the parent MCP process stays on the old one, so that case raises :sidecar_restart_required instead of restarting. The check runs against the pre-existing snapshot, before restart_worker! re-baselines it -- same ordering #dispatch uses. Nothing to compare against on the very first call.
67 68 69 70 71 72 73 74 |
# File 'lib/coatepec/worker_manager.rb', line 67 def restart! @lock.synchronize do raise_sidecar_restart_required! if sidecar_restart_required? restart_worker! status end end |
#routes(query: nil, limit: 50, offset: 0) ⇒ Object
43 44 45 |
# File 'lib/coatepec/worker_manager.rb', line 43 def routes(query: nil, limit: 50, offset: 0) dispatch("routes", { query: query, limit: limit, offset: offset }, timeout: 30) end |
#run_spec(paths:, example:, seed:, fail_fast:, timeout_seconds:) ⇒ Object
23 24 25 26 27 28 29 |
# File 'lib/coatepec/worker_manager.rb', line 23 def run_spec(paths:, example:, seed:, fail_fast:, timeout_seconds:) dispatch( "spec_run", { paths: paths, example: example, seed: seed, fail_fast: fail_fast, timeout_seconds: timeout_seconds }, timeout: timeout_seconds + 10 ) end |
#status ⇒ Object
19 20 21 |
# File 'lib/coatepec/worker_manager.rb', line 19 def status dispatch("status", {}, timeout: 30) end |
#stop ⇒ Object
51 52 53 |
# File 'lib/coatepec/worker_manager.rb', line 51 def stop @lock.synchronize { @client&.stop } end |