Class: ServerEngine::Supervisor

Inherits:
Object
  • Object
show all
Includes:
ConfigLoader
Defined in:
lib/serverengine/supervisor.rb

Defined Under Namespace

Modules: ServerInitializer

Instance Attribute Summary collapse

Attributes included from ConfigLoader

#config, #logger

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(server_module, worker_module, load_config_proc = {}, &block) ⇒ Supervisor

Returns a new instance of Supervisor.



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/serverengine/supervisor.rb', line 34

def initialize(server_module, worker_module, load_config_proc={}, &block)
  @server_module = server_module
  @worker_module = worker_module

  @detach_flag = BlockingFlag.new
  @stop = false

  @pm = ProcessManager.new(
    auto_tick: false,
    graceful_kill_signal: Signals::GRACEFUL_STOP,
    immediate_kill_signal: Signals::IMMEDIATE_STOP,
    enable_heartbeat: true,
    auto_heartbeat: true,
  )

  super(load_config_proc, &block)

  @create_server_proc = Supervisor.create_server_proc(server_module, worker_module, @config)
  @server_process_name = @config[:server_process_name]

  @restart_server_process = !!@config[:restart_server_process]
  @unrecoverable_exit_codes = @config.fetch(:unrecoverable_exit_codes, [])
  @enable_detach = !!@config[:enable_detach]
  @exit_on_detach = !!@config[:exit_on_detach]
  @disable_reload = !!@config[:disable_reload]

  @command_pipe = @config.fetch(:command_pipe, nil)

  @command_sender = @config.fetch(:command_sender, ServerEngine.windows? ? "pipe" : "signal")
  if @command_sender == "pipe"
    extend CommandSender::Pipe
  else
    extend CommandSender::Signal
  end
end

Instance Attribute Details

#serverObject (readonly)

server is available after start_server() call.



71
72
73
# File 'lib/serverengine/supervisor.rb', line 71

def server
  @server
end

Class Method Details

.create_server_proc(server_module, worker_module, config) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/serverengine/supervisor.rb', line 90

def self.create_server_proc(server_module, worker_module, config)
  wt = config[:worker_type] || 'embedded'
  case wt
  when 'embedded'
    server_class = EmbeddedServer
  when 'process'
    server_class = MultiProcessServer
  when 'thread'
    server_class = MultiThreadServer
  when 'spawn'
    server_class = MultiSpawnServer
  else
    raise ArgumentError, "unexpected :worker_type option #{wt}"
  end

  lambda {|load_config_proc,logger|
    s = server_class.new(worker_module, load_config_proc)
    s.logger = logger
    s.extend(ServerInitializer)
    s.extend(server_module) if server_module
    s.instance_eval { initialize }
    s
  }
end

Instance Method Details

#create_server(logger) ⇒ Object



115
116
117
# File 'lib/serverengine/supervisor.rb', line 115

def create_server(logger)
  @server = @create_server_proc.call(@load_config_proc, logger)
end

#detach(stop_graceful) ⇒ Object



142
143
144
145
146
147
148
149
# File 'lib/serverengine/supervisor.rb', line 142

def detach(stop_graceful)
  if @enable_detach
    @detach_flag.set!
    _stop(stop_graceful)
  else
    stop(stop_graceful)
  end
end

#dumpObject



151
152
153
# File 'lib/serverengine/supervisor.rb', line 151

def dump
  _dump
end

#install_signal_handlersObject



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/serverengine/supervisor.rb', line 155

def install_signal_handlers
  s = self
  if @command_pipe
    Thread.new do
      until @command_pipe.closed?
        case @command_pipe.gets.chomp
        when "GRACEFUL_STOP"
          s.stop(true)
        when "IMMEDIATE_STOP"
          s.stop(false)
        when "GRACEFUL_RESTART"
          s.restart(true)
        when "IMMEDIATE_RESTART"
          s.restart(false)
        when "RELOAD"
          s.reload
        when "DETACH"
          s.detach(true)
        when "DUMP"
          s.dump
        end
      end
    end
  else
    SignalThread.new do |st|
      st.trap(Signals::GRACEFUL_STOP) { s.stop(true) }
      st.trap(Signals::IMMEDIATE_STOP) { s.stop(false) }
      st.trap(Signals::GRACEFUL_RESTART) { s.restart(true) }
      st.trap(Signals::IMMEDIATE_RESTART) { s.restart(false) }
      st.trap(Signals::RELOAD) { s.reload }
      st.trap(Signals::DETACH) { s.detach(true) }
      st.trap(Signals::DUMP) { s.dump }
    end
  end
end

#logger=(logger) ⇒ Object



224
225
226
227
# File 'lib/serverengine/supervisor.rb', line 224

def logger=(logger)
  super
  @pm.logger = @logger
end

#mainObject



191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# File 'lib/serverengine/supervisor.rb', line 191

def main
  # just in case Supervisor is not created by Daemon
  create_logger unless @logger

  @pmon = start_server

  while true
    # keep the child process alive in this loop
    until @detach_flag.wait(0.5)
      if try_join
        return if @stop   # supervisor stoppped explicitly
        if @stop_status # set exit code told by server
          raise SystemExit.new(@stop_status)
        end

        # child process died unexpectedly.
        # sleep @server_detach_wait sec and reboot process
        @pmon = reboot_server
      end
    end

    wait_until = Time.now + @server_detach_wait
    while (w = wait_until - Time.now) > 0
      break if try_join
      sleep [0.5, w].min
    end

    return if @exit_on_detach

    @detach_flag.reset!
  end
end

#reloadObject



134
135
136
137
138
139
140
# File 'lib/serverengine/supervisor.rb', line 134

def reload
  unless @disable_reload
    reload_config
  end
  @logger.reopen! if @logger
  _reload
end

#reload_configObject



73
74
75
76
77
78
79
80
81
82
# File 'lib/serverengine/supervisor.rb', line 73

def reload_config
  super

  @server_detach_wait = @config[:server_detach_wait] || 10.0
  @server_restart_wait = @config[:server_restart_wait] || 1.0

  @pm.configure(@config, prefix: 'server_')

  nil
end

#restart(stop_graceful) ⇒ Object



124
125
126
127
128
129
130
131
132
# File 'lib/serverengine/supervisor.rb', line 124

def restart(stop_graceful)
  reload_config
  @logger.reopen! if @logger
  if @restart_server_process
    _stop(stop_graceful)
  else
    _restart(stop_graceful)
  end
end

#stop(stop_graceful) ⇒ Object



119
120
121
122
# File 'lib/serverengine/supervisor.rb', line 119

def stop(stop_graceful)
  @stop = true
  _stop(stop_graceful)
end