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

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

.reasonObject



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

Returns:

  • (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