Class: Servolux::Server
- Inherits:
-
Object
- Object
- Servolux::Server
- Includes:
- Threaded
- Defined in:
- lib/servolux/server.rb
Overview
Synopsis
The Server class makes it simple to create a server-type application in Ruby. A server in this context is any process that should run for a long period of time either in the foreground or as a daemon.
Details
The Server class provides for standard server features: process ID file management, signal handling, run loop, logging, etc. All that you need to provide is a run
method that will be called by the server’s run loop. Optionally, you can provide a block to the new
method and it will be called within the run loop instead of a run method.
SIGINT and SIGTERM are handled by default. These signals will gracefully shutdown the server by calling the shutdown
method (provided by default, too). A few other signals can be handled by defining a few methods on your server instance. For example, SIGINT is hanlded by the int
method (an alias for shutdown
). Likewise, SIGTERM is handled by the term
method (another alias for shutdown
). The following signal methods are recognized by the Server class:
Method | Signal | Default Action
--------+----------+----------------
hup SIGHUP none
int SIGINT shutdown
term SIGTERM shutdown
usr1 SIGUSR1 none
usr2 SIGUSR2 none
In order to handle SIGUSR1 you would define a usr1
method for your server.
There are a few other methods that are useful and should be mentioned. Two methods are called before and after the run loop starts: before_starting
and after_starting
. The first is called just before the run loop thread is created and started. The second is called just after the run loop thread has been created (no guarantee is made that the run loop thread has actually been scheduled).
Likewise, two other methods are called before and after the run loop is shutdown: before_stopping
and after_stopping
. The first is called just before the run loop thread is signaled for shutdown. The second is called just after the run loop thread has died; the after_stopping
method is guarnteed to NOT be called till after the run loop thread is well and truly dead.
Usage
For simple, quick and dirty servers just pass a block to the Server initializer. This block will be used as the run method.
server = Servolux::Server.new('Basic', :interval => 1) {
puts "I'm alive and well @ #{Time.now}"
}
server.startup
For more complex services you will need to define your own server methods: the run
method, signal handlers, and before/after methods. Any pattern that Ruby provides for defining methods on objects can be used to define these methods. In a nutshell:
Inheritance
class MyServer < Servolux::Server
def run
puts "I'm alive and well @ #{Time.now}"
end
end
server = MyServer.new('MyServer', :interval => 1)
server.startup
Extension
module MyServer
def run
puts "I'm alive and well @ #{Time.now}"
end
end
server = Servolux::Server.new('Module', :interval => 1)
server.extend MyServer
server.startup
Singleton Class
server = Servolux::Server.new('Singleton', :interval => 1)
class << server
def run
puts "I'm alive and well @ #{Time.now}"
end
end
server.startup
Examples
Signals
This example shows how to change the log level of the server when SIGUSR1 is sent to the process. The log level toggles between “debug” and the original log level each time SIGUSR1 is sent to the server process. Since this is a module, it can be used with any Servolux::Server instance.
module DebugSignal
def usr1
@old_log_level ||= nil
if @old_log_level
logger.level = @old_log_level
@old_log_level = nil
else
@old_log_level = logger.level
logger.level = :debug
end
end
end
server = Servolux::Server.new('Debugger', :interval => 2) {
logger.info "Running @ #{Time.now}"
logger.debug "hey look - a debug message"
}
server.extend DebugSignal
server.startup
Constant Summary collapse
- SIGNALS =
:stopdoc:
%w[HUP INT TERM USR1 USR2] & Signal.list.keys
- Error =
:startdoc:
Class.new(::Servolux::Error)
- DEFAULT_PID_FILE_MODE =
0640
Instance Attribute Summary collapse
-
#logger ⇒ Object
Returns the value of attribute logger.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
-
#pid_file ⇒ Object
Returns the PID file name used by the server.
-
#pid_file_mode ⇒ Object
Returns the value of attribute pid_file_mode.
Instance Method Summary collapse
-
#initialize(name, opts = {}, &block) ⇒ Server
constructor
call-seq: Server.new( name, options = {} ) { block }.
-
#shutdown ⇒ Server
(also: #int, #term)
Stop the server if it is running.
-
#startup(wait = false) ⇒ Server
Start the server running using it’s own internal thread.
-
#wait_for_shutdown ⇒ Object
If the server has been started, this method waits till the
shutdown
method has been called and has completed.
Methods included from Threaded
#_activity_thread, #continue_on_error=, #continue_on_error?, #finished_iterations?, #interval, #interval=, #iterations, #join, #maximum_iterations, #maximum_iterations=, #run, #running?, #start, #status, #stop, #wait
Constructor Details
#initialize(name, opts = {}, &block) ⇒ Server
call-seq:
Server.new( name, = {} ) { block }
Creates a new server identified by name and configured from the options hash. The block is run inside a separate thread that will loop at the configured interval.
Options
- logger <Logger>
-
The logger instance this server will use
- pid_file <String>
-
Location of the PID file
- interval <Numeric>
-
Sleep interval between invocations of the block
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/servolux/server.rb', line 151 def initialize( name, opts = {}, &block ) @name = name @mutex = Mutex.new @shutdown = nil self.logger = opts[:logger] self.pid_file = opts[:pid_file] self.pid_file_mode = opts[:pid_file_mode] || DEFAULT_PID_FILE_MODE self.interval = opts[:interval] || 0 if block eg = class << self; self; end eg.__send__(:define_method, :run, &block) end ary = %w[name logger pid_file].map { |var| self.send(var).nil? ? var : nil }.compact raise Error, "These variables are required: #{ary.join(', ')}." unless ary.empty? end |
Instance Attribute Details
#logger ⇒ Object
Returns the value of attribute logger.
135 136 137 |
# File 'lib/servolux/server.rb', line 135 def logger @logger end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
134 135 136 |
# File 'lib/servolux/server.rb', line 134 def name @name end |
#pid_file ⇒ Object
Returns the PID file name used by the server. If none was given, then the server name is used to create a PID file name.
246 247 248 |
# File 'lib/servolux/server.rb', line 246 def pid_file @pid_file ||= name.downcase.tr(' ','_') + '.pid' end |
#pid_file_mode ⇒ Object
Returns the value of attribute pid_file_mode.
137 138 139 |
# File 'lib/servolux/server.rb', line 137 def pid_file_mode @pid_file_mode end |
Instance Method Details
#shutdown ⇒ Server Also known as: int, term
Stop the server if it is running. This method will return after three things have occurred:
1) The ‘before_stopping’ method has returned. 2) The server’s activity thread has stopped. 3) The ‘after_stopping’ method has returned.
It is entirely possible that the activity thread will stop before either the before_stopping
or after_stopping
methods return. To make sure the server is completely stopped, use the wait_for_shutdown
method to be notified when the this shutdown
method is finished executing.
218 219 220 221 222 223 224 225 226 |
# File 'lib/servolux/server.rb', line 218 def shutdown return self unless running? stop @mutex.synchronize { @shutdown.signal @shutdown = nil } self end |
#startup(wait = false) ⇒ Server
Start the server running using it’s own internal thread. This method will not return until the server is shutdown.
Startup involves creating a PID file, registering signal handlers to shutdown the server, starting and joining the server thread. The PID file is deleted when this method returns.
If true
is passed to this method, then it will not return until the wait_for_shutdown
method has been called from another thread. This flag is used to ensure that the server has shutdown completely when shutdown by a signal.
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
# File 'lib/servolux/server.rb', line 186 def startup( wait = false ) return self if running? @mutex.synchronize { @shutdown = ConditionVariable.new } begin create_pid_file start trap_signals join wait_for_shutdown if wait ensure delete_pid_file end return self end |
#wait_for_shutdown ⇒ Object
If the server has been started, this method waits till the shutdown
method has been called and has completed. The current thread will be blocked until the server has been safely stopped.
232 233 234 235 236 237 |
# File 'lib/servolux/server.rb', line 232 def wait_for_shutdown @mutex.synchronize { @shutdown.wait(@mutex) unless @shutdown.nil? } self end |