Module: Clacky::Shutdown
- Defined in:
- lib/clacky/shutdown.rb
Overview
Process-wide cooperative shutdown flag.
Signal traps must never do heavy work — they only call request!(reason) and wake the shutdown coordinator thread. Long-running loops poll requested? at safe points and exit cleanly; threads blocked in IO are released by the coordinator closing their sockets (see Client#close_connections!).
Constant Summary collapse
- MUTEX =
Mutex.new
- INTERRUPT_SLICE =
Seconds between requested? polls while sleeping, so a sleeping thread notices shutdown within one slice instead of waiting out a long sleep.
0.2
Class Method Summary collapse
-
.checkpoint! ⇒ Object
Cooperative checkpoint: raise AgentInterrupted if shutdown was requested.
- .reason ⇒ Object
- .request!(reason = :unknown) ⇒ Object
- .requested? ⇒ Boolean
- .reset! ⇒ Object
-
.sleep(seconds) ⇒ Object
Sleep for total seconds, raising AgentInterrupted if shutdown is requested while sleeping.
-
.sleep_interruptibly(seconds) ⇒ Object
Sleep for total seconds but wake every INTERRUPT_SLICE to poll requested?.
Class Method Details
.checkpoint! ⇒ Object
Cooperative checkpoint: raise AgentInterrupted if shutdown was requested. Long-running loops call this at safe points so they exit cleanly instead of blocking the process shutdown.
59 60 61 |
# File 'lib/clacky/shutdown.rb', line 59 def checkpoint! raise Clacky::AgentInterrupted, "shutdown requested" if requested? end |
.reason ⇒ Object
30 31 32 |
# File 'lib/clacky/shutdown.rb', line 30 def reason MUTEX.synchronize { @reason } end |
.request!(reason = :unknown) ⇒ Object
18 19 20 21 22 23 24 |
# File 'lib/clacky/shutdown.rb', line 18 def request!(reason = :unknown) MUTEX.synchronize do @requested = true @reason = reason @requested_at = Time.now end end |
.requested? ⇒ Boolean
26 27 28 |
# File 'lib/clacky/shutdown.rb', line 26 def requested? MUTEX.synchronize { !!@requested } end |
.reset! ⇒ Object
34 35 36 37 38 39 40 |
# File 'lib/clacky/shutdown.rb', line 34 def reset! MUTEX.synchronize do @requested = nil @reason = nil @requested_at = nil end end |
.sleep(seconds) ⇒ Object
Sleep for total seconds, raising AgentInterrupted if shutdown is requested while sleeping. Callers don't need to check the return value — the exception unwinds the loop for them.
66 67 68 |
# File 'lib/clacky/shutdown.rb', line 66 def sleep(seconds) raise Clacky::AgentInterrupted, "shutdown requested" if sleep_interruptibly(seconds) end |
.sleep_interruptibly(seconds) ⇒ Object
Sleep for total seconds but wake every INTERRUPT_SLICE to poll requested?. Returns true if shutdown was requested while sleeping.
44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/clacky/shutdown.rb', line 44 def sleep_interruptibly(seconds) deadline = Time.now + seconds loop do return true if requested? remaining = deadline - Time.now return false if remaining <= 0 Kernel.sleep [remaining, INTERRUPT_SLICE].min end end |