class Dalli::Protocol::ConnectionManager
Manages the socket connection to the server, including ensuring liveness and retries.
Constants
- DEFAULTS
Attributes
hostname[RW]
options[RW]
port[RW]
sock[R]
socket_type[RW]
Public Class Methods
new(hostname, port, socket_type, client_options)
click to toggle source
# File lib/dalli/protocol/connection_manager.rb, line 29 def initialize(hostname, port, socket_type, client_options) @hostname = hostname @port = port @socket_type = socket_type @options = DEFAULTS.merge(client_options) @request_in_progress = false @sock = nil @pid = nil reset_down_info end
Public Instance Methods
abort_request!()
click to toggle source
# File lib/dalli/protocol/connection_manager.rb, line 131 def abort_request! @request_in_progress = false end
close()
click to toggle source
# File lib/dalli/protocol/connection_manager.rb, line 102 def close return unless @sock begin @sock.close rescue StandardError nil end @sock = nil @pid = nil abort_request! end
close_on_fork()
click to toggle source
# File lib/dalli/protocol/connection_manager.rb, line 218 def close_on_fork message = 'Fork detected, re-connecting child process...' Dalli.logger.info { message } # Close socket on a fork, setting us up for reconnect # on next request. close raise Dalli::NetworkError, message end
confirm_ready!()
click to toggle source
# File lib/dalli/protocol/connection_manager.rb, line 97 def confirm_ready! error_on_request!(RuntimeError.new('Already writing to socket')) if request_in_progress? close_on_fork if fork_detected? end
connected?()
click to toggle source
# File lib/dalli/protocol/connection_manager.rb, line 115 def connected? !@sock.nil? end
down!()
click to toggle source
Marks the server instance as down. Updates the down_at state and raises an Dalli::NetworkError that includes the underlying error in the message. Calls close to clean up socket state
# File lib/dalli/protocol/connection_manager.rb, line 80 def down! close log_down_detected @error = $ERROR_INFO&.class&.name @msg ||= $ERROR_INFO&.message raise_down_error end
error_on_request!(err_or_string)
click to toggle source
# File lib/dalli/protocol/connection_manager.rb, line 175 def error_on_request!(err_or_string) log_warn_message(err_or_string) @fail_count += 1 if @fail_count >= max_allowed_failures down! else # Closes the existing socket, setting up for a reconnect # on next request reconnect!('Socket operation failed, retrying...') end end
establish_connection()
click to toggle source
# File lib/dalli/protocol/connection_manager.rb, line 49 def establish_connection Dalli.logger.debug { "Dalli::Server#connect #{name}" } @sock = memcached_socket @pid = Process.pid rescue SystemCallError, Timeout::Error, EOFError, SocketError => e # SocketError = DNS resolution failure error_on_request!(e) end
finish_request!()
click to toggle source
# File lib/dalli/protocol/connection_manager.rb, line 127 def finish_request! @request_in_progress = false end
fork_detected?()
click to toggle source
# File lib/dalli/protocol/connection_manager.rb, line 227 def fork_detected? @pid && @pid != Process.pid end
log_down_detected()
click to toggle source
# File lib/dalli/protocol/connection_manager.rb, line 231 def log_down_detected @last_down_at = Time.now if @down_at time = Time.now - @down_at Dalli.logger.debug { format('%<name>s is still down (for %<time>.3f seconds now)', name: name, time: time) } else @down_at = @last_down_at Dalli.logger.warn("#{name} is down") end end
log_up_detected()
click to toggle source
# File lib/dalli/protocol/connection_manager.rb, line 243 def log_up_detected return unless @down_at time = Time.now - @down_at Dalli.logger.warn { format('%<name>s is back (downtime was %<time>.3f seconds)', name: name, time: time) } end
log_warn_message(err_or_string)
click to toggle source
# File lib/dalli/protocol/connection_manager.rb, line 210 def log_warn_message(err_or_string) detail = err_or_string.is_a?(String) ? err_or_string : "#{err_or_string.class}: #{err_or_string.message}" Dalli.logger.warn do detail = err_or_string.is_a?(String) ? err_or_string : "#{err_or_string.class}: #{err_or_string.message}" "#{name} failed (count: #{@fail_count}) #{detail}" end end
max_allowed_failures()
click to toggle source
# File lib/dalli/protocol/connection_manager.rb, line 171 def max_allowed_failures @max_allowed_failures ||= @options[:socket_max_failures] || 2 end
memcached_socket()
click to toggle source
# File lib/dalli/protocol/connection_manager.rb, line 202 def memcached_socket if socket_type == :unix Dalli::Socket::UNIX.open(hostname, options) else Dalli::Socket::TCP.open(hostname, port, options) end end
name()
click to toggle source
# File lib/dalli/protocol/connection_manager.rb, line 41 def name if socket_type == :unix hostname else "#{hostname}:#{port}" end end
raise_down_error()
click to toggle source
# File lib/dalli/protocol/connection_manager.rb, line 89 def raise_down_error raise Dalli::NetworkError, "#{name} is down: #{@error} #{@msg}" end
read(count)
click to toggle source
# File lib/dalli/protocol/connection_manager.rb, line 145 def read(count) start_request! data = @sock.readfull(count) finish_request! data rescue SystemCallError, Timeout::Error, EOFError => e error_on_request!(e) end
read_line()
click to toggle source
# File lib/dalli/protocol/connection_manager.rb, line 135 def read_line start_request! data = @sock.gets("\r\n") error_on_request!('EOF in read_line') if data.nil? finish_request! data rescue SystemCallError, Timeout::Error, EOFError => e error_on_request!(e) end
read_nonblock()
click to toggle source
Non-blocking read. Should only be used in the context of a caller who has called start_request!, but not yet called finish_request!. Here to support the operation of the get_multi operation
# File lib/dalli/protocol/connection_manager.rb, line 167 def read_nonblock @sock.read_available end
reconnect!(message)
click to toggle source
# File lib/dalli/protocol/connection_manager.rb, line 188 def reconnect!(message) close sleep(options[:socket_failure_delay]) if options[:socket_failure_delay] raise Dalli::NetworkError, message end
reconnect_down_server?()
click to toggle source
# File lib/dalli/protocol/connection_manager.rb, line 59 def reconnect_down_server? return true unless @last_down_at time_to_next_reconnect = @last_down_at + options[:down_retry_delay] - Time.now return true unless time_to_next_reconnect.positive? Dalli.logger.debug do format('down_retry_delay not reached for %<name>s (%<time>.3f seconds left)', name: name, time: time_to_next_reconnect) end false end
request_in_progress?()
click to toggle source
# File lib/dalli/protocol/connection_manager.rb, line 119 def request_in_progress? @request_in_progress end
reset_down_info()
click to toggle source
# File lib/dalli/protocol/connection_manager.rb, line 194 def reset_down_info @fail_count = 0 @down_at = nil @last_down_at = nil @msg = nil @error = nil end
socket_timeout()
click to toggle source
# File lib/dalli/protocol/connection_manager.rb, line 93 def socket_timeout @socket_timeout ||= @options[:socket_timeout] end
start_request!()
click to toggle source
# File lib/dalli/protocol/connection_manager.rb, line 123 def start_request! @request_in_progress = true end
up!()
click to toggle source
# File lib/dalli/protocol/connection_manager.rb, line 72 def up! log_up_detected reset_down_info end
write(bytes)
click to toggle source
# File lib/dalli/protocol/connection_manager.rb, line 154 def write(bytes) start_request! result = @sock.write(bytes) finish_request! result rescue SystemCallError, Timeout::Error => e error_on_request!(e) end