thrift_client 0.3 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data.tar.gz.sig +0 -0
- data/CHANGELOG +2 -0
- data/lib/thrift_client.rb +44 -19
- data/test/thrift_client_test.rb +23 -19
- data/thrift_client.gemspec +1 -1
- metadata +1 -1
- metadata.gz.sig +0 -0
data.tar.gz.sig
CHANGED
Binary file
|
data/CHANGELOG
CHANGED
data/lib/thrift_client.rb
CHANGED
@@ -30,12 +30,13 @@ class ThriftClient
|
|
30
30
|
:raise => true,
|
31
31
|
:retries => nil,
|
32
32
|
:server_retry_period => 1,
|
33
|
+
:server_max_requests => nil,
|
33
34
|
:timeout => 1,
|
34
35
|
:timeout_overrides => {},
|
35
36
|
:defaults => {}
|
36
37
|
}.freeze
|
37
38
|
|
38
|
-
attr_reader :client, :client_class, :server_list, :options
|
39
|
+
attr_reader :client, :client_class, :current_server, :server_list, :options
|
39
40
|
|
40
41
|
=begin rdoc
|
41
42
|
Create a new ThriftClient instance. Accepts an internal Thrift client class (such as CassandraRb::Client), a list of servers with ports, and optional parameters.
|
@@ -49,8 +50,9 @@ Valid optional parameters are:
|
|
49
50
|
<tt>:raise</tt>:: Whether to reraise errors if no responsive servers are found. Defaults to <tt>true</tt>.
|
50
51
|
<tt>:retries</tt>:: How many times to retry a request. Defaults to the number of servers defined.
|
51
52
|
<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.
|
52
|
-
<tt>:
|
53
|
-
<tt>:
|
53
|
+
<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).
|
54
|
+
<tt>:timeout</tt>:: Specify the default timeout in seconds. Defaults to <tt>1</tt>.
|
55
|
+
<tt>:timeout_overrides</tt>:: Specify additional timeouts on a per-method basis, in seconds. Only works with <tt>Thrift::BufferedTransport</tt>.
|
54
56
|
<tt>:defaults</tt>:: Specify default values to return on a per-method basis, if <tt>:raise</tt> is set to false.
|
55
57
|
|
56
58
|
=end rdoc
|
@@ -60,7 +62,6 @@ Valid optional parameters are:
|
|
60
62
|
@client_class = client_class
|
61
63
|
@server_list = Array(servers)
|
62
64
|
@retries = options[:retries] || @server_list.size
|
63
|
-
@server_list = @server_list.sort_by { rand } if @options[:randomize_server_list]
|
64
65
|
|
65
66
|
if @options[:timeout_overrides].any?
|
66
67
|
if @options[:transport].instance_methods.include?("timeout=")
|
@@ -69,9 +70,11 @@ Valid optional parameters are:
|
|
69
70
|
warn "ThriftClient: Timeout overrides have no effect with with transport type #{@options[:transport]}"
|
70
71
|
end
|
71
72
|
end
|
72
|
-
|
73
|
-
@
|
74
|
-
@
|
73
|
+
|
74
|
+
@request_count = 0
|
75
|
+
@max_requests = @options[:server_max_requests]
|
76
|
+
@retry_period = @options[:server_retry_period]
|
77
|
+
rebuild_live_server_list!
|
75
78
|
|
76
79
|
@client_class.instance_methods.each do |method_name|
|
77
80
|
if method_name =~ /^recv_(.*)$/
|
@@ -82,37 +85,51 @@ Valid optional parameters are:
|
|
82
85
|
|
83
86
|
# Force the client to connect to the server.
|
84
87
|
def connect!
|
85
|
-
server = next_server
|
86
|
-
|
88
|
+
server = next_server
|
89
|
+
host, port = server.to_s.split(":")
|
90
|
+
raise ArgumentError, 'Servers must be in the form "host:port"' unless host and port
|
87
91
|
|
88
92
|
@transport = @options[:transport].new(
|
89
|
-
Thrift::Socket.new(
|
93
|
+
Thrift::Socket.new(host, port.to_i, @options[:timeout]))
|
90
94
|
@transport.open
|
95
|
+
@current_server = server
|
91
96
|
@client = @client_class.new(@options[:protocol].new(@transport, *@options[:protocol_extra_params]))
|
92
97
|
rescue Thrift::TransportException
|
93
98
|
retry
|
94
99
|
end
|
95
100
|
|
96
101
|
# Force the client to disconnect from the server.
|
97
|
-
def disconnect!
|
102
|
+
def disconnect!(keep = true)
|
98
103
|
@transport.close rescue nil
|
104
|
+
|
105
|
+
# Keep live servers in the list if we have a retry period. Otherwise,
|
106
|
+
# always eject, because we will always re-add them.
|
107
|
+
if keep and @retry_period and @current_server
|
108
|
+
@live_server_list.unshift(@current_server)
|
109
|
+
end
|
110
|
+
|
111
|
+
@request_count = 0
|
99
112
|
@client = nil
|
113
|
+
@current_server = nil
|
100
114
|
end
|
101
115
|
|
102
116
|
private
|
103
117
|
|
104
118
|
def proxy(method_name, *args)
|
119
|
+
disconnect! if @max_requests and @request_count >= @max_requests
|
105
120
|
connect! unless @client
|
121
|
+
|
106
122
|
set_timeout!(method_name) if @set_timeout
|
123
|
+
@request_count += 1
|
107
124
|
@client.send(method_name, *args)
|
108
125
|
rescue NoServersAvailable => e
|
109
126
|
handle_exception(e, method_name, args)
|
110
127
|
rescue *@options[:exception_classes] => e
|
111
|
-
tries ||= @retries
|
128
|
+
tries ||= @retries
|
112
129
|
if (tries -= 1) == 0
|
113
130
|
handle_exception(e, method_name, args)
|
114
131
|
else
|
115
|
-
disconnect!
|
132
|
+
disconnect!(false)
|
116
133
|
retry
|
117
134
|
end
|
118
135
|
end
|
@@ -127,13 +144,21 @@ Valid optional parameters are:
|
|
127
144
|
end
|
128
145
|
|
129
146
|
def next_server
|
130
|
-
if @
|
131
|
-
if
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
@live_server_list = @server_list.dup
|
147
|
+
if @retry_period
|
148
|
+
rebuild_live_server_list! if Time.now > @last_rebuild + @retry_period
|
149
|
+
raise NoServersAvailable, "No live servers in #{@server_list.inspect} since #{@last_rebuild.inspect}." if @live_server_list.empty?
|
150
|
+
elsif @live_server_list.empty?
|
151
|
+
rebuild_live_server_list!
|
136
152
|
end
|
137
153
|
@live_server_list.pop
|
138
154
|
end
|
155
|
+
|
156
|
+
def rebuild_live_server_list!
|
157
|
+
@last_rebuild = Time.now
|
158
|
+
if @options[:randomize_server_list]
|
159
|
+
@live_server_list = @server_list.sort_by { rand }
|
160
|
+
else
|
161
|
+
@live_server_list = @server_list.dup
|
162
|
+
end
|
163
|
+
end
|
139
164
|
end
|
data/test/thrift_client_test.rb
CHANGED
@@ -26,23 +26,17 @@ class ThriftClientTest < Test::Unit::TestCase
|
|
26
26
|
ThriftClient.new(ScribeThrift::Client, @servers.first, @options.merge(:raise => false)).Log(@entry)
|
27
27
|
end
|
28
28
|
end
|
29
|
-
|
29
|
+
|
30
30
|
def test_dont_raise_with_defaults
|
31
31
|
client = ThriftClient.new(ScribeThrift::Client, @servers.first, @options.merge(:raise => false, :defaults => {:Log => 1}))
|
32
32
|
assert_equal 1, client.Log(@entry)
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
def test_defaults_dont_override_no_method_error
|
36
36
|
client = ThriftClient.new(ScribeThrift::Client, @servers, @options.merge(:raise => false, :defaults => {:Missing => 2}))
|
37
|
-
assert_raises(NoMethodError) { client.Missing(@entry) }
|
37
|
+
assert_raises(NoMethodError) { client.Missing(@entry) }
|
38
38
|
end
|
39
39
|
|
40
|
-
def test_random_server_list
|
41
|
-
@lists = []
|
42
|
-
@lists << ThriftClient.new(ScribeThrift::Client, @servers, @options).server_list while @lists.size < 10
|
43
|
-
assert @lists.uniq.size > 1
|
44
|
-
end
|
45
|
-
|
46
40
|
def test_random_fall_through
|
47
41
|
assert_nothing_raised do
|
48
42
|
10.times { ThriftClient.new(ScribeThrift::Client, @servers, @options).Log(@entry) }
|
@@ -62,35 +56,35 @@ class ThriftClientTest < Test::Unit::TestCase
|
|
62
56
|
client.disconnect!
|
63
57
|
end
|
64
58
|
end
|
65
|
-
|
59
|
+
|
66
60
|
def test_framed_transport_timeout
|
67
61
|
stub_server(@socket) do |socket|
|
68
62
|
measurement = Benchmark.measure do
|
69
63
|
assert_raises(Thrift::TransportException) do
|
70
|
-
ThriftClient.new(ScribeThrift::Client, "127.0.0.1:#{@socket}",
|
64
|
+
ThriftClient.new(ScribeThrift::Client, "127.0.0.1:#{@socket}",
|
71
65
|
@options.merge(:timeout => @timeout)
|
72
|
-
).Log(@entry)
|
66
|
+
).Log(@entry)
|
73
67
|
end
|
74
68
|
end
|
75
69
|
assert((measurement.real > @timeout - 0.01), "#{measurement.real} < #{@timeout}")
|
76
70
|
assert((measurement.real < @timeout + 0.01), "#{measurement.real} > #{@timeout}")
|
77
71
|
end
|
78
72
|
end
|
79
|
-
|
73
|
+
|
80
74
|
def test_buffered_transport_timeout
|
81
75
|
stub_server(@socket) do |socket|
|
82
76
|
measurement = Benchmark.measure do
|
83
77
|
assert_raises(Thrift::TransportException) do
|
84
78
|
ThriftClient.new(ScribeThrift::Client, "127.0.0.1:#{@socket}",
|
85
79
|
@options.merge(:timeout => @timeout, :transport => Thrift::BufferedTransport)
|
86
|
-
).Log(@entry)
|
80
|
+
).Log(@entry)
|
87
81
|
end
|
88
82
|
end
|
89
83
|
assert((measurement.real > @timeout - 0.01), "#{measurement.real} < #{@timeout}")
|
90
84
|
assert((measurement.real < @timeout + 0.01), "#{measurement.real} > #{@timeout}")
|
91
85
|
end
|
92
|
-
end
|
93
|
-
|
86
|
+
end
|
87
|
+
|
94
88
|
def test_buffered_transport_timeout_override
|
95
89
|
# FIXME Large timeout values always are applied twice for some bizarre reason
|
96
90
|
log_timeout = @timeout * 4
|
@@ -99,7 +93,7 @@ class ThriftClientTest < Test::Unit::TestCase
|
|
99
93
|
assert_raises(Thrift::TransportException) do
|
100
94
|
ThriftClient.new(ScribeThrift::Client, "127.0.0.1:#{@socket}",
|
101
95
|
@options.merge(:timeout => @timeout, :timeout_overrides => {:Log => log_timeout}, :transport => Thrift::BufferedTransport)
|
102
|
-
).Log(@entry)
|
96
|
+
).Log(@entry)
|
103
97
|
end
|
104
98
|
end
|
105
99
|
assert((measurement.real > log_timeout - 0.01), "#{measurement.real} < #{log_timeout }")
|
@@ -114,13 +108,23 @@ class ThriftClientTest < Test::Unit::TestCase
|
|
114
108
|
assert_raises(ThriftClient::NoServersAvailable) { client.Log(@entry) }
|
115
109
|
end
|
116
110
|
|
111
|
+
def test_server_max_requests
|
112
|
+
client = ThriftClient.new(ScribeThrift::Client, @servers, @options.merge(:server_max_requests => 2))
|
113
|
+
client.Log(@entry)
|
114
|
+
internal_client = client.client
|
115
|
+
client.Log(@entry)
|
116
|
+
assert_equal internal_client, client.client
|
117
|
+
client.Log(@entry)
|
118
|
+
assert_not_equal internal_client, client.client
|
119
|
+
end
|
120
|
+
|
117
121
|
private
|
118
|
-
|
122
|
+
|
119
123
|
def stub_server(port)
|
120
124
|
socket = TCPServer.new('127.0.0.1', port)
|
121
125
|
Thread.new { socket.accept }
|
122
126
|
yield socket
|
123
127
|
ensure
|
124
128
|
socket.close
|
125
|
-
end
|
129
|
+
end
|
126
130
|
end
|
data/thrift_client.gemspec
CHANGED
metadata
CHANGED
metadata.gz.sig
CHANGED
Binary file
|