class Moneta::Server

Moneta server to be used together with Moneta::Adapters::Client @api public

Public Class Methods

new(store, options = {}) click to toggle source

@param [Hash] options @option options [Integer] :port (9000) TCP port @option options [String] :socket Alternative Unix socket file name @option options [Integer] :timeout (1) Number of seconds to timeout on IO.select @option options [Integer] :max_size (0x100000) Maximum number of bytes

allowed to be sent by clients in requests
# File lib/moneta/server.rb, line 162
def initialize(store, options = {})
  options = configure(**options)
  @store = store
  @server = start(**options)
  @ios = [@server]
  @reads = @ios.dup
  @writes = []
  @connections = {}
  @running = false
end

Public Instance Methods

run() click to toggle source

Run the server

@note This method blocks!

# File lib/moneta/server.rb, line 183
def run
  raise 'Already running' if running?
  @stop = false
  @running = true
  begin
    mainloop until @stop
  ensure
    @running = false
    @server.close unless @server.closed?
    @ios
      .reject { |io| io == @server }
      .each { |io| close_connection(io) }
    File.unlink(config.socket) if config.socket rescue nil
  end
end
running?() click to toggle source

Is the server running

@return [Boolean] true if the server is running

# File lib/moneta/server.rb, line 176
def running?
  @running
end
stop() click to toggle source

Stop the server

# File lib/moneta/server.rb, line 200
def stop
  raise 'Not running' unless running?
  @stop = true
  @server.close
  nil
end

Private Instance Methods

accept_connection() click to toggle source
# File lib/moneta/server.rb, line 235
def accept_connection
  io = @server.accept
  @connections[io] = Connection.new(io, @store, config.max_size)
  @ios << io
  resume(io)
ensure
  @reads << @server
end
close_connection(io) click to toggle source
# File lib/moneta/server.rb, line 250
def close_connection(io)
  delete_connection(io)
  @connections.delete(io).resume(:close)
end
delete_connection(io) click to toggle source
# File lib/moneta/server.rb, line 244
def delete_connection(io)
  @ios.delete(io)
  @reads.delete(io)
  @writes.delete(io)
end
mainloop() click to toggle source
# File lib/moneta/server.rb, line 209
def mainloop
  if ready = IO.select(@reads, @writes, @ios, config.timeout)
    reads, writes, errors = ready
    errors.each { |io| close_connection(io) }

    @reads -= reads
    reads.each do |io|
      io == @server ? accept_connection : resume(io)
    end

    @writes -= writes
    writes.each { |io| resume(io) }
  end
rescue SignalException => signal
  warn "Moneta::Server - received #{signal}"
  case signal.signo
  when Signal.list['INT'], Signal.list['TERM']
    @stop = true # graceful exit
  end
rescue IOError => ex
  # We get a lot of these "closed stream" errors, which we ignore
  raise unless ex.message =~ /closed stream/
rescue Errno::EBADF => ex
  warn "Moneta::Server - #{ex.message}"
end
resume(io) click to toggle source
# File lib/moneta/server.rb, line 255
def resume(io)
  case result = @connections[io].resume
  when :closed # graceful exit
    delete_connection(io)
  when Exception # messy exit
    delete_connection(io)
    raise result
  when :read
    @reads << io
  when :write
    @writes << io
  end
end
start(host: '127.0.0.1', port: 9000, socket: nil) click to toggle source
# File lib/moneta/server.rb, line 269
def start(host: '127.0.0.1', port: 9000, socket: nil)
  if socket
    begin
      UNIXServer.open(socket)
    rescue Errno::EADDRINUSE
      if client = (UNIXSocket.open(socket) rescue nil)
        client.close
        raise
      end
      File.unlink(socket)
      tries ||= 0
      (tries += 1) < 3 ? retry : raise
    end
  else
    TCPServer.open(host, port)
  end
end
stats() click to toggle source
# File lib/moneta/server.rb, line 287
def stats
  {
    connections: @connections.length,
    reading: @reads.length,
    writing: @writes.length,
    total: @ios.length
  }
end