Class: Siding::Restarter

Inherits:
Object
  • Object
show all
Defined in:
lib/siding/restarter.rb

Constant Summary collapse

MIN_INTERVAL =
3.0
MAX_INTERVAL =
60.0
IDLE_FRACTION =
0.1
SETTLE =
1.0
HANDOVER_INTERVAL =
0.5
QUIET =
:quiet
SETTLING =
:settling
BOOT =
:boot
SUPERSEDED =
:superseded

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(manifest:, project_key:, runtime:, logger:, env: ENV, clock: nil, busy: nil, superseded: nil, on_superseded: nil, spawner: nil) ⇒ Restarter

Returns a new instance of Restarter.



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/siding/restarter.rb', line 21

def initialize(manifest:, project_key:, runtime:, logger:, env: ENV, clock: nil, busy: nil, superseded: nil, on_superseded: nil, spawner: nil)
  @manifest = manifest
  @project_key = project_key
  @runtime = runtime
  @logger = logger
  @env = env
  @clock = clock || -> { Process.clock_gettime(Process::CLOCK_MONOTONIC) }
  @busy = busy || -> { false }
  @superseded = superseded || -> { false }
  @on_superseded = on_superseded
  @spawner = spawner
  @gate = Mutex.new
  @signal = Thread::Queue.new
  @running = false
  @last_activity = @clock.call
end

Instance Attribute Details

#loggerObject (readonly)

Returns the value of attribute logger.



19
20
21
# File 'lib/siding/restarter.rb', line 19

def logger
  @logger
end

#manifestObject (readonly)

Returns the value of attribute manifest.



19
20
21
# File 'lib/siding/restarter.rb', line 19

def manifest
  @manifest
end

#project_keyObject (readonly)

Returns the value of attribute project_key.



19
20
21
# File 'lib/siding/restarter.rb', line 19

def project_key
  @project_key
end

#runtimeObject (readonly)

Returns the value of attribute runtime.



19
20
21
# File 'lib/siding/restarter.rb', line 19

def runtime
  @runtime
end

Instance Method Details

#around_forkObject



82
83
84
85
86
87
88
89
# File 'lib/siding/restarter.rb', line 82

def around_fork
  quiesce do
    @watch&.stop
    yield
  ensure
    @watch = start_watch if @running
  end
end

#busy!Object Also known as: idle!



65
66
67
# File 'lib/siding/restarter.rb', line 65

def busy!
  @last_activity = @clock.call
end

#idle_seconds(now = @clock.call) ⇒ Object



70
71
72
# File 'lib/siding/restarter.rb', line 70

def idle_seconds(now = @clock.call)
  now - @last_activity
end

#interval_for(idle) ⇒ Object



74
75
76
# File 'lib/siding/restarter.rb', line 74

def interval_for(idle)
  [[idle * IDLE_FRACTION, MIN_INTERVAL].max, MAX_INTERVAL].min
end

#poll(now: @clock.call) ⇒ Object



91
92
93
94
95
# File 'lib/siding/restarter.rb', line 91

def poll(now: @clock.call)
  decision = tick(now: now)
  act(decision)
  decision
end

#quiesceObject



78
79
80
# File 'lib/siding/restarter.rb', line 78

def quiesce
  @gate.synchronize { yield }
end

#replacement_pidObject



107
108
109
110
111
112
113
# File 'lib/siding/restarter.rb', line 107

def replacement_pid
  pid = @replacement_pid
  return nil if pid.nil?
  return pid if alive?(pid)

  @replacement_pid = nil
end

#startObject



38
39
40
41
42
43
44
45
46
47
# File 'lib/siding/restarter.rb', line 38

def start
  return self if @thread

  @watch = start_watch

  @running = true
  @thread = Thread.new { poll_loop }
  @thread.name = "siding-restarter" if @thread.respond_to?(:name=)
  self
end

#stopObject



49
50
51
52
53
54
55
56
57
58
59
# File 'lib/siding/restarter.rb', line 49

def stop
  thread = @thread
  @running = false
  @thread = nil
  @watch&.stop
  return self if thread.nil?

  @signal << :stop
  thread.join(1) || thread.kill
  self
end

#tick(now: @clock.call) ⇒ Object



97
98
99
100
101
102
103
104
105
# File 'lib/siding/restarter.rb', line 97

def tick(now: @clock.call)
  return SUPERSEDED if @superseded.call
  return QUIET if @busy.call

  verdict = Staleness.validate(manifest, env: @env)
  return settled(QUIET) if verdict.fresh?

  settle(verdict.revision_label, now)
end

#watch_modeObject



61
62
63
# File 'lib/siding/restarter.rb', line 61

def watch_mode
  @watch ? @watch.mode_label : "poll"
end