thrift_client 0.3.3 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,4 +1,12 @@
1
- v0.3.3 Allow for a timeout over all requests in a call.
1
+ v0.4.0. Add new EventMachine transport. This requires two layers of transport
2
+ configurability:
3
+ options[:transport] for EventMachine or Socket transports
4
+ options[:transport_wrapper] for optional Buffered or Framed Transport.
5
+ Clients will need to update their options to ensure they don't conflict with this change. (mperham)
6
+ Revert global timeouts. (ryanking)
7
+ Add support for HTTPClientTransport (Chris Sepic)
8
+
9
+ v0.3.3. Allow for a timeout over all requests in a call.
2
10
 
3
11
  v0.3.2. Fix connection close bug (nkallen, mattknox).
4
12
 
data/Manifest CHANGED
@@ -1,9 +1,21 @@
1
1
  CHANGELOG
2
2
  LICENSE
3
3
  Manifest
4
- README
4
+ README.rdoc
5
5
  Rakefile
6
6
  lib/thrift_client.rb
7
+ lib/thrift_client/connection.rb
8
+ lib/thrift_client/connection/base.rb
9
+ lib/thrift_client/connection/factory.rb
10
+ lib/thrift_client/connection/http.rb
11
+ lib/thrift_client/connection/socket.rb
12
+ lib/thrift_client/event_machine.rb
13
+ lib/thrift_client/simple.rb
7
14
  lib/thrift_client/thrift.rb
15
+ test/greeter/greeter.rb
16
+ test/greeter/greeter.thrift
17
+ test/greeter/server.rb
18
+ test/simple_test.rb
8
19
  test/test_helper.rb
20
+ test/thrift_client_http_test.rb
9
21
  test/thrift_client_test.rb
@@ -27,7 +27,7 @@ Instantiate a client:
27
27
  You can then make calls to the server via the <tt>client</tt> instance as if was your internal Thrift client. The connection will be opened lazily and methods will be proxied through.
28
28
 
29
29
  client.get_string_list_property("keyspaces")
30
-
30
+
31
31
  On failures, the client will try the remaining servers in the list before giving up. See ThriftClient for more.
32
32
 
33
33
  == Installation
@@ -36,6 +36,14 @@ You need Ruby 1.8 or 1.9. If you have those, just run:
36
36
 
37
37
  sudo gem install thrift_client
38
38
 
39
+ == Contributing
40
+
41
+ To contribute changes:
42
+
43
+ 1. Fork the project
44
+ 2. make your change, adding tests
45
+ 3. send a pull request to fauna and ryanking
46
+
39
47
  == Reporting problems
40
48
 
41
49
  The Github issue tracker is {here}[http://github.com/fauna/thrift_client/issues].
data/Rakefile CHANGED
@@ -14,4 +14,3 @@ Echoe.new("thrift_client") do |p|
14
14
  p.docs_host = "blog.evanweaver.com:~/www/bax/public/files/doc/"
15
15
  p.spec_pattern = "spec/*_spec.rb"
16
16
  end
17
-
@@ -0,0 +1,20 @@
1
+ module Connection
2
+ class Base
3
+ attr_accessor :transport, :server
4
+
5
+ def initialize(transport, transport_wrapper, server, timeout, error_hash)
6
+ @transport = transport
7
+ @transport_wrapper = transport_wrapper
8
+ @server = server
9
+ @timeout = timeout
10
+ @error_type = error_hash[:handles_error]
11
+ end
12
+
13
+ def connect!
14
+ raise NotImplementedError
15
+ end
16
+
17
+ def close
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,11 @@
1
+ module Connection
2
+ class Factory
3
+ def self.create(transport, transport_wrapper, server, timeout)
4
+ if transport == Thrift::HTTPClientTransport
5
+ Connection::HTTP.new(transport, transport_wrapper, server, timeout, :handles_error => Errno::ECONNREFUSED)
6
+ else
7
+ Connection::Socket.new(transport, transport_wrapper, server, timeout, :handles_error => Thrift::TransportException)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,18 @@
1
+ module Connection
2
+ class HTTP < Base
3
+ def connect!
4
+ uri = parse_server(@server)
5
+ @transport = Thrift::HTTPClientTransport.new(@server)
6
+ http = Net::HTTP.new(uri.host, uri.port)
7
+ http.use_ssl = uri.scheme == "https"
8
+ http.get(uri.path)
9
+ end
10
+
11
+ private
12
+ def parse_server(server)
13
+ uri = URI.parse(server)
14
+ raise ArgumentError, 'Servers must start with http' unless uri.scheme =~ /^http/
15
+ uri
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,22 @@
1
+ module Connection
2
+ class Socket < Base
3
+ def close
4
+ @transport.close
5
+ end
6
+
7
+ def connect!
8
+ host, port = parse_server(@server)
9
+ @transport = @transport.new(*[host, port.to_i, @timeout])
10
+ @transport = @transport_wrapper.new(@transport) if @transport_wrapper
11
+ @transport.open
12
+ end
13
+
14
+ private
15
+
16
+ def parse_server(server)
17
+ host, port = server.to_s.split(":")
18
+ raise ArgumentError, 'Servers must be in the form "host:port"' unless host and port
19
+ [host, port]
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,5 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + "/connection")
2
+ require "base"
3
+ require "socket"
4
+ require "http"
5
+ require "factory"
@@ -0,0 +1,141 @@
1
+ raise RuntimeError, "The eventmachine transport requires Ruby 1.9.x" if RUBY_VERSION < '1.9.0'
2
+
3
+ require 'eventmachine'
4
+ require 'fiber'
5
+
6
+ # EventMachine-ready Thrift connection
7
+ # Should not be used with a transport wrapper since it already performs buffering in Ruby.
8
+ module Thrift
9
+ class EventMachineTransport < BaseTransport
10
+ def initialize(host, port=9090, timeout=5)
11
+ @host, @port, @timeout = host, port, timeout
12
+ @connection = nil
13
+ end
14
+
15
+ def open?
16
+ @connection && @connection.connected?
17
+ end
18
+
19
+ def open
20
+ @connection = EventMachineConnection.connect(@host, @port, @timeout)
21
+ end
22
+
23
+ def close
24
+ @connection.close
25
+ end
26
+
27
+ def read(sz)
28
+ @connection.blocking_read(sz)
29
+ end
30
+
31
+ def write(buf)
32
+ @connection.send_data(buf)
33
+ end
34
+ end
35
+
36
+ module EventMachineConnection
37
+ GARBAGE_BUFFER_SIZE = 4096 # 4kB
38
+
39
+ include EM::Deferrable
40
+
41
+ def self.connect(host='localhost', port=9090, timeout=5, &block)
42
+ EM.connect(host, port, self, host, port) do |conn|
43
+ conn.pending_connect_timeout = timeout
44
+ end
45
+ end
46
+
47
+ def trap
48
+ begin
49
+ yield
50
+ rescue Exception => ex
51
+ puts ex.message
52
+ puts ex.backtrace.join("\n")
53
+ end
54
+ end
55
+
56
+ def initialize(host, port=9090)
57
+ @host, @port = host, port
58
+ @index = 0
59
+ @reconnecting = false
60
+ @connected = false
61
+ @buf = ''
62
+ end
63
+
64
+ def close
65
+ trap do
66
+ @connected = false
67
+ close_connection(true)
68
+ end
69
+ end
70
+
71
+ def blocking_read(size)
72
+ trap do
73
+ if can_read?(size)
74
+ yank(size)
75
+ else
76
+ raise ArgumentError, "Unexpected state" if @size or @callback
77
+
78
+ fiber = Fiber.current
79
+ @size = size
80
+ @callback = proc { |data|
81
+ fiber.resume(data)
82
+ }
83
+ Fiber.yield
84
+ end
85
+ end
86
+ end
87
+
88
+ def receive_data(data)
89
+ trap do
90
+ (@buf) << data
91
+
92
+ if @callback and can_read?(@size)
93
+ callback = @callback
94
+ data = yank(@size)
95
+ @callback = @size = nil
96
+ callback.call(data)
97
+ end
98
+ end
99
+ end
100
+
101
+ def connected?
102
+ @connected
103
+ end
104
+
105
+ def connection_completed
106
+ @reconnecting = false
107
+ @connected = true
108
+ succeed
109
+ end
110
+
111
+ def unbind
112
+ # If we disconnect, try to reconnect
113
+ if @connected or !@reconnecting
114
+ EM.add_timer(1) {
115
+ # XXX Connect timeout?
116
+ reconnect @host, @port
117
+ }
118
+ @connected = false
119
+ @reconnecting = true
120
+ end
121
+ end
122
+
123
+ def can_read?(size)
124
+ @buf.size >= @index + size
125
+ end
126
+
127
+ private
128
+
129
+ def yank(len)
130
+ data = @buf.slice(@index, len)
131
+ @index += len
132
+ @index = @buf.size if @index > @buf.size
133
+ if @index >= GARBAGE_BUFFER_SIZE
134
+ @buf = @buf.slice(@index..-1)
135
+ @index = 0
136
+ end
137
+ data
138
+ end
139
+
140
+ end
141
+ end
@@ -0,0 +1,263 @@
1
+ require 'socket'
2
+ require 'getoptlong'
3
+
4
+ class ThriftClient
5
+
6
+ # This is a simplified form of thrift, useful for clients only, and not
7
+ # making any attempt to have good performance. It's intended to be used by
8
+ # small command-line tools that don't want to install a dozen ruby files.
9
+ module Simple
10
+ VERSION_1 = 0x8001
11
+
12
+ # message types
13
+ CALL, REPLY, EXCEPTION = (1..3).to_a
14
+
15
+ # value types
16
+ STOP, VOID, BOOL, BYTE, DOUBLE, _, I16, _, I32, _, I64, STRING, STRUCT, MAP, SET, LIST = (0..15).to_a
17
+
18
+ FORMATS = {
19
+ BYTE => "c",
20
+ DOUBLE => "G",
21
+ I16 => "n",
22
+ I32 => "N",
23
+ }
24
+
25
+ SIZES = {
26
+ BYTE => 1,
27
+ DOUBLE => 8,
28
+ I16 => 2,
29
+ I32 => 4,
30
+ }
31
+
32
+ module ComplexType
33
+ module Extends
34
+ def type_id=(n)
35
+ @type_id = n
36
+ end
37
+
38
+ def type_id
39
+ @type_id
40
+ end
41
+ end
42
+
43
+ module Includes
44
+ def to_i
45
+ self.class.type_id
46
+ end
47
+
48
+ def to_s
49
+ args = self.values.map { |v| self.class.type_id == STRUCT ? v.name : v.to_s }.join(", ")
50
+ "#{self.class.name}.new(#{args})"
51
+ end
52
+ end
53
+ end
54
+
55
+ def self.make_type(type_id, name, *args)
56
+ klass = Struct.new("STT_#{name}", *args)
57
+ klass.send(:extend, ComplexType::Extends)
58
+ klass.send(:include, ComplexType::Includes)
59
+ klass.type_id = type_id
60
+ klass
61
+ end
62
+
63
+ ListType = make_type(LIST, "ListType", :element_type)
64
+ MapType = make_type(MAP, "MapType", :key_type, :value_type)
65
+ SetType = make_type(SET, "SetType", :element_type)
66
+ StructType = make_type(STRUCT, "StructType", :struct_class)
67
+
68
+ class << self
69
+ def pack_value(type, value)
70
+ case type
71
+ when BOOL
72
+ [ value ? 1 : 0 ].pack("c")
73
+ when STRING
74
+ [ value.size, value ].pack("Na*")
75
+ when I64
76
+ [ value >> 32, value & 0xffffffff ].pack("NN")
77
+ when ListType
78
+ [ type.element_type.to_i, value.size ].pack("cN") + value.map { |item| pack_value(type.element_type, item) }.join("")
79
+ when MapType
80
+ [ type.key_type.to_i, type.value_type.to_i, value.size ].pack("ccN") + value.map { |k, v| pack_value(type.key_type, k) + pack_value(type.value_type, v) }.join("")
81
+ when SetType
82
+ [ type.element_type.to_i, value.size ].pack("cN") + value.map { |item| pack_value(type.element_type, item) }.join("")
83
+ when StructType
84
+ value._pack
85
+ else
86
+ [ value ].pack(FORMATS[type])
87
+ end
88
+ end
89
+
90
+ def pack_request(method_name, arg_struct, request_id=0)
91
+ [ VERSION_1, CALL, method_name.to_s.size, method_name.to_s, request_id, arg_struct._pack ].pack("nnNa*Na*")
92
+ end
93
+
94
+ def read_value(s, type)
95
+ case type
96
+ when BOOL
97
+ s.read(1).unpack("c").first != 0
98
+ when STRING
99
+ len = s.read(4).unpack("N").first
100
+ s.read(len)
101
+ when I64
102
+ hi, lo = s.read(8).unpack("NN")
103
+ (hi << 32) | lo
104
+ when LIST
105
+ read_list(s)
106
+ when MAP
107
+ read_map(s)
108
+ when STRUCT
109
+ read_struct(s)
110
+ when ListType
111
+ read_list(s, type.element_type)
112
+ when MapType
113
+ read_map(s, type.key_type, type.value_type)
114
+ when StructType
115
+ read_struct(s, type.struct_class)
116
+ else
117
+ s.read(SIZES[type]).unpack(FORMATS[type]).first
118
+ end
119
+ end
120
+
121
+ def read_list(s, element_type=nil)
122
+ etype, len = s.read(5).unpack("cN")
123
+ expected_type = (element_type and element_type.to_i == etype.to_i) ? element_type : etype
124
+ rv = []
125
+ len.times do
126
+ rv << read_value(s, expected_type)
127
+ end
128
+ rv
129
+ end
130
+
131
+ def read_map(s, key_type=nil, value_type=nil)
132
+ ktype, vtype, len = s.read(6).unpack("ccN")
133
+ rv = {}
134
+ expected_key_type, expected_value_type = if key_type and value_type and key_type.to_i == ktype and value_type.to_i == vtype
135
+ [ key_type, value_type ]
136
+ else
137
+ [ ktype, vtype ]
138
+ end
139
+ len.times do
140
+ key = read_value(s, expected_key_type)
141
+ value = read_value(s, expected_value_type)
142
+ rv[key] = value
143
+ end
144
+ rv
145
+ end
146
+
147
+ def read_struct(s, struct_class=nil)
148
+ rv = struct_class.new()
149
+ while true
150
+ type = s.read(1).unpack("c").first
151
+ return rv if type == STOP
152
+ fid = s.read(2).unpack("n").first
153
+ field = struct_class ? struct_class._fields.find { |f| (f.fid == fid) and (f.type.to_i == type) } : nil
154
+ value = read_value(s, field ? field.type : type)
155
+ rv[field.name] = value if field
156
+ end
157
+ end
158
+
159
+ def read_response(s, rv_class)
160
+ version, message_type, method_name_len = s.read(8).unpack("nnN")
161
+ method_name = s.read(method_name_len)
162
+ seq_id = s.read(4).unpack("N").first
163
+ [ method_name, seq_id, read_struct(s, rv_class).rv ]
164
+ end
165
+ end
166
+
167
+ ## ----------------------------------------
168
+
169
+ class Field
170
+ attr_accessor :name, :type, :fid
171
+
172
+ def initialize(name, type, fid)
173
+ @name = name
174
+ @type = type
175
+ @fid = fid
176
+ end
177
+
178
+ def pack(value)
179
+ value.nil? ? "" : [ type.to_i, fid, ThriftClient::Simple.pack_value(type, value) ].pack("cna*")
180
+ end
181
+ end
182
+
183
+ class ThriftException < RuntimeError
184
+ def initialize(reason)
185
+ @reason = reason
186
+ end
187
+
188
+ def to_s
189
+ "ThriftException(#{@reason.inspect})"
190
+ end
191
+ end
192
+
193
+ module ThriftStruct
194
+ module Include
195
+ def _pack
196
+ self.class._fields.map { |f| f.pack(self[f.name]) }.join + [ STOP ].pack("c")
197
+ end
198
+ end
199
+
200
+ module Extend
201
+ def _fields
202
+ @fields
203
+ end
204
+
205
+ def _fields=(f)
206
+ @fields = f
207
+ end
208
+ end
209
+ end
210
+
211
+ def self.make_struct(name, *fields)
212
+ st_name = "ST_#{name}"
213
+ if Struct.constants.include?(st_name)
214
+ warn "#{caller[0]}: Struct::#{st_name} is already defined; returning original class."
215
+ Struct.const_get(st_name)
216
+ else
217
+ names = fields.map { |f| f.name.to_sym }
218
+ klass = Struct.new(st_name, *names)
219
+ klass.send(:include, ThriftStruct::Include)
220
+ klass.send(:extend, ThriftStruct::Extend)
221
+ klass._fields = fields
222
+ klass
223
+ end
224
+ end
225
+
226
+ class ThriftService
227
+ def initialize(sock)
228
+ @sock = sock
229
+ end
230
+
231
+ def self._arg_structs
232
+ @_arg_structs = {} if @_arg_structs.nil?
233
+ @_arg_structs
234
+ end
235
+
236
+ def self.thrift_method(name, rtype, *args)
237
+ arg_struct = ThriftClient::Simple.make_struct("Args__#{self.name}__#{name}", *args)
238
+ rv_struct = ThriftClient::Simple.make_struct("Retval__#{self.name}__#{name}", ThriftClient::Simple::Field.new(:rv, rtype, 0))
239
+ _arg_structs[name.to_sym] = [ arg_struct, rv_struct ]
240
+
241
+ arg_names = args.map { |a| a.name.to_s }.join(", ")
242
+ class_eval "def #{name}(#{arg_names}); _proxy(:#{name}#{args.size > 0 ? ', ' : ''}#{arg_names}); end"
243
+ end
244
+
245
+ def _proxy(method_name, *args)
246
+ cls = self.class.ancestors.find { |cls| cls.respond_to?(:_arg_structs) and cls._arg_structs[method_name.to_sym] }
247
+ arg_class, rv_class = cls._arg_structs[method_name.to_sym]
248
+ arg_struct = arg_class.new(*args)
249
+ @sock.write(ThriftClient::Simple.pack_request(method_name, arg_struct))
250
+ rv = ThriftClient::Simple.read_response(@sock, rv_class)
251
+ rv[2]
252
+ end
253
+
254
+ # convenience. robey is lazy.
255
+ [[ :field, "Field.new" ], [ :struct, "StructType.new" ],
256
+ [ :list, "ListType.new" ], [ :map, "MapType.new" ]].each do |new_name, old_name|
257
+ class_eval "def self.#{new_name}(*args); ThriftClient::Simple::#{old_name}(*args); end"
258
+ end
259
+
260
+ [ :void, :bool, :byte, :double, :i16, :i32, :i64, :string ].each { |sym| class_eval "def self.#{sym}; ThriftClient::Simple::#{sym.to_s.upcase}; end" }
261
+ end
262
+ end
263
+ end
@@ -1,4 +1,3 @@
1
-
2
1
  module Thrift
3
2
  class BufferedTransport
4
3
  def timeout=(timeout)
data/lib/thrift_client.rb CHANGED
@@ -1,4 +1,3 @@
1
-
2
1
  if ENV["ANCIENT_THRIFT"]
3
2
  $LOAD_PATH.unshift("/Users/eweaver/p/twitter/rails/vendor/gems/thrift-751142/lib")
4
3
  $LOAD_PATH.unshift("/Users/eweaver/p/twitter/rails/vendor/gems/thrift-751142/ext")
@@ -8,18 +7,19 @@ else
8
7
  require 'thrift'
9
8
  end
10
9
 
11
- require 'timeout'
12
10
  require 'rubygems'
13
11
  require 'thrift_client/thrift'
12
+ require 'thrift_client/connection'
14
13
 
15
14
  class ThriftClient
15
+
16
16
  class NoServersAvailable < StandardError; end
17
- class GlobalThriftClientTimeout < Timeout::Error; end
18
17
 
19
18
  DEFAULTS = {
20
19
  :protocol => Thrift::BinaryProtocol,
21
20
  :protocol_extra_params => [],
22
- :transport => Thrift::FramedTransport,
21
+ :transport => Thrift::Socket,
22
+ :transport_wrapper => Thrift::FramedTransport,
23
23
  :randomize_server_list => true,
24
24
  :exception_classes => [
25
25
  IOError,
@@ -52,8 +52,7 @@ Valid optional parameters are:
52
52
  <tt>:retries</tt>:: How many times to retry a request. Defaults to the number of servers defined.
53
53
  <tt>:server_retry_period</tt>:: How many seconds to wait before trying to reconnect after marking all servers as down. Defaults to <tt>1</tt>. Set to <tt>nil</tt> to retry endlessly.
54
54
  <tt>:server_max_requests</tt>:: How many requests to perform before moving on to the next server in the pool, regardless of error status. Defaults to <tt>nil</tt> (no limit).
55
- <tt>:global_timeout</tt>:: Specify the timeout for all connections made. Defaults to being disabled.
56
- <tt>:timeout</tt>:: Specify the default timeout in seconds per connection. Defaults to <tt>1</tt>.
55
+ <tt>:timeout</tt>:: Specify the default timeout in seconds. Defaults to <tt>1</tt>.
57
56
  <tt>:timeout_overrides</tt>:: Specify additional timeouts on a per-method basis, in seconds. Only works with <tt>Thrift::BufferedTransport</tt>.
58
57
  <tt>:defaults</tt>:: Specify default values to return on a per-method basis, if <tt>:raise</tt> is set to false.
59
58
 
@@ -66,17 +65,16 @@ Valid optional parameters are:
66
65
  @retries = options[:retries] || @server_list.size
67
66
 
68
67
  if @options[:timeout_overrides].any?
69
- if @options[:transport].instance_methods.include?("timeout=")
68
+ if (@options[:transport_wrapper] || @options[:transport]).method_defined?(:timeout=)
70
69
  @set_timeout = true
71
70
  else
72
- warn "ThriftClient: Timeout overrides have no effect with with transport type #{@options[:transport]}"
71
+ warn "ThriftClient: Timeout overrides have no effect with with transport type #{(@options[:transport_wrapper] || @options[:transport])}"
73
72
  end
74
73
  end
75
74
 
76
75
  @request_count = 0
77
76
  @max_requests = @options[:server_max_requests]
78
77
  @retry_period = @options[:server_retry_period]
79
- @global_timeout = @options[:global_timeout] || 0
80
78
  rebuild_live_server_list!
81
79
 
82
80
  @client_class.instance_methods.each do |method_name|
@@ -88,23 +86,18 @@ Valid optional parameters are:
88
86
 
89
87
  # Force the client to connect to the server.
90
88
  def connect!
91
- server = next_server
92
- host, port = server.to_s.split(":")
93
- raise ArgumentError, 'Servers must be in the form "host:port"' unless host and port
94
-
95
- @transport = @options[:transport].new(
96
- Thrift::Socket.new(host, port.to_i, @options[:timeout]))
97
- @transport.open
98
- @current_server = server
99
- @client = @client_class.new(@options[:protocol].new(@transport, *@options[:protocol_extra_params]))
100
- rescue Thrift::TransportException
89
+ @current_server = next_server
90
+ @connection = Connection::Factory.create(@options[:transport], @options[:transport_wrapper], @current_server, @options[:timeout])
91
+ @connection.connect!
92
+ @client = @client_class.new(@options[:protocol].new(@connection.transport, *@options[:protocol_extra_params]))
93
+ rescue Thrift::TransportException, Errno::ECONNREFUSED
101
94
  @transport.close rescue nil
102
95
  retry
103
96
  end
104
97
 
105
98
  # Force the client to disconnect from the server.
106
99
  def disconnect!(keep = true)
107
- @transport.close rescue nil
100
+ @connection.close rescue nil
108
101
 
109
102
  # Keep live servers in the list if we have a retry period. Otherwise,
110
103
  # always eject, because we will always re-add them.
@@ -119,16 +112,26 @@ Valid optional parameters are:
119
112
 
120
113
  private
121
114
 
122
- def proxy(method_name, *args)
123
- Timeout.timeout(@global_timeout, GlobalThriftClientTimeout) do
124
- raw_proxy(method_name, *args)
115
+ def next_server
116
+ if @retry_period
117
+ rebuild_live_server_list! if Time.now > @last_rebuild + @retry_period
118
+ raise NoServersAvailable, "No live servers in #{@server_list.inspect} since #{@last_rebuild.inspect}." if @live_server_list.empty?
119
+ elsif @live_server_list.empty?
120
+ rebuild_live_server_list!
121
+ end
122
+ @live_server_list.pop
123
+ end
124
+
125
+ def rebuild_live_server_list!
126
+ @last_rebuild = Time.now
127
+ if @options[:randomize_server_list]
128
+ @live_server_list = @server_list.sort_by { rand }
129
+ else
130
+ @live_server_list = @server_list.dup
125
131
  end
126
- rescue GlobalThriftClientTimeout => e
127
- disconnect!(false)
128
- raise e
129
132
  end
130
133
 
131
- def raw_proxy(method_name, *args)
134
+ def proxy(method_name, *args)
132
135
  disconnect! if @max_requests and @request_count >= @max_requests
133
136
  connect! unless @client
134
137
 
@@ -148,27 +151,8 @@ Valid optional parameters are:
148
151
  @client.timeout = @options[:timeout_overrides][method_name.to_sym] || @options[:timeout]
149
152
  end
150
153
 
151
- def handle_exception(e, method_name, args)
154
+ def handle_exception(e, method_name, args=nil)
152
155
  raise e if @options[:raise]
153
156
  @options[:defaults][method_name.to_sym]
154
157
  end
155
-
156
- def next_server
157
- if @retry_period
158
- rebuild_live_server_list! if Time.now > @last_rebuild + @retry_period
159
- raise NoServersAvailable, "No live servers in #{@server_list.inspect} since #{@last_rebuild.inspect}." if @live_server_list.empty?
160
- elsif @live_server_list.empty?
161
- rebuild_live_server_list!
162
- end
163
- @live_server_list.pop
164
- end
165
-
166
- def rebuild_live_server_list!
167
- @last_rebuild = Time.now
168
- if @options[:randomize_server_list]
169
- @live_server_list = @server_list.sort_by { rand }
170
- else
171
- @live_server_list = @server_list.dup
172
- end
173
- end
174
158
  end
@@ -0,0 +1,77 @@
1
+ #
2
+ # Autogenerated by Thrift
3
+ #
4
+ # DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
5
+ #
6
+
7
+ require 'thrift'
8
+
9
+ module Greeter
10
+ class Client
11
+ include ::Thrift::Client
12
+
13
+ def greeting(name)
14
+ send_greeting(name)
15
+ return recv_greeting()
16
+ end
17
+
18
+ def send_greeting(name)
19
+ send_message('greeting', Greeting_args, :name => name)
20
+ end
21
+
22
+ def recv_greeting()
23
+ result = receive_message(Greeting_result)
24
+ return result.success unless result.success.nil?
25
+ raise ::Thrift::ApplicationException.new(::Thrift::ApplicationException::MISSING_RESULT, 'greeting failed: unknown result')
26
+ end
27
+
28
+ end
29
+
30
+ class Processor
31
+ include ::Thrift::Processor
32
+
33
+ def process_greeting(seqid, iprot, oprot)
34
+ args = read_args(iprot, Greeting_args)
35
+ result = Greeting_result.new()
36
+ result.success = @handler.greeting(args.name)
37
+ write_result(result, oprot, 'greeting', seqid)
38
+ end
39
+
40
+ end
41
+
42
+ # HELPER FUNCTIONS AND STRUCTURES
43
+
44
+ class Greeting_args
45
+ include ::Thrift::Struct
46
+ NAME = 1
47
+
48
+ ::Thrift::Struct.field_accessor self, :name
49
+ FIELDS = {
50
+ NAME => {:type => ::Thrift::Types::STRING, :name => 'name'}
51
+ }
52
+
53
+ def struct_fields; FIELDS; end
54
+
55
+ def validate
56
+ end
57
+
58
+ end
59
+
60
+ class Greeting_result
61
+ include ::Thrift::Struct
62
+ SUCCESS = 0
63
+
64
+ ::Thrift::Struct.field_accessor self, :success
65
+ FIELDS = {
66
+ SUCCESS => {:type => ::Thrift::Types::STRING, :name => 'success'}
67
+ }
68
+
69
+ def struct_fields; FIELDS; end
70
+
71
+ def validate
72
+ end
73
+
74
+ end
75
+
76
+ end
77
+
@@ -0,0 +1,3 @@
1
+ service Greeter {
2
+ string greeting(1:string name)
3
+ }
@@ -0,0 +1,40 @@
1
+ module Greeter
2
+ class Handler
3
+ def greeting(name)
4
+ "hello there #{name}!"
5
+ end
6
+ end
7
+
8
+ class Server
9
+ def initialize(port)
10
+ @port = port
11
+ handler = Greeter::Handler.new
12
+ processor = Greeter::Processor.new(handler)
13
+ transport = Thrift::ServerSocket.new("127.0.0.1", port)
14
+ transportFactory = Thrift::FramedTransportFactory.new()
15
+ @server = Thrift::SimpleServer.new(processor, transport, transportFactory)
16
+ end
17
+
18
+ def serve
19
+ @server.serve()
20
+ end
21
+ end
22
+
23
+ # client:
24
+ # trans = Thrift::HTTPClientTransport.new("http://127.0.0.1:9292/greeter")
25
+ # prot = Thrift::BinaryProtocol.new(trans)
26
+ # c = Greeter::Client.new(prot)
27
+ class HTTPServer
28
+ def initialize(uri)
29
+ uri = URI.parse(uri)
30
+ handler = Greeter::Handler.new
31
+ processor = Greeter::Processor.new(handler)
32
+ path = uri.path[1..-1]
33
+ @server = Thrift::MongrelHTTPServer.new(processor, :port => uri.port, :ip => uri.host, :path => path)
34
+ end
35
+
36
+ def serve
37
+ @server.serve()
38
+ end
39
+ end
40
+ end
data/test/simple_test.rb CHANGED
@@ -2,18 +2,18 @@
2
2
  require "#{File.dirname(__FILE__)}/test_helper"
3
3
 
4
4
  class SimpleTest < Test::Unit::TestCase
5
-
5
+
6
6
  S = ThriftClient::Simple
7
7
  S.make_struct("Example", S::Field.new(:name, S::STRING, 1))
8
8
  S.make_struct("Args")
9
9
  S.make_struct("Retval", S::Field.new(:rv, S::I32, 0))
10
-
10
+
11
11
  def test_definition
12
12
  assert Struct::ST_Example
13
13
  assert Struct::ST_Args
14
14
  assert Struct::ST_Retval
15
15
  end
16
-
16
+
17
17
  ## Encoding
18
18
 
19
19
  def test_boolean_encoding
@@ -69,7 +69,7 @@ class SimpleTest < Test::Unit::TestCase
69
69
  assert_equal "\x80\x01\x00\x01\x00\x00\x00\x09getHeight\x00\x00\x00\x17\x00",
70
70
  S.pack_request("getHeight", Struct::ST_Args.new, 23)
71
71
  end
72
-
72
+
73
73
  ## Decoding
74
74
 
75
75
  def test_boolean_decoding
@@ -133,5 +133,5 @@ class SimpleTest < Test::Unit::TestCase
133
133
  StringIO.new("\x80\x01\x00\x02\x00\x00\x00\x09getHeight\x00\x00\x00\xff\x08\x00\x00\x00\x00\x00\x01\x00"),
134
134
  Struct::ST_Retval)
135
135
  end
136
-
136
+
137
137
  end
data/test/test_helper.rb CHANGED
@@ -4,5 +4,9 @@ require 'benchmark'
4
4
  $LOAD_PATH << "#{File.expand_path(File.dirname(__FILE__))}/../lib"
5
5
  require 'thrift_client'
6
6
  require 'thrift_client/simple'
7
- require 'scribe'
7
+
8
+ $LOAD_PATH << File.expand_path(File.dirname(__FILE__))
9
+ require 'greeter/greeter'
10
+ require 'greeter/server'
11
+
8
12
  begin; require 'ruby-debug'; rescue LoadError; end
@@ -0,0 +1,54 @@
1
+ require "#{File.dirname(__FILE__)}/test_helper"
2
+ require "thrift/server/mongrel_http_server"
3
+
4
+ class ThriftClientHTTPTest < Test::Unit::TestCase
5
+
6
+ def setup
7
+ @servers = ["http://127.0.0.1:1461/greeter", "http://127.0.0.1:1462/greeter", "http://127.0.0.1:1463/greeter"]
8
+ @socket = 1461
9
+ @timeout = 0.2
10
+ @options = {:protocol_extra_params => [false]}
11
+ @pid = Process.fork do
12
+ Signal.trap("INT") { exit }
13
+ Greeter::HTTPServer.new(@servers.last).serve
14
+ end
15
+ # Need to give the child process a moment to open the listening socket or
16
+ # we get occasional "could not connect" errors in tests.
17
+ sleep 0.05
18
+ end
19
+
20
+ def teardown
21
+ Process.kill("INT", @pid)
22
+ Process.wait
23
+ end
24
+
25
+ def test_bad_uri
26
+ assert_raises URI::InvalidURIError do
27
+ @options.merge!({ :protocol => Thrift::BinaryProtocol, :transport => Thrift::HTTPClientTransport })
28
+ ThriftClient.new(Greeter::Client, "127.0.0.1:1463", @options).greeting("someone")
29
+ end
30
+ end
31
+
32
+ def test_bad_uri_no_http
33
+ assert_raises ArgumentError do
34
+ @options.merge!({ :protocol => Thrift::BinaryProtocol, :transport => Thrift::HTTPClientTransport })
35
+ ThriftClient.new(Greeter::Client, "//127.0.0.1:1463", @options).greeting("someone")
36
+ end
37
+ end
38
+
39
+ def test_valid_server
40
+ assert_nothing_raised do
41
+ @options.merge!({ :protocol => Thrift::BinaryProtocol, :transport => Thrift::HTTPClientTransport })
42
+ ThriftClient.new(Greeter::Client, "http://127.0.0.1:1463/greeter", @options).greeting("someone")
43
+ end
44
+ end
45
+
46
+ def test_non_random_fall_through
47
+ @servers = ["http://127.0.0.1:1463/greeter", "http://127.0.0.1:1461/greeter", "http://127.0.0.1:1462/greeter"]
48
+ assert_nothing_raised do
49
+ @options.merge!({ :protocol => Thrift::BinaryProtocol, :transport => Thrift::HTTPClientTransport })
50
+ ThriftClient.new(Greeter::Client, @servers, @options.merge(:randomize_server_list => false)).greeting("someone")
51
+ end
52
+ end
53
+
54
+ end
@@ -1,58 +1,74 @@
1
1
  require "#{File.dirname(__FILE__)}/test_helper"
2
2
 
3
3
  class ThriftClientTest < Test::Unit::TestCase
4
+
4
5
  def setup
5
- @entry = [ScribeThrift::LogEntry.new(:message => "something", :category => "thrift_client")]
6
6
  @servers = ["127.0.0.1:1461", "127.0.0.1:1462", "127.0.0.1:1463"]
7
7
  @socket = 1461
8
8
  @timeout = 0.2
9
9
  @options = {:protocol_extra_params => [false]}
10
+ @pid = Process.fork do
11
+ Signal.trap("INT") { exit }
12
+ Greeter::Server.new("1463").serve
13
+ end
14
+ # Need to give the child process a moment to open the listening socket or
15
+ # we get occasional "could not connect" errors in tests.
16
+ sleep 0.05
17
+ end
18
+
19
+ def teardown
20
+ Process.kill("INT", @pid)
21
+ Process.wait
10
22
  end
11
23
 
12
24
  def test_live_server
13
25
  assert_nothing_raised do
14
- ThriftClient.new(ScribeThrift::Client, @servers.last, @options).Log(@entry)
26
+ ThriftClient.new(Greeter::Client, @servers.last, @options).greeting("someone")
15
27
  end
16
28
  end
17
29
 
18
30
  def test_non_random_fall_through
19
31
  assert_nothing_raised do
20
- ThriftClient.new(ScribeThrift::Client, @servers, @options.merge(:randomize_server_list => false)).Log(@entry)
32
+ ThriftClient.new(Greeter::Client, @servers, @options.merge(:randomize_server_list => false)).greeting("someone")
21
33
  end
22
34
  end
23
35
 
24
36
  def test_dont_raise
25
37
  assert_nothing_raised do
26
- ThriftClient.new(ScribeThrift::Client, @servers.first, @options.merge(:raise => false)).Log(@entry)
38
+ ThriftClient.new(Greeter::Client, @servers.first, @options.merge(:raise => false)).greeting("someone")
27
39
  end
28
40
  end
29
41
 
30
42
  def test_dont_raise_with_defaults
31
- client = ThriftClient.new(ScribeThrift::Client, @servers.first, @options.merge(:raise => false, :defaults => {:Log => 1}))
32
- assert_equal 1, client.Log(@entry)
43
+ client = ThriftClient.new(Greeter::Client, @servers.first, @options.merge(:raise => false, :defaults => {:greeting => 1}))
44
+ assert_equal 1, client.greeting
33
45
  end
34
46
 
35
47
  def test_defaults_dont_override_no_method_error
36
- client = ThriftClient.new(ScribeThrift::Client, @servers, @options.merge(:raise => false, :defaults => {:Missing => 2}))
37
- assert_raises(NoMethodError) { client.Missing(@entry) }
48
+ client = ThriftClient.new(Greeter::Client, @servers, @options.merge(:raise => false, :defaults => {:Missing => 2}))
49
+ assert_raises(NoMethodError) { client.Missing }
38
50
  end
39
51
 
40
52
  def test_random_fall_through
41
53
  assert_nothing_raised do
42
- 10.times { ThriftClient.new(ScribeThrift::Client, @servers, @options).Log(@entry) }
54
+ 10.times do
55
+ client = ThriftClient.new(Greeter::Client, @servers, @options)
56
+ client.greeting("someone")
57
+ client.disconnect!
58
+ end
43
59
  end
44
60
  end
45
61
 
46
62
  def test_lazy_connection
47
63
  assert_nothing_raised do
48
- ThriftClient.new(ScribeThrift::Client, @servers[0,2])
64
+ ThriftClient.new(Greeter::Client, @servers[0,2])
49
65
  end
50
66
  end
51
67
 
52
68
  def test_no_servers_eventually_raise
53
- client = ThriftClient.new(ScribeThrift::Client, @servers[0,2], @options)
69
+ client = ThriftClient.new(Greeter::Client, @servers[0,2], @options)
54
70
  assert_raises(ThriftClient::NoServersAvailable) do
55
- client.Log(@entry)
71
+ client.greeting("someone")
56
72
  client.disconnect!
57
73
  end
58
74
  end
@@ -61,13 +77,12 @@ class ThriftClientTest < Test::Unit::TestCase
61
77
  stub_server(@socket) do |socket|
62
78
  measurement = Benchmark.measure do
63
79
  assert_raises(Thrift::TransportException) do
64
- ThriftClient.new(ScribeThrift::Client, "127.0.0.1:#{@socket}",
80
+ ThriftClient.new(Greeter::Client, "127.0.0.1:#{@socket}",
65
81
  @options.merge(:timeout => @timeout)
66
- ).Log(@entry)
82
+ ).greeting("someone")
67
83
  end
68
84
  end
69
- assert((measurement.real > @timeout - 0.01), "#{measurement.real} < #{@timeout}")
70
- assert((measurement.real < @timeout + 0.01), "#{measurement.real} > #{@timeout}")
85
+ assert((measurement.real > @timeout), "#{measurement.real} < #{@timeout}")
71
86
  end
72
87
  end
73
88
 
@@ -75,13 +90,12 @@ class ThriftClientTest < Test::Unit::TestCase
75
90
  stub_server(@socket) do |socket|
76
91
  measurement = Benchmark.measure do
77
92
  assert_raises(Thrift::TransportException) do
78
- ThriftClient.new(ScribeThrift::Client, "127.0.0.1:#{@socket}",
79
- @options.merge(:timeout => @timeout, :transport => Thrift::BufferedTransport)
80
- ).Log(@entry)
93
+ ThriftClient.new(Greeter::Client, "127.0.0.1:#{@socket}",
94
+ @options.merge(:timeout => @timeout, :transport_wrapper => Thrift::BufferedTransport)
95
+ ).greeting("someone")
81
96
  end
82
97
  end
83
- assert((measurement.real > @timeout - 0.01), "#{measurement.real} < #{@timeout}")
84
- assert((measurement.real < @timeout + 0.01), "#{measurement.real} > #{@timeout}")
98
+ assert((measurement.real > @timeout), "#{measurement.real} < #{@timeout}")
85
99
  end
86
100
  end
87
101
 
@@ -91,30 +105,29 @@ class ThriftClientTest < Test::Unit::TestCase
91
105
  stub_server(@socket) do |socket|
92
106
  measurement = Benchmark.measure do
93
107
  assert_raises(Thrift::TransportException) do
94
- ThriftClient.new(ScribeThrift::Client, "127.0.0.1:#{@socket}",
95
- @options.merge(:timeout => @timeout, :timeout_overrides => {:Log => log_timeout}, :transport => Thrift::BufferedTransport)
96
- ).Log(@entry)
108
+ ThriftClient.new(Greeter::Client, "127.0.0.1:#{@socket}",
109
+ @options.merge(:timeout => @timeout, :timeout_overrides => {:greeting => log_timeout}, :transport_wrapper => Thrift::BufferedTransport)
110
+ ).greeting("someone")
97
111
  end
98
112
  end
99
- assert((measurement.real > log_timeout - 0.01), "#{measurement.real} < #{log_timeout }")
100
- assert((measurement.real < log_timeout + 0.01), "#{measurement.real} > #{log_timeout}")
113
+ assert((measurement.real > log_timeout), "#{measurement.real} < #{log_timeout}")
101
114
  end
102
115
  end
103
116
 
104
117
  def test_retry_period
105
- client = ThriftClient.new(ScribeThrift::Client, @servers[0,2], @options.merge(:server_retry_period => 1))
106
- assert_raises(ThriftClient::NoServersAvailable) { client.Log(@entry) }
118
+ client = ThriftClient.new(Greeter::Client, @servers[0,2], @options.merge(:server_retry_period => 1))
119
+ assert_raises(ThriftClient::NoServersAvailable) { client.greeting("someone") }
107
120
  sleep 1.1
108
- assert_raises(ThriftClient::NoServersAvailable) { client.Log(@entry) }
121
+ assert_raises(ThriftClient::NoServersAvailable) { client.greeting("someone") }
109
122
  end
110
-
123
+
111
124
  def test_server_max_requests
112
- client = ThriftClient.new(ScribeThrift::Client, @servers, @options.merge(:server_max_requests => 2))
113
- client.Log(@entry)
125
+ client = ThriftClient.new(Greeter::Client, @servers, @options.merge(:server_max_requests => 2))
126
+ client.greeting("someone")
114
127
  internal_client = client.client
115
- client.Log(@entry)
128
+ client.greeting("someone")
116
129
  assert_equal internal_client, client.client
117
- client.Log(@entry)
130
+ client.greeting("someone")
118
131
  assert_not_equal internal_client, client.client
119
132
  end
120
133
 
@@ -2,22 +2,24 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{thrift_client}
5
- s.version = "0.3.3"
5
+ s.version = "0.4.0"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0.8") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Evan Weaver"]
9
- s.date = %q{2010-01-11}
9
+ s.cert_chain = ["/Users/ryan/.gemkeys/gem-public_cert.pem"]
10
+ s.date = %q{2010-02-18}
10
11
  s.description = %q{A Thrift client wrapper that encapsulates some common failover behavior.}
11
12
  s.email = %q{}
12
- s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README", "lib/thrift_client.rb", "lib/thrift_client/thrift.rb"]
13
- s.files = ["CHANGELOG", "LICENSE", "Manifest", "README", "Rakefile", "lib/thrift_client.rb", "lib/thrift_client/thrift.rb", "test/test_helper.rb", "test/thrift_client_test.rb", "thrift_client.gemspec", "test/simple_test.rb"]
13
+ s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README.rdoc", "lib/thrift_client.rb", "lib/thrift_client/connection.rb", "lib/thrift_client/connection/base.rb", "lib/thrift_client/connection/factory.rb", "lib/thrift_client/connection/http.rb", "lib/thrift_client/connection/socket.rb", "lib/thrift_client/event_machine.rb", "lib/thrift_client/simple.rb", "lib/thrift_client/thrift.rb"]
14
+ s.files = ["CHANGELOG", "LICENSE", "Manifest", "README.rdoc", "Rakefile", "lib/thrift_client.rb", "lib/thrift_client/connection.rb", "lib/thrift_client/connection/base.rb", "lib/thrift_client/connection/factory.rb", "lib/thrift_client/connection/http.rb", "lib/thrift_client/connection/socket.rb", "lib/thrift_client/event_machine.rb", "lib/thrift_client/simple.rb", "lib/thrift_client/thrift.rb", "test/greeter/greeter.rb", "test/greeter/greeter.thrift", "test/greeter/server.rb", "test/simple_test.rb", "test/test_helper.rb", "test/thrift_client_http_test.rb", "test/thrift_client_test.rb", "thrift_client.gemspec"]
14
15
  s.homepage = %q{http://blog.evanweaver.com/files/doc/fauna/thrift_client/}
15
- s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Thrift_client", "--main", "README"]
16
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Thrift_client", "--main", "README.rdoc"]
16
17
  s.require_paths = ["lib"]
17
18
  s.rubyforge_project = %q{fauna}
18
19
  s.rubygems_version = %q{1.3.5}
20
+ s.signing_key = %q{/Users/ryan/.gemkeys/gem-private_key.pem}
19
21
  s.summary = %q{A Thrift client wrapper that encapsulates some common failover behavior.}
20
- s.test_files = ["test/simple_test.rb", "test/test_helper.rb", "test/thrift_client_test.rb"]
22
+ s.test_files = ["test/simple_test.rb", "test/test_helper.rb", "test/thrift_client_http_test.rb", "test/thrift_client_test.rb"]
21
23
 
22
24
  if s.respond_to? :specification_version then
23
25
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
data.tar.gz.sig ADDED
Binary file
metadata CHANGED
@@ -1,15 +1,36 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: thrift_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.3
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evan Weaver
8
8
  autorequire:
9
9
  bindir: bin
10
- cert_chain: []
10
+ cert_chain:
11
+ - |
12
+ -----BEGIN CERTIFICATE-----
13
+ MIIDNjCCAh6gAwIBAgIBADANBgkqhkiG9w0BAQUFADBBMQ0wCwYDVQQDDARyeWFu
14
+ MRswGQYKCZImiZPyLGQBGRYLdGhlcnlhbmtpbmcxEzARBgoJkiaJk/IsZAEZFgNj
15
+ b20wHhcNMTAwMTA4MTc1MDM0WhcNMTEwMTA4MTc1MDM0WjBBMQ0wCwYDVQQDDARy
16
+ eWFuMRswGQYKCZImiZPyLGQBGRYLdGhlcnlhbmtpbmcxEzARBgoJkiaJk/IsZAEZ
17
+ FgNjb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDLPp+0PtRT3qCI
18
+ 02sMsADSn7Uf1GpyXUtk4Fb94LqUO6Scl91YDmbFMpjzrQwQvBYMIVreWcwSish6
19
+ nip6WEk9lqXcOeDmex/qY2/FVXG8ffqjFHiNiN9vpWrWj5VMICequ+ftzWLKsPIS
20
+ DGJ4o+Z6wEYRuirgaRPCYAUDPglsaqctJ56wPuycryMe5+ApSkOS9iLWMprQKEAq
21
+ j2R2OBV0dSARdbtzuKwrP7sLDo7uPa0egFBUlcZ+nujGr4LvmpryB8scNRNmZK1w
22
+ 1rEI7O06CbULj08qYxEhnKmFE7LbBoN/HrmvZLVQK5mWuiZQhtmJuhBfStJsaDux
23
+ 5tBEkYZVAgMBAAGjOTA3MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQW
24
+ BBSnLarDEo5eBE2arSMrBdOOhtrnPTANBgkqhkiG9w0BAQUFAAOCAQEANER07s4K
25
+ Pvc1DSduliRDMUax/VSfLzDTtTAQwuSAPDrWAYXKugcJtOZOXjDbGL7c5zoWmy9u
26
+ Fn5vEVdm/93J+84D/IMaaof3BwX/NNEYH01CeZEIGMfc5AFFha7dabzP/uiPpb/c
27
+ GSvomC9IzyN37+eWwOS16cC+5XnBT6KRCaXYg2Fh6WpTgde67OVgXr4Q58HXlaZ+
28
+ /2BB3wq9lZ4JskvlpYpYnlPAUyiyc6R2Mjts1pURz5nkW4SuS7Kd1KCOOyr1McDH
29
+ VP12sTSjJclmI17BjDGQpAF0n9v5ExhJxWpeOjeBUPQsOin3ypEM1KkckLmOKvH6
30
+ zyKMYVRO0z/58g==
31
+ -----END CERTIFICATE-----
11
32
 
12
- date: 2010-01-11 00:00:00 -08:00
33
+ date: 2010-02-18 00:00:00 -08:00
13
34
  default_executable:
14
35
  dependencies:
15
36
  - !ruby/object:Gem::Dependency
@@ -31,18 +52,37 @@ extensions: []
31
52
  extra_rdoc_files:
32
53
  - CHANGELOG
33
54
  - LICENSE
34
- - README
55
+ - README.rdoc
35
56
  - lib/thrift_client.rb
57
+ - lib/thrift_client/connection.rb
58
+ - lib/thrift_client/connection/base.rb
59
+ - lib/thrift_client/connection/factory.rb
60
+ - lib/thrift_client/connection/http.rb
61
+ - lib/thrift_client/connection/socket.rb
62
+ - lib/thrift_client/event_machine.rb
63
+ - lib/thrift_client/simple.rb
36
64
  - lib/thrift_client/thrift.rb
37
65
  files:
38
66
  - CHANGELOG
39
67
  - LICENSE
40
68
  - Manifest
41
- - README
69
+ - README.rdoc
42
70
  - Rakefile
43
71
  - lib/thrift_client.rb
72
+ - lib/thrift_client/connection.rb
73
+ - lib/thrift_client/connection/base.rb
74
+ - lib/thrift_client/connection/factory.rb
75
+ - lib/thrift_client/connection/http.rb
76
+ - lib/thrift_client/connection/socket.rb
77
+ - lib/thrift_client/event_machine.rb
78
+ - lib/thrift_client/simple.rb
44
79
  - lib/thrift_client/thrift.rb
80
+ - test/greeter/greeter.rb
81
+ - test/greeter/greeter.thrift
82
+ - test/greeter/server.rb
83
+ - test/simple_test.rb
45
84
  - test/test_helper.rb
85
+ - test/thrift_client_http_test.rb
46
86
  - test/thrift_client_test.rb
47
87
  - thrift_client.gemspec
48
88
  has_rdoc: true
@@ -56,7 +96,7 @@ rdoc_options:
56
96
  - --title
57
97
  - Thrift_client
58
98
  - --main
59
- - README
99
+ - README.rdoc
60
100
  require_paths:
61
101
  - lib
62
102
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -81,4 +121,5 @@ summary: A Thrift client wrapper that encapsulates some common failover behavior
81
121
  test_files:
82
122
  - test/simple_test.rb
83
123
  - test/test_helper.rb
124
+ - test/thrift_client_http_test.rb
84
125
  - test/thrift_client_test.rb
metadata.gz.sig ADDED
@@ -0,0 +1,3 @@
1
+ w�
2
+ � ����_e�@j ~C�q�Kv�)� y k�4����1հ��o�M�_��3,^�&ȯ0i��-ħ�Ve�`�D�x5&��
3
+ 9b�KŮ��c4�uX�Z�m{��U��:'�ٟG�֔�%9�D��0�u���-v�Ma��ֹ��͗"n����t�pN�1֊�2�3�E�\u����֕�ʹ��Q�<I�Ky��}{A�