File: //lib/ruby/vendor_ruby/moneta/shared.rb
module Moneta
# Shares a store between processes
#
# @example Share a store
# Moneta.build do
# use :Transformer, key: :marshal, value: :marshal
# use :Shared do
# adapter :GDBM, file: 'shared.db'
# end
# end
#
# @api public
class Shared < Wrapper
# @param [Hash] options
# @option options [Integer] :port (9000) TCP port
# @option options [String] :host Server hostname
# @option options [String] :socket Unix socket file name
def initialize(options = {}, &block)
@options = options
@builder = Builder.new(&block)
end
# (see Proxy#close)
def close
if @server
@server.stop
@thread.join
@server = @thread = nil
end
if @adapter
@adapter.close
@adapter = nil
end
end
protected
def wrap(*args)
connect
yield
end
def connect
@adapter ||= Adapters::Client.new(@options)
rescue Errno::ECONNREFUSED, Errno::ENOENT => ex
start_server
tries ||= 0
warn "Moneta::Shared - Failed to connect: #{ex.message}" if tries > 0
(tries += 1) < 3 ? retry : raise
end
# TODO: Implement this using forking (MRI) and threading (JRuby)
# to get maximal performance
def start_server
@adapter = Lock.new(@builder.build.last)
@server = Server.new(@adapter, @options)
@thread = Thread.new { @server.run }
sleep 0.1 until @server.running?
rescue Exception => ex
@adapter.close if @adapter
@adapter = nil
@server = nil
@thread = nil
warn "Moneta::Shared - Failed to start server: #{ex.message}"
end
end
end