net_tcp_client 1.0.2 → 2.0.0
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.
- checksums.yaml +4 -4
- data/README.md +237 -41
- data/lib/net/tcp_client.rb +18 -2
- data/lib/net/tcp_client/address.rb +53 -0
- data/lib/net/tcp_client/exceptions.rb +5 -3
- data/lib/net/tcp_client/policy/base.rb +36 -0
- data/lib/net/tcp_client/policy/custom.rb +39 -0
- data/lib/net/tcp_client/policy/ordered.rb +14 -0
- data/lib/net/tcp_client/policy/random.rb +14 -0
- data/lib/net/tcp_client/tcp_client.rb +332 -209
- data/lib/net/tcp_client/version.rb +1 -1
- data/test/address_test.rb +91 -0
- data/test/policy/custom_policy_test.rb +42 -0
- data/test/policy/ordered_policy_test.rb +36 -0
- data/test/policy/random_policy_test.rb +46 -0
- data/test/simple_tcp_server.rb +36 -9
- data/test/ssl_files/ca.pem +19 -0
- data/test/ssl_files/localhost-server-key.pem +27 -0
- data/test/ssl_files/localhost-server.pem +18 -0
- data/test/tcp_client_test.rb +207 -143
- data/test/test_helper.rb +1 -2
- metadata +23 -5
- data/lib/net/tcp_client/logging.rb +0 -193
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9d6906da5ebe4657343ec1175664ee2f42b359eb
|
|
4
|
+
data.tar.gz: c816880d83f7d557390b00cbdfb5ed7c6a308512
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5d1aafb91baf376f68f291d5d18bc9d5569522cc2b093baf337f525b8060d3e632f6799ee64d8da12fc4db533f01a29059ec63144403da29e0f9884cd0f1a623
|
|
7
|
+
data.tar.gz: 32605f07229206ee29216ccfb5a2ecc74fe9c8c6d32459b7ec973fcd31f4541ab4ca710f148e6804254838265af364737449265908407f227100a96b761950af
|
data/README.md
CHANGED
|
@@ -1,43 +1,184 @@
|
|
|
1
1
|
# net_tcp_client
|
|
2
|
-
 ](https://rubygems.org/gems/net_tcp_client) [](https://travis-ci.org/rocketjob/net_tcp_client) [](https://rubygems.org/gems/net_tcp_client) [](http://opensource.org/licenses/Apache-2.0)  [-Support-brightgreen.svg)](https://gitter.im/rocketjob/support)
|
|
3
3
|
|
|
4
|
-
Net::TCPClient is a TCP Socket Client with
|
|
4
|
+
Net::TCPClient is a TCP Socket Client with automated failover, load balancing, retries and built-in timeouts.
|
|
5
5
|
|
|
6
6
|
* http://github.com/rocketjob/net_tcp_client
|
|
7
7
|
|
|
8
8
|
## Introduction
|
|
9
9
|
|
|
10
|
-
Net::TCPClient implements resilience features that many developers wish was
|
|
10
|
+
Net::TCPClient implements high availability and resilience features that many developers wish was
|
|
11
11
|
already included in the standard Ruby libraries.
|
|
12
12
|
|
|
13
|
-
With so many "client" libraries to servers such us memcache, MongoDB, Redis, etc.
|
|
14
|
-
their focus is on the communication formats and messaging interactions. As a result
|
|
15
|
-
adding resilience is usually an after thought.
|
|
16
|
-
|
|
17
|
-
More importantly the way that each client implements connection failure handling
|
|
18
|
-
varies dramatically. The purpose of this library is to extract the best
|
|
19
|
-
of all the socket error handling out there and create a consistent way of dealing
|
|
20
|
-
with connection failures.
|
|
21
|
-
|
|
22
13
|
Another important feature is that the _connect_ and _read_ API's use timeout's to
|
|
23
14
|
prevent a network issue from "hanging" the client program.
|
|
24
15
|
|
|
25
|
-
##
|
|
16
|
+
## Features
|
|
17
|
+
|
|
18
|
+
* Automated failover to another server.
|
|
19
|
+
* Load balancing across multiple servers.
|
|
20
|
+
* SSL and non-ssl connections.
|
|
21
|
+
* Connect Timeout.
|
|
22
|
+
* Read Timeout.
|
|
23
|
+
* Write Timeout.
|
|
24
|
+
* Fails over / load balances across all servers under a single DNS entry.
|
|
25
|
+
* Logging.
|
|
26
|
+
* Optional trace level logging of all data sent or received.
|
|
27
|
+
* Uses non blocking timeouts, instead of using threads such as used by the Timeout class.
|
|
28
|
+
* Additional exceptions to distinguish between connection failures and timeouts.
|
|
29
|
+
* Handshake callbacks.
|
|
30
|
+
* After a new connection has been established callbacks can be used
|
|
31
|
+
for handshakes such as authentication before data is sent.
|
|
32
|
+
|
|
33
|
+
### Example
|
|
34
|
+
|
|
35
|
+
~~~ruby
|
|
36
|
+
require 'net/tcp_client'
|
|
37
|
+
|
|
38
|
+
Net::TCPClient.connect(server: 'mydomain:3300') do |client|
|
|
39
|
+
client.send('Update the database')
|
|
40
|
+
response = client.read(20)
|
|
41
|
+
puts "Received: #{response}"
|
|
42
|
+
end
|
|
43
|
+
~~~
|
|
44
|
+
|
|
45
|
+
Enable SSL encryption:
|
|
46
|
+
|
|
47
|
+
~~~ruby
|
|
48
|
+
require 'net/tcp_client'
|
|
26
49
|
|
|
27
|
-
Net::TCPClient
|
|
50
|
+
Net::TCPClient.connect(server: 'mydomain:3300', ssl: true) do |client|
|
|
51
|
+
client.send('Update the database')
|
|
52
|
+
response = client.read(20)
|
|
53
|
+
puts "Received: #{response}"
|
|
54
|
+
end
|
|
55
|
+
~~~
|
|
28
56
|
|
|
29
|
-
|
|
30
|
-
that support automatic failover, re-connect and messaging retries.
|
|
57
|
+
## High Availability
|
|
31
58
|
|
|
32
|
-
|
|
59
|
+
Net::TCPClient automatically tries each server in turn, should it fail to connect, or
|
|
60
|
+
if the connection is lost the next server is tried immediately.
|
|
33
61
|
|
|
34
|
-
|
|
62
|
+
Net::TCPClient detects DNS entries that have multiple IP Addresses associated with them and
|
|
63
|
+
adds each of the ip addresses for the single DNS name to the list of servers to try to connect to.
|
|
35
64
|
|
|
36
|
-
|
|
65
|
+
If a server is unavailable, cannot connect, or the connection is lost, the next server is immediately
|
|
66
|
+
tried. Once all servers have been exhausted, it will keep trying to connect, starting with the
|
|
67
|
+
first server again.
|
|
37
68
|
|
|
38
|
-
|
|
39
|
-
|
|
69
|
+
When a connection is first established, and every time a connection is lost, Net::TCPClient
|
|
70
|
+
uses connection policies to determine which server to connect to.
|
|
71
|
+
|
|
72
|
+
## Load Balancing
|
|
73
|
+
|
|
74
|
+
Using the connection policies client TCP connections can be balanced across multiple servers.
|
|
75
|
+
|
|
76
|
+
## Connection Policies
|
|
77
|
+
|
|
78
|
+
#### Ordered
|
|
79
|
+
|
|
80
|
+
Servers are tried in the order they were supplied.
|
|
81
|
+
|
|
82
|
+
~~~ruby
|
|
83
|
+
tcp_client = Net::TCPClient.new(
|
|
84
|
+
servers: ['server1:3300', 'server2:3300', 'server3:3600']
|
|
85
|
+
)
|
|
86
|
+
~~~
|
|
87
|
+
|
|
88
|
+
The servers will tried in the following order:
|
|
89
|
+
`server1`, `server2`, `server3`
|
|
90
|
+
|
|
91
|
+
`:ordered` is the default, but can be explicitly defined follows:
|
|
92
|
+
|
|
93
|
+
~~~ruby
|
|
94
|
+
tcp_client = Net::TCPClient.new(
|
|
95
|
+
servers: ['server1:3300', 'server2:3300', 'server3:3600'],
|
|
96
|
+
policy: :ordered
|
|
97
|
+
)
|
|
98
|
+
~~~
|
|
99
|
+
|
|
100
|
+
#### Random
|
|
101
|
+
|
|
102
|
+
Servers are tried in a Random order.
|
|
103
|
+
|
|
104
|
+
~~~ruby
|
|
105
|
+
tcp_client = Net::TCPClient.new(
|
|
106
|
+
servers: ['server1:3300', 'server2:3300', 'server3:3600'],
|
|
107
|
+
policy: :ordered
|
|
108
|
+
)
|
|
109
|
+
~~~
|
|
110
|
+
|
|
111
|
+
No server is tried again until all of the others have been tried first.
|
|
112
|
+
|
|
113
|
+
Example run, the servers could be tried in the following order:
|
|
114
|
+
`server3`, `server1`, `server2`
|
|
115
|
+
|
|
116
|
+
#### Custom defined order
|
|
117
|
+
|
|
118
|
+
Supply your own custom order / load balancing algorithm for connecting to servers:
|
|
119
|
+
|
|
120
|
+
Example:
|
|
121
|
+
|
|
122
|
+
~~~ruby
|
|
123
|
+
tcp_client = Net::TCPClient.new(
|
|
124
|
+
servers: ['server1:3300', 'server2:3300', 'server3:3600'],
|
|
125
|
+
policy: -> addresses, count do
|
|
126
|
+
# Return nil after the last address has been tried so that retry logic can take over
|
|
127
|
+
if count <= address.size
|
|
128
|
+
addresses.sample
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
)
|
|
132
|
+
~~~
|
|
133
|
+
|
|
134
|
+
The above example returns addresses in random order without checking if a host name has been used before.
|
|
135
|
+
|
|
136
|
+
It is important to check the count so that once all servers have been tried, it should return nil so that
|
|
137
|
+
the retry logic can take over. Otherwise it will constantly try to connect to the servers without
|
|
138
|
+
the retry delays etc.
|
|
139
|
+
|
|
140
|
+
Example run, the servers could be tried in the following order:
|
|
141
|
+
`server3`, `server1`, `server3`
|
|
40
142
|
|
|
143
|
+
### Automatic Retry
|
|
144
|
+
|
|
145
|
+
If a connection cannot be established to any servers in the list Net::TCPClient will retry from the
|
|
146
|
+
first server. This retry behavior can be controlled using the following options:
|
|
147
|
+
|
|
148
|
+
* `connect_retry_count` [Fixnum]
|
|
149
|
+
* Number of times to retry connecting when a connection fails
|
|
150
|
+
* Default: 10
|
|
151
|
+
|
|
152
|
+
* `connect_retry_interval` [Float]
|
|
153
|
+
* Number of seconds between connection retry attempts after the first failed attempt
|
|
154
|
+
* Default: 0.5
|
|
155
|
+
|
|
156
|
+
* `retry_count` [Fixnum]
|
|
157
|
+
* Number of times to retry when calling #retry_on_connection_failure
|
|
158
|
+
* This is independent of :connect_retry_count which still applies with
|
|
159
|
+
* connection failures. This retry controls upto how many times to retry the
|
|
160
|
+
* supplied block should a connection failure occur during the block
|
|
161
|
+
* Default: 3
|
|
162
|
+
|
|
163
|
+
#### Note
|
|
164
|
+
|
|
165
|
+
A server will only be retried again using the retry controls above once all other servers in the
|
|
166
|
+
list have been exhausted.
|
|
167
|
+
|
|
168
|
+
This means that if a connection is lost to a server that it will try to connect to a different server,
|
|
169
|
+
not the same server unless it is the only server in the list.
|
|
170
|
+
|
|
171
|
+
## Tuning
|
|
172
|
+
|
|
173
|
+
If there are multiple servers in the list it is important to keep the `connect_timeout` low otherwise
|
|
174
|
+
it can take a long time to find the next available server.
|
|
175
|
+
|
|
176
|
+
## Retry on connection loss
|
|
177
|
+
|
|
178
|
+
To transparently handle when a connection is lost after it has been established
|
|
179
|
+
wrap calls that can be retried with `retry_on_connection_failure`.
|
|
180
|
+
|
|
181
|
+
~~~ruby
|
|
41
182
|
Net::TCPClient.connect(
|
|
42
183
|
server: 'localhost:3300',
|
|
43
184
|
connect_retry_interval: 0.1,
|
|
@@ -45,12 +186,57 @@ Net::TCPClient.connect(
|
|
|
45
186
|
) do |client|
|
|
46
187
|
# If the connection is lost, create a new one and retry the send
|
|
47
188
|
client.retry_on_connection_failure do
|
|
48
|
-
client.send('
|
|
189
|
+
client.send('How many users available?')
|
|
190
|
+
response = client.read(20)
|
|
191
|
+
puts "Received: #{response}"
|
|
49
192
|
end
|
|
50
|
-
response = client.read(20)
|
|
51
|
-
puts "Received: #{response}"
|
|
52
193
|
end
|
|
53
|
-
|
|
194
|
+
~~~
|
|
195
|
+
|
|
196
|
+
If the connection is lost during either the `send` or the `read` above the
|
|
197
|
+
entire block will be re-tried once the connection has been re-stablished.
|
|
198
|
+
|
|
199
|
+
## Callbacks
|
|
200
|
+
|
|
201
|
+
Any time a connection has been established a callback can be called to handle activities such as:
|
|
202
|
+
|
|
203
|
+
* Initialize per connection session sequence numbers.
|
|
204
|
+
* Pass authentication information to the server.
|
|
205
|
+
* Perform a handshake with the server.
|
|
206
|
+
|
|
207
|
+
#### Authentication example:
|
|
208
|
+
|
|
209
|
+
~~~ruby
|
|
210
|
+
tcp_client = Net::TCPClient.new(
|
|
211
|
+
servers: ['server1:3300', 'server2:3300', 'server3:3600'],
|
|
212
|
+
on_connect: -> do |client|
|
|
213
|
+
client.send('My username and password')
|
|
214
|
+
result = client.read(2)
|
|
215
|
+
raise "Authentication failed" if result != 'OK'
|
|
216
|
+
end
|
|
217
|
+
)
|
|
218
|
+
~~~
|
|
219
|
+
|
|
220
|
+
#### Per connection sequence number example:
|
|
221
|
+
|
|
222
|
+
~~~ruby
|
|
223
|
+
tcp_client = Net::TCPClient.new(
|
|
224
|
+
servers: ['server1:3300', 'server2:3300', 'server3:3600'],
|
|
225
|
+
on_connect: -> do |client|
|
|
226
|
+
# Set the sequence number to 0
|
|
227
|
+
user_data = 0
|
|
228
|
+
end
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
tcp_client.retry_on_connection_failure do
|
|
232
|
+
# Send with the sequence number
|
|
233
|
+
tcp_client.send("#{tcp_client.user_data} hello")
|
|
234
|
+
result = tcp_client.receive(30)
|
|
235
|
+
|
|
236
|
+
# Increment sequence number after every call to the server
|
|
237
|
+
tcp_client.user_data += 1
|
|
238
|
+
end
|
|
239
|
+
~~~
|
|
54
240
|
|
|
55
241
|
## Project Status
|
|
56
242
|
|
|
@@ -64,34 +250,46 @@ test on a daily basis, including connections over the internet between remote da
|
|
|
64
250
|
|
|
65
251
|
gem install net_tcp_client
|
|
66
252
|
|
|
67
|
-
|
|
253
|
+
To enable logging add [Semantic Logger](http://rocketjob.github.io/semantic_logger):
|
|
68
254
|
|
|
69
255
|
gem install semantic_logger
|
|
70
256
|
|
|
71
257
|
Or, add the following lines to you `Gemfile`:
|
|
72
258
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
259
|
+
~~~ruby
|
|
260
|
+
gem 'semantic_logger'
|
|
261
|
+
gem 'net_tcp_client'
|
|
262
|
+
~~~
|
|
77
263
|
|
|
78
264
|
To configure a stand-alone application for Semantic Logger:
|
|
79
265
|
|
|
80
|
-
|
|
266
|
+
~~~ruby
|
|
81
267
|
require 'semantic_logger'
|
|
82
268
|
|
|
83
269
|
# Set the global default log level
|
|
84
270
|
SemanticLogger.default_level = :trace
|
|
85
271
|
|
|
86
272
|
# Log to a file, and use the colorized formatter
|
|
87
|
-
SemanticLogger.add_appender('development.log',
|
|
88
|
-
|
|
273
|
+
SemanticLogger.add_appender(file_name: 'development.log', formatter: :color)
|
|
274
|
+
~~~
|
|
89
275
|
|
|
90
276
|
If running Rails, see: [Semantic Logger Rails](http://rocketjob.github.io/semantic_logger/rails.html)
|
|
91
277
|
|
|
92
|
-
|
|
278
|
+
### Support
|
|
93
279
|
|
|
94
|
-
|
|
280
|
+
Join the [Gitter chat session](https://gitter.im/rocketjob/support) if you have any questions.
|
|
281
|
+
|
|
282
|
+
Issues / bugs can be reported via [Github issues](https://github.com/rocketjob/net_tcp_client/issues).
|
|
283
|
+
|
|
284
|
+
### Upgrading to V2
|
|
285
|
+
|
|
286
|
+
The following breaking changes have been made with V2:
|
|
287
|
+
* The Connection timeout default is now 10 seconds, was 30 seconds.
|
|
288
|
+
* To enable logging, add gem semantic_logger.
|
|
289
|
+
* The :logger option has been removed.
|
|
290
|
+
* Deprecated option and attribute :server_selector has been removed.
|
|
291
|
+
|
|
292
|
+
### Upgrading from ResilientSocket 
|
|
95
293
|
|
|
96
294
|
ResilientSocket::TCPClient has been renamed to Net::TCPClient.
|
|
97
295
|
The API is exactly the same, just with a new namespace. Please upgrade to the new
|
|
@@ -101,8 +299,8 @@ with `Net::TCPClient` in your code.
|
|
|
101
299
|
## Supports
|
|
102
300
|
|
|
103
301
|
Tested and supported on the following Ruby platforms:
|
|
104
|
-
- Ruby 1
|
|
105
|
-
- JRuby 1.7, 9.0 and above
|
|
302
|
+
- Ruby 2.1, 2.2, 2.3 and above
|
|
303
|
+
- JRuby 1.7.23, 9.0 and above
|
|
106
304
|
- Rubinius 2.5 and above
|
|
107
305
|
|
|
108
306
|
There is a soft dependency on [Semantic Logger](http://github.com/rocketjob/semantic_logger). It will use SemanticLogger only if
|
|
@@ -112,14 +310,12 @@ it is already available, otherwise any other standard Ruby logger can be used.
|
|
|
112
310
|
|
|
113
311
|
Be sure to place the `semantic_logger` gem dependency before `net_tcp_client` in your Gemfile.
|
|
114
312
|
|
|
115
|
-
## Versioning
|
|
116
|
-
|
|
117
|
-
This project adheres to [Semantic Versioning](http://semver.org/).
|
|
118
|
-
|
|
119
313
|
## Author
|
|
120
314
|
|
|
121
315
|
[Reid Morrison](https://github.com/reidmorrison)
|
|
122
316
|
|
|
317
|
+
[Contributors](https://github.com/rocketjob/net_tcp_client/graphs/contributors)
|
|
318
|
+
|
|
123
319
|
## Versioning
|
|
124
320
|
|
|
125
321
|
This project uses [Semantic Versioning](http://semver.org/).
|
data/lib/net/tcp_client.rb
CHANGED
|
@@ -1,6 +1,22 @@
|
|
|
1
1
|
require 'socket'
|
|
2
|
+
# Load SemanticLogger if available
|
|
3
|
+
begin
|
|
4
|
+
require 'semantic_logger'
|
|
5
|
+
rescue LoadError
|
|
6
|
+
end
|
|
2
7
|
require 'net/tcp_client/version'
|
|
8
|
+
require 'net/tcp_client/address'
|
|
3
9
|
require 'net/tcp_client/exceptions'
|
|
4
10
|
require 'net/tcp_client/tcp_client'
|
|
5
|
-
|
|
6
|
-
|
|
11
|
+
|
|
12
|
+
# @formatter:off
|
|
13
|
+
module Net
|
|
14
|
+
class TCPClient
|
|
15
|
+
module Policy
|
|
16
|
+
autoload :Base, 'net/tcp_client/policy/base.rb'
|
|
17
|
+
autoload :Custom, 'net/tcp_client/policy/custom.rb'
|
|
18
|
+
autoload :Ordered, 'net/tcp_client/policy/ordered.rb'
|
|
19
|
+
autoload :Random, 'net/tcp_client/policy/random.rb'
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
require 'socket'
|
|
2
|
+
require 'ipaddr'
|
|
3
|
+
module Net
|
|
4
|
+
class TCPClient
|
|
5
|
+
# Host name, ip address and port to connect to
|
|
6
|
+
class Address
|
|
7
|
+
attr_accessor :host_name, :ip_address, :port
|
|
8
|
+
|
|
9
|
+
# Returns [Array<String>] ip addresses for the supplied DNS entry
|
|
10
|
+
# Returns dns_name if it is already an IP Address
|
|
11
|
+
def self.ip_addresses(dns_name)
|
|
12
|
+
ips = []
|
|
13
|
+
Socket.getaddrinfo(dns_name, nil, Socket::AF_INET, Socket::SOCK_STREAM).each do |s|
|
|
14
|
+
ips << s[3] if s[0] == 'AF_INET'
|
|
15
|
+
end
|
|
16
|
+
ips.uniq
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Returns [Array<Net::TCPClient::Address>] addresses for a given DNS / host name.
|
|
20
|
+
# The Addresses will contain the resolved ip address, host name, and port number.
|
|
21
|
+
#
|
|
22
|
+
# Note:
|
|
23
|
+
# Multiple ip addresses will be returned when a DNS entry has multiple ip addresses associated with it.
|
|
24
|
+
def self.addresses(dns_name, port)
|
|
25
|
+
ip_addresses(dns_name).collect { |ip| new(dns_name, ip, port) }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Returns [Array<Net::TCPClient::Address>] addresses for a list of DNS / host name's
|
|
29
|
+
# that are paired with their numbers
|
|
30
|
+
#
|
|
31
|
+
# server_name should be either a host_name, or ip address combined with a port:
|
|
32
|
+
# "host_name:1234"
|
|
33
|
+
# "192.168.1.10:80"
|
|
34
|
+
def self.addresses_for_server_name(server_name)
|
|
35
|
+
dns_name, port = server_name.split(':')
|
|
36
|
+
port = port.to_i
|
|
37
|
+
raise(ArgumentError, "Invalid host_name: #{server_name.inspect}. Must be formatted as 'host_name:1234' or '192.168.1.10:80'") unless dns_name && (port > 0)
|
|
38
|
+
addresses(dns_name, port)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def initialize(host_name, ip_address, port)
|
|
42
|
+
@host_name = host_name
|
|
43
|
+
@ip_address = ip_address
|
|
44
|
+
@port = port.to_i
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def to_s
|
|
48
|
+
"#{host_name}[#{ip_address}]:#{port}"
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
module Net
|
|
2
2
|
class TCPClient
|
|
3
3
|
|
|
4
|
-
class ConnectionTimeout < ::SocketError
|
|
4
|
+
class ConnectionTimeout < ::SocketError
|
|
5
5
|
end
|
|
6
|
-
class ReadTimeout < ::SocketError
|
|
6
|
+
class ReadTimeout < ::SocketError
|
|
7
|
+
end
|
|
8
|
+
class WriteTimeout < ::SocketError
|
|
7
9
|
end
|
|
8
10
|
|
|
9
11
|
# Raised by ResilientSocket whenever a Socket connection failure has occurred
|
|
10
12
|
class ConnectionFailure < ::SocketError
|
|
11
|
-
# Returns the
|
|
13
|
+
# Returns the host name and port against which the connection failure occurred
|
|
12
14
|
attr_reader :server
|
|
13
15
|
|
|
14
16
|
# Returns the original exception that caused the connection failure
|