module THTP::Utils

Methods for interacting with generated Thrift files

Public Instance Methods

args_class(service, rpc) click to toggle source

args class is named after RPC, e.g., get_things => Get_things_args

# File lib/thtp/utils.rb, line 41
def args_class(service, rpc)
  service.const_get("#{rpc.capitalize}_args")
end
canonical_name(klass) click to toggle source

Used to turn classes to canonical strings for routing and logging, e.g.,

  • MyServices::Thing::ThingService -> MyService.Thing.ThingService

  • MyServices::Thing::ThingRequest -> MyService.Thing.ThingRequest

  • MyServices::Thing::BadException -> MyService.Thing.BadException

@param klass [Class]

# File lib/thtp/utils.rb, line 93
def canonical_name(klass)
  klass.name.gsub('::', '.')
end
deserialize(transport, struct, protocol) click to toggle source

Thrift deserialisation

# File lib/thtp/utils.rb, line 52
def deserialize(transport, struct, protocol)
  struct.read(protocol.new(transport)) # read off the stream into Thrift objects
  struct # return input object with all fields filled out
rescue Thrift::ProtocolException, EOFError => e
  raise DeserializationError, e
end
deserialize_buffer(buffer, struct, protocol) click to toggle source
# File lib/thtp/utils.rb, line 59
def deserialize_buffer(buffer, struct, protocol)
  deserialize(Thrift::MemoryBufferTransport.new(buffer), struct, protocol)
end
deserialize_stream(in_stream, struct, protocol) click to toggle source
# File lib/thtp/utils.rb, line 63
def deserialize_stream(in_stream, struct, protocol)
  deserialize(Thrift::IOStreamTransport.new(in_stream, nil), struct, protocol)
end
elapsed_ms(start_time) click to toggle source

useful for benchmarking. returns wall clock ms since start time

# File lib/thtp/utils.rb, line 19
def elapsed_ms(start_time)
  ((get_time - start_time) * 1000).round
end
extract_rpcs(thrift_service) click to toggle source

@return array<Symbol> for a given thrift Service using reflection

because the Thrift compiler's generated definitions do not lend
themselves to external use
# File lib/thtp/utils.rb, line 28
def extract_rpcs(thrift_service)
  # it's really the Processor we want (the Client would work too)
  root = thrift_service < Thrift::Processor ? thrift_service : thrift_service::Processor
  # get all candidate classes that may contribute RPCs to this service
  root.ancestors.flat_map do |klass|
    next [] unless klass < Thrift::Processor
    klass.instance_methods(false).
      select { |method_name| method_name =~ /^process_/ }.
      map { |method_name| method_name.to_s.sub(/^process_/, '').to_sym }
  end
end
get_time() click to toggle source

get the current time, for benchmarking purposes. monotonic time is better than Time.now for this purposes. note, only works on Ruby 2.1.8+

# File lib/thtp/utils.rb, line 14
def get_time
  Process.clock_gettime(Process::CLOCK_MONOTONIC)
end
jsonify(obj) click to toggle source

Recursive object serialiser compatible with anything likely to appear in Thrift, in case ActiveSupport's as_json monkeypatch is unavailable

# File lib/thtp/utils.rb, line 99
def jsonify(obj)
  return obj.as_json if obj.respond_to?(:as_json) # ActiveSupport shortcut

  case obj
  when nil, false, true, Numeric # directly representable as JSON
    obj
  when Hash
    obj.each_with_object({}) { |(k, v), h| h[jsonify(k)] = jsonify(v) }
  when Enumerable
    obj.map { |v| jsonify(v) }
  else
    if obj.instance_variables.any?
      obj.instance_variables.each_with_object({}) do |iv, h|
        h[iv.to_s[1..-1].to_sym] = jsonify(obj.instance_variable_get(iv))
      end
    else
      obj.to_s # lowest common denominator serialisation
    end
  end
end
result_class(service, rpc) click to toggle source

result class is named after RPC, e.g., do_stuff => Do_stuff_result

# File lib/thtp/utils.rb, line 46
def result_class(service, rpc)
  service.const_get("#{rpc.capitalize}_result")
end
serialize(base_struct, transport, protocol) click to toggle source

Thrift serialisation

# File lib/thtp/utils.rb, line 69
def serialize(base_struct, transport, protocol)
  base_struct.write(protocol.new(transport))
  transport.tap(&:flush)
rescue Thrift::ProtocolException, EOFError => e
  raise SerializationError, e
end
serialize_buffer(base_struct, protocol) click to toggle source
# File lib/thtp/utils.rb, line 76
def serialize_buffer(base_struct, protocol)
  transport = Thrift::MemoryBufferTransport.new
  serialize(base_struct, transport, protocol) # write to output transport, an in-memory buffer
  transport.read(transport.available) # return serialised thrift
end
serialize_stream(base_struct, out_stream, protocol) click to toggle source
# File lib/thtp/utils.rb, line 82
def serialize_stream(base_struct, out_stream, protocol)
  serialize(base_struct, Thrift::IOStreamTransport.new(nil, out_stream), protocol)
end