Class: Pgbus::Process::WakePipe
- Inherits:
-
Object
- Object
- Pgbus::Process::WakePipe
- Defined in:
- lib/pgbus/process/wake_pipe.rb
Overview
Fork-side receiver for supervisor-mediated wake-ups (issue #381, worker_notify_scope: :supervisor). The supervisor's NotifyHub holds the write end of a per-fork pipe; this class owns the inherited read end and a single watcher thread that translates the byte protocol into the fork's existing primitives:
W — a NOTIFY arrived for a queue this fork reads → wake_signal.notify!
H — the shared listener is healthy (connected + delivering) → the
fork may sleep up to the NOTIFY poll ceiling
P — the shared listener is degraded (dead thread, mid-reconnect,
pooler-deaf) → the fork falls back to fast polling
Status starts optimistic (mirrors NotifyListener's @delivering default) so a just-forked worker isn't pinned to fast polling before the hub's first broadcast. EOF on the pipe means the supervisor is gone: mark not-delivering and let the fork run on plain polling.
A nil reader (scope :fork, or the supervisor never armed the pipe) yields an inert instance: start is a no-op and delivering? is false, so wake_timeout math treats it exactly like an absent listener.
Constant Summary collapse
- WAKE =
"W"- HEALTHY =
"H"- DEGRADED =
"P"
Instance Method Summary collapse
- #delivering? ⇒ Boolean
-
#initialize(reader, wake_signal:, logger: Pgbus.logger) ⇒ WakePipe
constructor
A new instance of WakePipe.
- #running? ⇒ Boolean
- #start ⇒ Object
- #stop ⇒ Object
Constructor Details
#initialize(reader, wake_signal:, logger: Pgbus.logger) ⇒ WakePipe
Returns a new instance of WakePipe.
30 31 32 33 34 35 36 37 38 |
# File 'lib/pgbus/process/wake_pipe.rb', line 30 def initialize(reader, wake_signal:, logger: Pgbus.logger) @reader = reader @wake_signal = wake_signal @logger = logger @state_mutex = Mutex.new @running = false @thread = nil @delivering = !reader.nil? end |
Instance Method Details
#delivering? ⇒ Boolean
40 41 42 |
# File 'lib/pgbus/process/wake_pipe.rb', line 40 def delivering? @state_mutex.synchronize { @delivering } end |
#running? ⇒ Boolean
44 45 46 |
# File 'lib/pgbus/process/wake_pipe.rb', line 44 def running? @state_mutex.synchronize { @running } end |
#start ⇒ Object
48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/pgbus/process/wake_pipe.rb', line 48 def start return self if @reader.nil? @state_mutex.synchronize do return self if @running @running = true end @thread = Thread.new { run_loop } self end |
#stop ⇒ Object
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/pgbus/process/wake_pipe.rb', line 60 def stop @state_mutex.synchronize do return self unless @running @running = false end # Closing the pipe FD interrupts the watcher's blocking readpartial — # Ruby raises IOError in the blocked thread at the interpreter level. # (Safe for a plain IO, unlike PG::Connection#close, which is PQfinish # under a concurrent libpq call — issue #375. That constraint is about # libpq, not IO.) close_reader_quietly @thread&.join(2) @thread = nil self end |