class AbstractThriftClient

Constants

APPLICATION_ERRORS
DEFAULTS

DEFAULT_BEFORE_METHOD = Proc.new {|method_name| puts “prepare call #{method_name} method.”} DEFAULT_AFTER_METHOD = Proc.new {|method_name| puts “called #{method_name} method.”} DEFAULT_ON_EXCEPTION = Proc.new {|method_name, e| puts “call #{method_name} method ouccur exception.”; raise e}

DISCONNECT_ERRORS

Public Class Methods

new(options = {}) click to toggle source
# File lib/thrift_client/abstract_thrift_client.rb, line 44
def initialize(options = {})
  user_options = initialize_options(options)

  servers = parse_servers(options["servers"])

  #initialize options
  @options = DEFAULTS.merge(user_options)

  #initialize servers info
  @server_list = servers.collect do |s|
    Server.new(s, @options)
  end.sort_by { rand }

  @callbacks = {}

  #initialize client methods
  @client_methods = []
  @options[:client_class].instance_methods.each do |method_name|
    if method_name != 'send_message' && method_name =~ /^send_(.*)$/
      instance_eval("def #{$1}(*args); handle_method(:'#{$1}', *args); end", __FILE__, __LINE__)
      @client_methods << $1
    end
  end
  @retry = @options[:retry]
  @state = 1
end

Public Instance Methods

add_callback(callback_type, &block) click to toggle source
# File lib/thrift_client/abstract_thrift_client.rb, line 71
def add_callback(callback_type, &block)
  case callback_type
  when :before_method, :after_method, :on_exception
    @callbacks[callback_type] ||= []
    @callbacks[callback_type].push(block)
  else
    raise ArgumentError.new("Unknown callback type #{callback_type},only support before_method|after_method|on_exception")
  end
  return self
end
destroy() click to toggle source
# File lib/thrift_client/abstract_thrift_client.rb, line 122
def destroy
  @state = -1
  @server_list.each { |server|
    begin
      server.destroy if server
    rescue Exception => e
      puts "destroy server #{server} error, #{e.message}, #{e.backtrace}"
    end
  }
end
handle_method(method_name, *args) click to toggle source

retry two times

# File lib/thrift_client/abstract_thrift_client.rb, line 83
def handle_method(method_name, *args)
  check_state
  server = next_server
  do_callbacks(:before_method, method_name)
  result = server.with do |client|
    tries = 0
    begin
      ensure_connected client
      client.send(method_name, *args)
    rescue *@options[:application_exception_classes] => e
      if(@callbacks[:on_exception] && @callbacks[:on_exception].length > 0)
        do_callbacks(:on_exception, method_name, e)
      else
        raise e
      end
    rescue *@options[:disconnect_exception_classes] => e
      # if e instance_of? Thrift::TransportException && e.type == Thrift::TransportException::TIMED_OUT
      begin
        if client.connected?
          client.disconnect
        end
      rescue Exception => e
        puts "disconnect error"
      end
      if tries < @retry # retry two times
        tries += 1
        retry
      end
      if(@callbacks[:on_exception] && @callbacks[:on_exception].length > 0)
        do_callbacks(:on_exception, method_name, e)
      else
        raise e
      end
    end
  end
  do_callbacks(:after_method, method_name)
  result
end

Private Instance Methods

check_state() click to toggle source
# File lib/thrift_client/abstract_thrift_client.rb, line 154
def check_state
  if @state < 0
    raise ClientAlreadyDestroyedError, "Client had already destroyed."
  end
end
do_callbacks(callback_type_sym, *args) click to toggle source

Calls all callbacks of the specified type with the given args

# File lib/thrift_client/abstract_thrift_client.rb, line 175
def do_callbacks(callback_type_sym, *args)
  return unless @callbacks[callback_type_sym]
  @callbacks[callback_type_sym].each do |callback|
    callback.call(*args)
  end
end
ensure_connected(client) click to toggle source

确保连接正常,在遇到异常时,重试一次

# File lib/thrift_client/abstract_thrift_client.rb, line 136
def ensure_connected(client)
  try = true
  begin
    if !client.connected?
      client.connect
    end
    client
  rescue Exception => e
    client.disconnect
    if try
      try = false
      retry
    else
      raise
    end
  end
end
initialize_options(options) click to toggle source
# File lib/thrift_client/abstract_thrift_client.rb, line 182
def initialize_options(options)
  user_options = {}
  if options["client_class"] != nil
    client_class_str = options["client_class"].strip
    if client_class_str.empty?
      raise ArgumentError, "client class is empty string"
    end
    begin
      client_class = eval(client_class_str)
      flag = client_class.ancestors.include?(Thrift::Client)
    rescue Exception => e
      raise ArgumentError, "could not find class #{client_class_str}"
    end
    if flag
      user_options.store(:client_class, client_class)
    else
      raise ArgumentError, "client class [#{client_class}] is not a subclass of Thrift::Client"
    end
  else
    raise ArgumentError, "client class is nil"
  end

  if options["protocol"] != nil
    case options["protocol"]
    when "compact"
      protocol_class = Thrift::CompactProtocol
    when "binary"
      protocol_class = Thrift::BinaryProtocol
    when "json"
      protocol_class = Thrift::JsonProtocol
    else
      raise ArgumentError, "Unknown protocol type [#{options["protocol"]}], use compact|binary|json"
    end
    user_options.store(:protocol, protocol_class)
  end

  if options["transport"] != nil
    case options["transport"]
    when "socket"
      transport_class = Thrift::Socket
    when "unix_socket"
      transport_class = Thrift::UNIXSocket
    when "eventmachine"
      transport_class = Thrift::EventMachineTransport
    when "em"
      transport_class = Thrift::EventMachineTransport
    else
      raise ArgumentError, "Unknown transport type [#{options["transport"]}], use socket|unix_socket|em(eventmachine)"
    end
    user_options.store(:transport, transport_class)
  end

  if options["framed"] != nil
    if options["framed"] != true
      user_options.store(:transport_wrapper, Thrift::BufferedTransport)
    end
  end

  if options["disconnect_exception_classes"] != nil
    user_define_disconnect_exceptions = options["disconnect_exception_classes"].split(",")
    user_define_disconnect_exceptions.each do |exception|
      exception_class = eval(exception)
      if exception_class.ancestors.include?(Exception)
        DISCONNECT_ERRORS.push(exception_class)
      else
        raise ArgumentError, "exception class [#{exception_class}] is not a subclass of Exception"
      end
    end
    DISCONNECT_ERRORS.uniq!
  end
  user_options.store(:disconnect_exception_classes, DISCONNECT_ERRORS)

  if options["application_exception_classes"] != nil
    user_define_application_exceptions = options["application_exception_classes"].split(",")
    user_define_application_exceptions.each do |exception|
      exception_class = eval(exception)
      if exception_class.ancestors.include?(Exception)
        APPLICATION_ERRORS.push(exception_class)
      else
        raise ArgumentError, "exception class [#{exception_class}] is not a subclass of Exception"
      end
    end
    APPLICATION_ERRORS.uniq!
  end
  user_options.store(:application_exception_classes, APPLICATION_ERRORS)

  if options["size"] != nil
    user_options.store(:size, options["size"].to_i)
  end

  if options["timeout"] != nil
    user_options.store(:timeout, options["timeout"].to_i)
  end

  if options["multiplexed"] != nil
    user_options.store(:multiplexed, options["multiplexed"] || options["multiplexed"] == 'true')
  end

  if options["retry"] != nil
    user_options.store(:retry, options["retry"])
  end
  user_options
end
next_server() click to toggle source
# File lib/thrift_client/abstract_thrift_client.rb, line 160
def next_server
  @current_server_index ||= 0
  @server_list.length.times do |i|
    index = (1 + @current_server_index + i) % @server_list.length
    @current_server_index = index
    return @server_list[index]
  end
end
no_available_server() click to toggle source
# File lib/thrift_client/abstract_thrift_client.rb, line 169
def no_available_server
  servers = @server_list.map { |s| s.to_s }.join(',')
  raise NoAvailableServerError, "No available servers in [#{servers}]."
end
parse_servers(servers_string) click to toggle source
# File lib/thrift_client/abstract_thrift_client.rb, line 286
def parse_servers(servers_string)
  if servers_string != nil
    servers_string = servers_string.strip
    if servers_string.empty?
      raise ArgumentError, "servers info is empty string"
    end
    return servers_string.split(",")
  else
    raise ArgumentError, "servers info is nil"
  end
end