thrift_client 0.4.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +2 -0
- data/Manifest +3 -0
- data/README.rdoc +1 -1
- data/lib/thrift_client/abstract_thrift_client.rb +212 -0
- data/lib/thrift_client/connection/base.rb +2 -3
- data/lib/thrift_client/connection/factory.rb +3 -3
- data/lib/thrift_client/connection/socket.rb +1 -1
- data/lib/thrift_client/event_machine.rb +13 -9
- data/lib/thrift_client.rb +8 -121
- data/test/multiple_working_servers_test.rb +112 -0
- data/test/thrift_client_test.rb +21 -3
- data/thrift_client.gemspec +6 -8
- metadata +24 -31
- data.tar.gz.sig +0 -0
- metadata.gz.sig +0 -3
data/CHANGELOG
CHANGED
data/Manifest
CHANGED
@@ -4,6 +4,7 @@ Manifest
|
|
4
4
|
README.rdoc
|
5
5
|
Rakefile
|
6
6
|
lib/thrift_client.rb
|
7
|
+
lib/thrift_client/abstract_thrift_client.rb
|
7
8
|
lib/thrift_client/connection.rb
|
8
9
|
lib/thrift_client/connection/base.rb
|
9
10
|
lib/thrift_client/connection/factory.rb
|
@@ -15,7 +16,9 @@ lib/thrift_client/thrift.rb
|
|
15
16
|
test/greeter/greeter.rb
|
16
17
|
test/greeter/greeter.thrift
|
17
18
|
test/greeter/server.rb
|
19
|
+
test/multiple_working_servers_test.rb
|
18
20
|
test/simple_test.rb
|
19
21
|
test/test_helper.rb
|
20
22
|
test/thrift_client_http_test.rb
|
21
23
|
test/thrift_client_test.rb
|
24
|
+
thrift_client.gemspec
|
data/README.rdoc
CHANGED
@@ -7,7 +7,7 @@ A Thrift client wrapper that encapsulates some common failover behavior.
|
|
7
7
|
|
8
8
|
Copyright 2009 Twitter, Inc. See included LICENSE file.
|
9
9
|
|
10
|
-
The public certificate for this gem is here[http://
|
10
|
+
The public certificate for this gem is here[http://blog.evanweaver.com/files/evan_weaver-original-public_cert.pem].
|
11
11
|
|
12
12
|
== Features
|
13
13
|
|
@@ -0,0 +1,212 @@
|
|
1
|
+
class AbstractThriftClient
|
2
|
+
|
3
|
+
DEFAULTS = {
|
4
|
+
:protocol => Thrift::BinaryProtocol,
|
5
|
+
:protocol_extra_params => [],
|
6
|
+
:transport => Thrift::Socket,
|
7
|
+
:transport_wrapper => Thrift::FramedTransport,
|
8
|
+
:raise => true,
|
9
|
+
:defaults => {}
|
10
|
+
}.freeze
|
11
|
+
|
12
|
+
attr_reader :client, :client_class, :current_server, :server_list, :options, :client_methods
|
13
|
+
|
14
|
+
def initialize(client_class, servers, options = {})
|
15
|
+
@options = DEFAULTS.merge(options)
|
16
|
+
@client_class = client_class
|
17
|
+
@server_list = Array(servers)
|
18
|
+
@current_server = @server_list.first
|
19
|
+
|
20
|
+
@client_methods = []
|
21
|
+
@client_class.instance_methods.each do |method_name|
|
22
|
+
if method_name =~ /^recv_(.*)$/
|
23
|
+
instance_eval("def #{$1}(*args); handled_proxy(:'#{$1}', *args); end", __FILE__, __LINE__)
|
24
|
+
@client_methods << $1
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Force the client to connect to the server. Not necessary to be
|
30
|
+
# called as the connection will be made on the first RPC method
|
31
|
+
# call.
|
32
|
+
def connect!
|
33
|
+
@connection = Connection::Factory.create(@options[:transport], @options[:transport_wrapper], @current_server, @options[:timeout])
|
34
|
+
@connection.connect!
|
35
|
+
@client = @client_class.new(@options[:protocol].new(@connection.transport, *@options[:protocol_extra_params]))
|
36
|
+
rescue Thrift::TransportException, Errno::ECONNREFUSED => e
|
37
|
+
@transport.close rescue nil
|
38
|
+
raise e
|
39
|
+
end
|
40
|
+
|
41
|
+
def disconnect!
|
42
|
+
@connection.close rescue nil
|
43
|
+
@client = nil
|
44
|
+
@current_server = nil
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
def handled_proxy(method_name, *args)
|
49
|
+
proxy(method_name, *args)
|
50
|
+
rescue Exception => e
|
51
|
+
handle_exception(e, method_name, args)
|
52
|
+
end
|
53
|
+
|
54
|
+
def proxy(method_name, *args)
|
55
|
+
connect! unless @client
|
56
|
+
send_rpc(method_name, *args)
|
57
|
+
end
|
58
|
+
|
59
|
+
def send_rpc(method_name, *args)
|
60
|
+
@client.send(method_name, *args)
|
61
|
+
end
|
62
|
+
|
63
|
+
def disconnect_on_error!
|
64
|
+
@connection.close rescue nil
|
65
|
+
@client = nil
|
66
|
+
@current_server = nil
|
67
|
+
end
|
68
|
+
|
69
|
+
def handle_exception(e, method_name, args=nil)
|
70
|
+
raise e if @options[:raise]
|
71
|
+
@options[:defaults][method_name.to_sym]
|
72
|
+
end
|
73
|
+
|
74
|
+
module RetryingThriftClient
|
75
|
+
DISCONNECT_ERRORS = [
|
76
|
+
IOError,
|
77
|
+
Thrift::Exception,
|
78
|
+
Thrift::ProtocolException,
|
79
|
+
Thrift::ApplicationException,
|
80
|
+
Thrift::TransportException
|
81
|
+
].freeze
|
82
|
+
|
83
|
+
RETRYING_DEFAULTS = {
|
84
|
+
:exception_classes => DISCONNECT_ERRORS,
|
85
|
+
:randomize_server_list => true,
|
86
|
+
:retries => nil,
|
87
|
+
:server_retry_period => 1,
|
88
|
+
:server_max_requests => nil
|
89
|
+
}.freeze
|
90
|
+
|
91
|
+
def initialize(client_class, servers, options = {})
|
92
|
+
super
|
93
|
+
@options = RETRYING_DEFAULTS.merge(@options)
|
94
|
+
@retries = options[:retries] || @server_list.size
|
95
|
+
@request_count = 0
|
96
|
+
@max_requests = @options[:server_max_requests]
|
97
|
+
@retry_period = @options[:server_retry_period]
|
98
|
+
rebuild_live_server_list!
|
99
|
+
end
|
100
|
+
|
101
|
+
def connect!
|
102
|
+
@current_server = next_server
|
103
|
+
super
|
104
|
+
rescue Thrift::TransportException, Errno::ECONNREFUSED
|
105
|
+
retry
|
106
|
+
end
|
107
|
+
|
108
|
+
def disconnect!
|
109
|
+
# Keep live servers in the list if we have a retry period. Otherwise,
|
110
|
+
# always eject, because we will always re-add them.
|
111
|
+
if @retry_period && @current_server
|
112
|
+
@live_server_list.unshift(@current_server)
|
113
|
+
end
|
114
|
+
|
115
|
+
super()
|
116
|
+
@request_count = 0
|
117
|
+
end
|
118
|
+
|
119
|
+
private
|
120
|
+
|
121
|
+
def next_server
|
122
|
+
if @retry_period
|
123
|
+
rebuild_live_server_list! if Time.now > @last_rebuild + @retry_period
|
124
|
+
raise ThriftClient::NoServersAvailable, "No live servers in #{@server_list.inspect} since #{@last_rebuild.inspect}." if @live_server_list.empty?
|
125
|
+
elsif @live_server_list.empty?
|
126
|
+
rebuild_live_server_list!
|
127
|
+
end
|
128
|
+
@live_server_list.pop
|
129
|
+
end
|
130
|
+
|
131
|
+
def rebuild_live_server_list!
|
132
|
+
@last_rebuild = Time.now
|
133
|
+
if @options[:randomize_server_list]
|
134
|
+
@live_server_list = @server_list.sort_by { rand }
|
135
|
+
else
|
136
|
+
@live_server_list = @server_list.dup
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def handled_proxy(method_name, *args)
|
141
|
+
disconnect_on_max! if @max_requests and @request_count >= @max_requests
|
142
|
+
super
|
143
|
+
end
|
144
|
+
|
145
|
+
def proxy(method_name, *args)
|
146
|
+
super
|
147
|
+
rescue *@options[:exception_classes] => e
|
148
|
+
disconnect_on_error!
|
149
|
+
tries ||= @retries
|
150
|
+
tries -= 1
|
151
|
+
tries == 0 ? handle_exception(e, method_name, args) : retry
|
152
|
+
end
|
153
|
+
|
154
|
+
def send_rpc(method_name, *args)
|
155
|
+
@request_count += 1
|
156
|
+
super
|
157
|
+
end
|
158
|
+
|
159
|
+
def disconnect_on_max!
|
160
|
+
@live_server_list.push(@current_server)
|
161
|
+
disconnect_on_error!
|
162
|
+
end
|
163
|
+
|
164
|
+
def disconnect_on_error!
|
165
|
+
super
|
166
|
+
@request_count = 0
|
167
|
+
end
|
168
|
+
|
169
|
+
end
|
170
|
+
|
171
|
+
module TimingOutThriftClient
|
172
|
+
TIMINGOUT_DEFAULTS = {
|
173
|
+
:timeout => 1,
|
174
|
+
:timeout_overrides => {}
|
175
|
+
}.freeze
|
176
|
+
|
177
|
+
def initialize(client_class, servers, options = {})
|
178
|
+
super
|
179
|
+
@options = TIMINGOUT_DEFAULTS.merge(@options)
|
180
|
+
end
|
181
|
+
|
182
|
+
def connect!
|
183
|
+
super
|
184
|
+
set_method_timeouts!
|
185
|
+
end
|
186
|
+
|
187
|
+
private
|
188
|
+
def set_method_timeouts!
|
189
|
+
return unless has_timeouts?
|
190
|
+
@client_methods.each do |method_name|
|
191
|
+
@client.timeout = @options[:timeout_overrides][method_name.to_sym] || @options[:timeout]
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def has_timeouts?
|
196
|
+
@has_timeouts ||= has_timeouts!
|
197
|
+
end
|
198
|
+
|
199
|
+
def has_timeouts!
|
200
|
+
@options[:timeout_overrides].any? && transport_can_timeout?
|
201
|
+
end
|
202
|
+
|
203
|
+
def transport_can_timeout?
|
204
|
+
if (@options[:transport_wrapper] || @options[:transport]).method_defined?(:timeout=)
|
205
|
+
true
|
206
|
+
else
|
207
|
+
warn "ThriftClient: Timeout overrides have no effect with with transport type #{(@options[:transport_wrapper] || @options[:transport])}"
|
208
|
+
false
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
@@ -2,12 +2,11 @@ module Connection
|
|
2
2
|
class Base
|
3
3
|
attr_accessor :transport, :server
|
4
4
|
|
5
|
-
def initialize(transport, transport_wrapper, server, timeout
|
5
|
+
def initialize(transport, transport_wrapper, server, timeout)
|
6
6
|
@transport = transport
|
7
7
|
@transport_wrapper = transport_wrapper
|
8
8
|
@server = server
|
9
9
|
@timeout = timeout
|
10
|
-
@error_type = error_hash[:handles_error]
|
11
10
|
end
|
12
11
|
|
13
12
|
def connect!
|
@@ -17,4 +16,4 @@ module Connection
|
|
17
16
|
def close
|
18
17
|
end
|
19
18
|
end
|
20
|
-
end
|
19
|
+
end
|
@@ -2,10 +2,10 @@ module Connection
|
|
2
2
|
class Factory
|
3
3
|
def self.create(transport, transport_wrapper, server, timeout)
|
4
4
|
if transport == Thrift::HTTPClientTransport
|
5
|
-
Connection::HTTP.new(transport, transport_wrapper, server, timeout
|
5
|
+
Connection::HTTP.new(transport, transport_wrapper, server, timeout)
|
6
6
|
else
|
7
|
-
Connection::Socket.new(transport, transport_wrapper, server, timeout
|
7
|
+
Connection::Socket.new(transport, transport_wrapper, server, timeout)
|
8
8
|
end
|
9
9
|
end
|
10
10
|
end
|
11
|
-
end
|
11
|
+
end
|
@@ -17,7 +17,16 @@ module Thrift
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def open
|
20
|
+
fiber = Fiber.current
|
20
21
|
@connection = EventMachineConnection.connect(@host, @port, @timeout)
|
22
|
+
@connection.callback do
|
23
|
+
fiber.resume
|
24
|
+
end
|
25
|
+
@connection.errback do
|
26
|
+
fiber.resume
|
27
|
+
end
|
28
|
+
Fiber.yield
|
29
|
+
@connection
|
21
30
|
end
|
22
31
|
|
23
32
|
def close
|
@@ -56,7 +65,6 @@ module Thrift
|
|
56
65
|
def initialize(host, port=9090)
|
57
66
|
@host, @port = host, port
|
58
67
|
@index = 0
|
59
|
-
@reconnecting = false
|
60
68
|
@connected = false
|
61
69
|
@buf = ''
|
62
70
|
end
|
@@ -69,6 +77,7 @@ module Thrift
|
|
69
77
|
end
|
70
78
|
|
71
79
|
def blocking_read(size)
|
80
|
+
raise IOError, "lost connection to #{@host}:#{@port}" unless @connected
|
72
81
|
trap do
|
73
82
|
if can_read?(size)
|
74
83
|
yank(size)
|
@@ -103,20 +112,15 @@ module Thrift
|
|
103
112
|
end
|
104
113
|
|
105
114
|
def connection_completed
|
106
|
-
@reconnecting = false
|
107
115
|
@connected = true
|
108
116
|
succeed
|
109
117
|
end
|
110
118
|
|
111
119
|
def unbind
|
112
|
-
|
113
|
-
if @connected or !@reconnecting
|
114
|
-
EM.add_timer(1) {
|
115
|
-
# XXX Connect timeout?
|
116
|
-
reconnect @host, @port
|
117
|
-
}
|
120
|
+
if @connected
|
118
121
|
@connected = false
|
119
|
-
|
122
|
+
else
|
123
|
+
fail
|
120
124
|
end
|
121
125
|
end
|
122
126
|
|
data/lib/thrift_client.rb
CHANGED
@@ -10,34 +10,14 @@ end
|
|
10
10
|
require 'rubygems'
|
11
11
|
require 'thrift_client/thrift'
|
12
12
|
require 'thrift_client/connection'
|
13
|
+
require 'thrift_client/abstract_thrift_client'
|
13
14
|
|
14
|
-
class ThriftClient
|
15
|
-
|
15
|
+
class ThriftClient < AbstractThriftClient
|
16
|
+
# This error is for backwards compatibility only. If defined in
|
17
|
+
# RetryingThriftClient instead, causes the test suite will break.
|
16
18
|
class NoServersAvailable < StandardError; end
|
17
|
-
|
18
|
-
|
19
|
-
:protocol => Thrift::BinaryProtocol,
|
20
|
-
:protocol_extra_params => [],
|
21
|
-
:transport => Thrift::Socket,
|
22
|
-
:transport_wrapper => Thrift::FramedTransport,
|
23
|
-
:randomize_server_list => true,
|
24
|
-
:exception_classes => [
|
25
|
-
IOError,
|
26
|
-
Thrift::Exception,
|
27
|
-
Thrift::ProtocolException,
|
28
|
-
Thrift::ApplicationException,
|
29
|
-
Thrift::TransportException,
|
30
|
-
NoServersAvailable],
|
31
|
-
:raise => true,
|
32
|
-
:retries => nil,
|
33
|
-
:server_retry_period => 1,
|
34
|
-
:server_max_requests => nil,
|
35
|
-
:timeout => 1,
|
36
|
-
:timeout_overrides => {},
|
37
|
-
:defaults => {}
|
38
|
-
}.freeze
|
39
|
-
|
40
|
-
attr_reader :client, :client_class, :current_server, :server_list, :options
|
19
|
+
include RetryingThriftClient
|
20
|
+
include TimingOutThriftClient
|
41
21
|
|
42
22
|
=begin rdoc
|
43
23
|
Create a new ThriftClient instance. Accepts an internal Thrift client class (such as CassandraRb::Client), a list of servers with ports, and optional parameters.
|
@@ -48,6 +28,7 @@ Valid optional parameters are:
|
|
48
28
|
<tt>:protocol_extra_params</tt>:: An array of additional parameters to pass to the protocol initialization call. Defaults to <tt>[]</tt>.
|
49
29
|
<tt>:transport</tt>:: Which Thrift transport to use. Defaults to <tt>Thrift::FramedTransport</tt>.
|
50
30
|
<tt>:randomize_server_list</tt>:: Whether to connect to the servers randomly, instead of in order. Defaults to <tt>true</tt>.
|
31
|
+
<tt>:exception_classes</tt>:: Which exceptions to catch and retry when sending a request. Defaults to <tt>[IOError, Thrift::Exception, Thrift::ProtocolException, Thrift::ApplicationException, Thrift::TransportException, NoServersAvailable]</tt>
|
51
32
|
<tt>:raise</tt>:: Whether to reraise errors if no responsive servers are found. Defaults to <tt>true</tt>.
|
52
33
|
<tt>:retries</tt>:: How many times to retry a request. Defaults to the number of servers defined.
|
53
34
|
<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.
|
@@ -59,100 +40,6 @@ Valid optional parameters are:
|
|
59
40
|
=end rdoc
|
60
41
|
|
61
42
|
def initialize(client_class, servers, options = {})
|
62
|
-
|
63
|
-
@client_class = client_class
|
64
|
-
@server_list = Array(servers)
|
65
|
-
@retries = options[:retries] || @server_list.size
|
66
|
-
|
67
|
-
if @options[:timeout_overrides].any?
|
68
|
-
if (@options[:transport_wrapper] || @options[:transport]).method_defined?(:timeout=)
|
69
|
-
@set_timeout = true
|
70
|
-
else
|
71
|
-
warn "ThriftClient: Timeout overrides have no effect with with transport type #{(@options[:transport_wrapper] || @options[:transport])}"
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
@request_count = 0
|
76
|
-
@max_requests = @options[:server_max_requests]
|
77
|
-
@retry_period = @options[:server_retry_period]
|
78
|
-
rebuild_live_server_list!
|
79
|
-
|
80
|
-
@client_class.instance_methods.each do |method_name|
|
81
|
-
if method_name =~ /^recv_(.*)$/
|
82
|
-
instance_eval("def #{$1}(*args); proxy(:'#{$1}', *args); end")
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
# Force the client to connect to the server.
|
88
|
-
def connect!
|
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
|
94
|
-
@transport.close rescue nil
|
95
|
-
retry
|
96
|
-
end
|
97
|
-
|
98
|
-
# Force the client to disconnect from the server.
|
99
|
-
def disconnect!(keep = true)
|
100
|
-
@connection.close rescue nil
|
101
|
-
|
102
|
-
# Keep live servers in the list if we have a retry period. Otherwise,
|
103
|
-
# always eject, because we will always re-add them.
|
104
|
-
if keep and @retry_period and @current_server
|
105
|
-
@live_server_list.unshift(@current_server)
|
106
|
-
end
|
107
|
-
|
108
|
-
@request_count = 0
|
109
|
-
@client = nil
|
110
|
-
@current_server = nil
|
111
|
-
end
|
112
|
-
|
113
|
-
private
|
114
|
-
|
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
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
def proxy(method_name, *args)
|
135
|
-
disconnect! if @max_requests and @request_count >= @max_requests
|
136
|
-
connect! unless @client
|
137
|
-
|
138
|
-
set_timeout!(method_name) if @set_timeout
|
139
|
-
@request_count += 1
|
140
|
-
@client.send(method_name, *args)
|
141
|
-
rescue NoServersAvailable => e
|
142
|
-
handle_exception(e, method_name, args)
|
143
|
-
rescue *@options[:exception_classes] => e
|
144
|
-
disconnect!(false)
|
145
|
-
tries ||= @retries
|
146
|
-
tries -= 1
|
147
|
-
tries == 0 ? handle_exception(e, method_name, args) : retry
|
148
|
-
end
|
149
|
-
|
150
|
-
def set_timeout!(method_name)
|
151
|
-
@client.timeout = @options[:timeout_overrides][method_name.to_sym] || @options[:timeout]
|
152
|
-
end
|
153
|
-
|
154
|
-
def handle_exception(e, method_name, args=nil)
|
155
|
-
raise e if @options[:raise]
|
156
|
-
@options[:defaults][method_name.to_sym]
|
43
|
+
super
|
157
44
|
end
|
158
45
|
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/test_helper"
|
2
|
+
|
3
|
+
class MultipleWorkingServersTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@servers = ["127.0.0.1:1461", "127.0.0.1:1462", "127.0.0.1:1463"]
|
6
|
+
@socket = 1461
|
7
|
+
@timeout = 0.2
|
8
|
+
@options = {:protocol_extra_params => [false]}
|
9
|
+
@pids = []
|
10
|
+
@servers.each do |s|
|
11
|
+
@pids << Process.fork do
|
12
|
+
Signal.trap("INT") { exit }
|
13
|
+
Greeter::Server.new(s.split(':').last).serve
|
14
|
+
end
|
15
|
+
end
|
16
|
+
# Need to give the child process a moment to open the listening socket or
|
17
|
+
# we get occasional "could not connect" errors in tests.
|
18
|
+
sleep 0.05
|
19
|
+
end
|
20
|
+
|
21
|
+
def teardown
|
22
|
+
@pids.each do |pid|
|
23
|
+
Process.kill("INT", pid)
|
24
|
+
Process.wait(pid)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_server_creates_new_client_that_can_talk_to_all_servers_after_disconnect
|
29
|
+
client = ThriftClient.new(Greeter::Client, @servers, @options)
|
30
|
+
client.greeting("someone")
|
31
|
+
internal_client = client.client
|
32
|
+
client.greeting("someone")
|
33
|
+
assert_equal internal_client, client.client # Sanity check
|
34
|
+
|
35
|
+
client.disconnect!
|
36
|
+
client.greeting("someone")
|
37
|
+
internal_client = client.client
|
38
|
+
client.greeting("someone")
|
39
|
+
assert_equal internal_client, client.client
|
40
|
+
internal_client = client.client
|
41
|
+
client.greeting("someone")
|
42
|
+
assert_equal internal_client, client.client
|
43
|
+
|
44
|
+
# Moves on to the second server
|
45
|
+
assert_nothing_raised {
|
46
|
+
client.greeting("someone")
|
47
|
+
client.greeting("someone")
|
48
|
+
}
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_server_doesnt_max_out_after_explicit_disconnect
|
52
|
+
client = ThriftClient.new(Greeter::Client, @servers, @options.merge(:server_max_requests => 2))
|
53
|
+
client.greeting("someone")
|
54
|
+
internal_client = client.client
|
55
|
+
client.greeting("someone")
|
56
|
+
assert_equal internal_client, client.client # Sanity check
|
57
|
+
|
58
|
+
client.disconnect!
|
59
|
+
|
60
|
+
client.greeting("someone")
|
61
|
+
internal_client = client.client
|
62
|
+
client.greeting("someone")
|
63
|
+
assert_equal internal_client, client.client, "ThriftClient should not have reset the internal client if the counter was reset on disconnect"
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_server_disconnect_doesnt_drop_servers_with_retry_period
|
67
|
+
client = ThriftClient.new(Greeter::Client, @servers, @options.merge(:server_max_requests => 2, :retry_period => 1))
|
68
|
+
3.times {
|
69
|
+
client.greeting("someone")
|
70
|
+
internal_client = client.client
|
71
|
+
client.greeting("someone")
|
72
|
+
assert_equal internal_client, client.client # Sanity check
|
73
|
+
|
74
|
+
client.disconnect!
|
75
|
+
|
76
|
+
client.greeting("someone")
|
77
|
+
internal_client = client.client
|
78
|
+
client.greeting("someone")
|
79
|
+
assert_equal internal_client, client.client, "ThriftClient should not have reset the internal client if the counter was reset on disconnect"
|
80
|
+
}
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
def test_server_max_requests
|
85
|
+
client = ThriftClient.new(Greeter::Client, @servers, @options.merge(:server_max_requests => 2))
|
86
|
+
|
87
|
+
client.greeting("someone")
|
88
|
+
internal_client = client.client
|
89
|
+
|
90
|
+
client.greeting("someone")
|
91
|
+
assert_equal internal_client, client.client
|
92
|
+
|
93
|
+
# This next call maxes out the requests for that "client" object
|
94
|
+
# and moves on to the next.
|
95
|
+
client.greeting("someone")
|
96
|
+
assert_not_equal internal_client, new_client = client.client
|
97
|
+
|
98
|
+
# And here we should still have the same client as the last one...
|
99
|
+
client.greeting("someone")
|
100
|
+
assert_equal new_client, client.client
|
101
|
+
|
102
|
+
# Until we max it out, too.
|
103
|
+
client.greeting("someone")
|
104
|
+
assert_not_equal new_client, client.client
|
105
|
+
assert_not_nil client.client
|
106
|
+
|
107
|
+
new_new_client = client.client
|
108
|
+
# And we should still have one server left
|
109
|
+
client.greeting("someone")
|
110
|
+
assert_equal new_new_client, client.client
|
111
|
+
end
|
112
|
+
end
|
data/test/thrift_client_test.rb
CHANGED
@@ -121,13 +121,31 @@ class ThriftClientTest < Test::Unit::TestCase
|
|
121
121
|
assert_raises(ThriftClient::NoServersAvailable) { client.greeting("someone") }
|
122
122
|
end
|
123
123
|
|
124
|
-
def
|
124
|
+
def test_client_with_retry_period_drops_servers
|
125
|
+
client = ThriftClient.new(Greeter::Client, @servers[0,2], @options.merge(:server_retry_period => 1))
|
126
|
+
assert_raises(ThriftClient::NoServersAvailable) { client.greeting("someone") }
|
127
|
+
sleep 1.1
|
128
|
+
assert_raises(ThriftClient::NoServersAvailable) { client.greeting("someone") }
|
129
|
+
end
|
130
|
+
|
131
|
+
def test_server_max_requests_with_downed_servers
|
125
132
|
client = ThriftClient.new(Greeter::Client, @servers, @options.merge(:server_max_requests => 2))
|
126
133
|
client.greeting("someone")
|
127
134
|
internal_client = client.client
|
128
135
|
client.greeting("someone")
|
129
136
|
assert_equal internal_client, client.client
|
130
|
-
|
137
|
+
|
138
|
+
# This next call maxes out the requests for that "client" object
|
139
|
+
# and moves on to the next.
|
140
|
+
client.greeting("someone")
|
141
|
+
assert_not_equal internal_client, new_client = client.client
|
142
|
+
|
143
|
+
# And here we should still have the same client as the last one...
|
144
|
+
client.greeting("someone")
|
145
|
+
assert_equal new_client, client.client
|
146
|
+
|
147
|
+
# Until we max it out, too.
|
148
|
+
client.greeting("someone")
|
131
149
|
assert_not_equal internal_client, client.client
|
132
150
|
end
|
133
151
|
|
@@ -140,4 +158,4 @@ class ThriftClientTest < Test::Unit::TestCase
|
|
140
158
|
ensure
|
141
159
|
socket.close
|
142
160
|
end
|
143
|
-
end
|
161
|
+
end
|
data/thrift_client.gemspec
CHANGED
@@ -2,24 +2,22 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{thrift_client}
|
5
|
-
s.version = "0.4.
|
5
|
+
s.version = "0.4.1"
|
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.
|
10
|
-
s.date = %q{2010-02-18}
|
9
|
+
s.date = %q{2010-03-30}
|
11
10
|
s.description = %q{A Thrift client wrapper that encapsulates some common failover behavior.}
|
12
11
|
s.email = %q{}
|
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"]
|
12
|
+
s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README.rdoc", "lib/thrift_client.rb", "lib/thrift_client/abstract_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"]
|
13
|
+
s.files = ["CHANGELOG", "LICENSE", "Manifest", "README.rdoc", "Rakefile", "lib/thrift_client.rb", "lib/thrift_client/abstract_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/multiple_working_servers_test.rb", "test/simple_test.rb", "test/test_helper.rb", "test/thrift_client_http_test.rb", "test/thrift_client_test.rb", "thrift_client.gemspec"]
|
15
14
|
s.homepage = %q{http://blog.evanweaver.com/files/doc/fauna/thrift_client/}
|
16
15
|
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Thrift_client", "--main", "README.rdoc"]
|
17
16
|
s.require_paths = ["lib"]
|
18
17
|
s.rubyforge_project = %q{fauna}
|
19
|
-
s.rubygems_version = %q{1.3.
|
20
|
-
s.signing_key = %q{/Users/ryan/.gemkeys/gem-private_key.pem}
|
18
|
+
s.rubygems_version = %q{1.3.6}
|
21
19
|
s.summary = %q{A Thrift client wrapper that encapsulates some common failover behavior.}
|
22
|
-
s.test_files = ["test/simple_test.rb", "test/test_helper.rb", "test/thrift_client_http_test.rb", "test/thrift_client_test.rb"]
|
20
|
+
s.test_files = ["test/multiple_working_servers_test.rb", "test/simple_test.rb", "test/test_helper.rb", "test/thrift_client_http_test.rb", "test/thrift_client_test.rb"]
|
23
21
|
|
24
22
|
if s.respond_to? :specification_version then
|
25
23
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
metadata
CHANGED
@@ -1,48 +1,34 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: thrift_client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 4
|
8
|
+
- 1
|
9
|
+
version: 0.4.1
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- Evan Weaver
|
8
13
|
autorequire:
|
9
14
|
bindir: bin
|
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-----
|
15
|
+
cert_chain: []
|
32
16
|
|
33
|
-
date: 2010-
|
17
|
+
date: 2010-03-30 00:00:00 -07:00
|
34
18
|
default_executable:
|
35
19
|
dependencies:
|
36
20
|
- !ruby/object:Gem::Dependency
|
37
21
|
name: thrift
|
38
|
-
|
39
|
-
|
40
|
-
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
41
24
|
requirements:
|
42
25
|
- - ">="
|
43
26
|
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
44
29
|
version: "0"
|
45
|
-
|
30
|
+
type: :runtime
|
31
|
+
version_requirements: *id001
|
46
32
|
description: A Thrift client wrapper that encapsulates some common failover behavior.
|
47
33
|
email: ""
|
48
34
|
executables: []
|
@@ -54,6 +40,7 @@ extra_rdoc_files:
|
|
54
40
|
- LICENSE
|
55
41
|
- README.rdoc
|
56
42
|
- lib/thrift_client.rb
|
43
|
+
- lib/thrift_client/abstract_thrift_client.rb
|
57
44
|
- lib/thrift_client/connection.rb
|
58
45
|
- lib/thrift_client/connection/base.rb
|
59
46
|
- lib/thrift_client/connection/factory.rb
|
@@ -69,6 +56,7 @@ files:
|
|
69
56
|
- README.rdoc
|
70
57
|
- Rakefile
|
71
58
|
- lib/thrift_client.rb
|
59
|
+
- lib/thrift_client/abstract_thrift_client.rb
|
72
60
|
- lib/thrift_client/connection.rb
|
73
61
|
- lib/thrift_client/connection/base.rb
|
74
62
|
- lib/thrift_client/connection/factory.rb
|
@@ -80,6 +68,7 @@ files:
|
|
80
68
|
- test/greeter/greeter.rb
|
81
69
|
- test/greeter/greeter.thrift
|
82
70
|
- test/greeter/server.rb
|
71
|
+
- test/multiple_working_servers_test.rb
|
83
72
|
- test/simple_test.rb
|
84
73
|
- test/test_helper.rb
|
85
74
|
- test/thrift_client_http_test.rb
|
@@ -103,22 +92,26 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
103
92
|
requirements:
|
104
93
|
- - ">="
|
105
94
|
- !ruby/object:Gem::Version
|
95
|
+
segments:
|
96
|
+
- 0
|
106
97
|
version: "0"
|
107
|
-
version:
|
108
98
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
109
99
|
requirements:
|
110
100
|
- - ">="
|
111
101
|
- !ruby/object:Gem::Version
|
102
|
+
segments:
|
103
|
+
- 0
|
104
|
+
- 8
|
112
105
|
version: "0.8"
|
113
|
-
version:
|
114
106
|
requirements: []
|
115
107
|
|
116
108
|
rubyforge_project: fauna
|
117
|
-
rubygems_version: 1.3.
|
109
|
+
rubygems_version: 1.3.6
|
118
110
|
signing_key:
|
119
111
|
specification_version: 3
|
120
112
|
summary: A Thrift client wrapper that encapsulates some common failover behavior.
|
121
113
|
test_files:
|
114
|
+
- test/multiple_working_servers_test.rb
|
122
115
|
- test/simple_test.rb
|
123
116
|
- test/test_helper.rb
|
124
117
|
- test/thrift_client_http_test.rb
|
data.tar.gz.sig
DELETED
Binary file
|
metadata.gz.sig
DELETED