net_tcp_client 2.0.1 → 2.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +20 -20
- data/Rakefile +10 -17
- data/lib/net/tcp_client/address.rb +11 -6
- data/lib/net/tcp_client/exceptions.rb +3 -3
- data/lib/net/tcp_client/policy/base.rb +0 -1
- data/lib/net/tcp_client/policy/custom.rb +5 -3
- data/lib/net/tcp_client/policy/ordered.rb +1 -2
- data/lib/net/tcp_client/policy/random.rb +1 -2
- data/lib/net/tcp_client/tcp_client.rb +149 -122
- data/lib/net/tcp_client/version.rb +2 -2
- data/lib/net/tcp_client.rb +10 -10
- data/lib/net_tcp_client.rb +1 -1
- metadata +11 -32
- data/test/address_test.rb +0 -91
- data/test/policy/custom_policy_test.rb +0 -42
- data/test/policy/ordered_policy_test.rb +0 -36
- data/test/policy/random_policy_test.rb +0 -46
- data/test/simple_tcp_server.rb +0 -140
- data/test/ssl_files/ca.pem +0 -19
- data/test/ssl_files/localhost-server-key.pem +0 -27
- data/test/ssl_files/localhost-server.pem +0 -18
- data/test/tcp_client_test.rb +0 -245
- data/test/test_helper.rb +0 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e8ada0256a62a84b52bd1084e1c82d4735c28fafb652e933afb7828d9176a262
|
4
|
+
data.tar.gz: ebb5a4e0ae53dffdc317b88263ed60a027b85cac35f1fa909fb626fad62fef88
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 74165666c671d74fd1ffe989692cf8f108145cdcf2f70cd82fc4f90730129e391deb8055177ea9eebabcd9d03ea6bdcbf60f117c8aa5f1fe77645a2762b46905
|
7
|
+
data.tar.gz: b5de49d7560b9ed8a20fde3d211178b37481b5e988c7027afe2c87569f3d81c012aa8d5c4d79590ec5f47d2cfce41280e76cdf3c8cd4bad31d2f7fd2f48f077e
|
data/README.md
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# net_tcp_client
|
2
|
-
[![Gem Version](https://img.shields.io/gem/v/net_tcp_client.svg)](https://rubygems.org/gems/net_tcp_client) [![Build Status](https://
|
2
|
+
[![Gem Version](https://img.shields.io/gem/v/net_tcp_client.svg)](https://rubygems.org/gems/net_tcp_client) [![Build Status](https://github.com/reidmorrison/net_tcp_client/workflows/build/badge.svg)](https://github.com/reidmorrison/net_tcp_client/actions?query=workflow%3Abuild) [![Downloads](https://img.shields.io/gem/dt/net_tcp_client.svg)](https://rubygems.org/gems/net_tcp_client) [![License](https://img.shields.io/badge/license-Apache%202.0-brightgreen.svg)](http://opensource.org/licenses/Apache-2.0) ![](https://img.shields.io/badge/status-Production%20Ready-blue.svg)
|
3
3
|
|
4
4
|
Net::TCPClient is a TCP Socket Client with automated failover, load balancing, retries and built-in timeouts.
|
5
5
|
|
6
|
-
*
|
6
|
+
* https://github.com/reidmorrison/net_tcp_client
|
7
7
|
|
8
8
|
## Introduction
|
9
9
|
|
@@ -36,7 +36,7 @@ prevent a network issue from "hanging" the client program.
|
|
36
36
|
require 'net/tcp_client'
|
37
37
|
|
38
38
|
Net::TCPClient.connect(server: 'mydomain:3300') do |client|
|
39
|
-
client.
|
39
|
+
client.write('Update the database')
|
40
40
|
response = client.read(20)
|
41
41
|
puts "Received: #{response}"
|
42
42
|
end
|
@@ -48,7 +48,7 @@ Enable SSL encryption:
|
|
48
48
|
require 'net/tcp_client'
|
49
49
|
|
50
50
|
Net::TCPClient.connect(server: 'mydomain:3300', ssl: true) do |client|
|
51
|
-
client.
|
51
|
+
client.write('Update the database')
|
52
52
|
response = client.read(20)
|
53
53
|
puts "Received: #{response}"
|
54
54
|
end
|
@@ -104,7 +104,7 @@ Servers are tried in a Random order.
|
|
104
104
|
~~~ruby
|
105
105
|
tcp_client = Net::TCPClient.new(
|
106
106
|
servers: ['server1:3300', 'server2:3300', 'server3:3600'],
|
107
|
-
policy: :
|
107
|
+
policy: :random
|
108
108
|
)
|
109
109
|
~~~
|
110
110
|
|
@@ -145,7 +145,7 @@ Example run, the servers could be tried in the following order:
|
|
145
145
|
If a connection cannot be established to any servers in the list Net::TCPClient will retry from the
|
146
146
|
first server. This retry behavior can be controlled using the following options:
|
147
147
|
|
148
|
-
* `connect_retry_count` [
|
148
|
+
* `connect_retry_count` [Integer]
|
149
149
|
* Number of times to retry connecting when a connection fails
|
150
150
|
* Default: 10
|
151
151
|
|
@@ -153,7 +153,7 @@ first server. This retry behavior can be controlled using the following options:
|
|
153
153
|
* Number of seconds between connection retry attempts after the first failed attempt
|
154
154
|
* Default: 0.5
|
155
155
|
|
156
|
-
* `retry_count` [
|
156
|
+
* `retry_count` [Integer]
|
157
157
|
* Number of times to retry when calling #retry_on_connection_failure
|
158
158
|
* This is independent of :connect_retry_count which still applies with
|
159
159
|
* connection failures. This retry controls upto how many times to retry the
|
@@ -184,16 +184,16 @@ Net::TCPClient.connect(
|
|
184
184
|
connect_retry_interval: 0.1,
|
185
185
|
connect_retry_count: 5
|
186
186
|
) do |client|
|
187
|
-
# If the connection is lost, create a new one and retry the
|
187
|
+
# If the connection is lost, create a new one and retry the write
|
188
188
|
client.retry_on_connection_failure do
|
189
|
-
client.
|
189
|
+
client.write('How many users available?')
|
190
190
|
response = client.read(20)
|
191
191
|
puts "Received: #{response}"
|
192
192
|
end
|
193
193
|
end
|
194
194
|
~~~
|
195
195
|
|
196
|
-
If the connection is lost during either the `
|
196
|
+
If the connection is lost during either the `write` or the `read` above the
|
197
197
|
entire block will be re-tried once the connection has been re-stablished.
|
198
198
|
|
199
199
|
## Callbacks
|
@@ -210,7 +210,7 @@ Any time a connection has been established a callback can be called to handle ac
|
|
210
210
|
tcp_client = Net::TCPClient.new(
|
211
211
|
servers: ['server1:3300', 'server2:3300', 'server3:3600'],
|
212
212
|
on_connect: -> do |client|
|
213
|
-
client.
|
213
|
+
client.write('My username and password')
|
214
214
|
result = client.read(2)
|
215
215
|
raise "Authentication failed" if result != 'OK'
|
216
216
|
end
|
@@ -224,13 +224,13 @@ tcp_client = Net::TCPClient.new(
|
|
224
224
|
servers: ['server1:3300', 'server2:3300', 'server3:3600'],
|
225
225
|
on_connect: -> do |client|
|
226
226
|
# Set the sequence number to 0
|
227
|
-
user_data = 0
|
227
|
+
client.user_data = 0
|
228
228
|
end
|
229
229
|
)
|
230
230
|
|
231
231
|
tcp_client.retry_on_connection_failure do
|
232
|
-
#
|
233
|
-
tcp_client.
|
232
|
+
# Write with the sequence number
|
233
|
+
tcp_client.write("#{tcp_client.user_data} hello")
|
234
234
|
result = tcp_client.receive(30)
|
235
235
|
|
236
236
|
# Increment sequence number after every call to the server
|
@@ -250,7 +250,7 @@ test on a daily basis, including connections over the internet between remote da
|
|
250
250
|
|
251
251
|
gem install net_tcp_client
|
252
252
|
|
253
|
-
To enable logging add [Semantic Logger](
|
253
|
+
To enable logging add [Semantic Logger](https://logger.rocketjob.io/):
|
254
254
|
|
255
255
|
gem install semantic_logger
|
256
256
|
|
@@ -273,13 +273,13 @@ SemanticLogger.default_level = :trace
|
|
273
273
|
SemanticLogger.add_appender(file_name: 'development.log', formatter: :color)
|
274
274
|
~~~
|
275
275
|
|
276
|
-
If running Rails, see: [Semantic Logger Rails](
|
276
|
+
If running Rails, see: [Semantic Logger Rails](https://logger.rocketjob.io/rails.html)
|
277
277
|
|
278
278
|
### Support
|
279
279
|
|
280
280
|
Join the [Gitter chat session](https://gitter.im/rocketjob/support) if you have any questions.
|
281
281
|
|
282
|
-
Issues / bugs can be reported via [Github issues](https://github.com/
|
282
|
+
Issues / bugs can be reported via [Github issues](https://github.com/reidmorrison/net_tcp_client/issues).
|
283
283
|
|
284
284
|
### Upgrading to V2
|
285
285
|
|
@@ -303,7 +303,7 @@ Tested and supported on the following Ruby platforms:
|
|
303
303
|
- JRuby 1.7.23, 9.0 and above
|
304
304
|
- Rubinius 2.5 and above
|
305
305
|
|
306
|
-
There is a soft dependency on [Semantic Logger](
|
306
|
+
There is a soft dependency on [Semantic Logger](https://github.com/reidmorrison/semantic_logger). It will use SemanticLogger only if
|
307
307
|
it is already available, otherwise any other standard Ruby logger can be used.
|
308
308
|
|
309
309
|
### Note
|
@@ -314,8 +314,8 @@ Be sure to place the `semantic_logger` gem dependency before `net_tcp_client` in
|
|
314
314
|
|
315
315
|
[Reid Morrison](https://github.com/reidmorrison)
|
316
316
|
|
317
|
-
[Contributors](https://github.com/
|
317
|
+
[Contributors](https://github.com/reidmorrison/net_tcp_client/graphs/contributors)
|
318
318
|
|
319
319
|
## Versioning
|
320
320
|
|
321
|
-
This project uses [Semantic Versioning](
|
321
|
+
This project uses [Semantic Versioning](https://semver.org/).
|
data/Rakefile
CHANGED
@@ -1,28 +1,21 @@
|
|
1
|
-
require
|
2
|
-
|
3
|
-
|
4
|
-
$LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
|
5
|
-
require 'net/tcp_client/version'
|
1
|
+
require "rake/testtask"
|
2
|
+
require_relative "lib/net/tcp_client/version"
|
6
3
|
|
7
4
|
task :gem do
|
8
|
-
system
|
5
|
+
system "gem build net_tcp_client.gemspec"
|
9
6
|
end
|
10
7
|
|
11
|
-
task :
|
8
|
+
task publish: :gem do
|
12
9
|
system "git tag -a v#{Net::TCPClient::VERSION} -m 'Tagging #{Net::TCPClient::VERSION}'"
|
13
|
-
system
|
10
|
+
system "git push --tags"
|
14
11
|
system "gem push net_tcp_client-#{Net::TCPClient::VERSION}.gem"
|
15
12
|
system "rm net_tcp_client-#{Net::TCPClient::VERSION}.gem"
|
16
13
|
end
|
17
14
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
t.verbose = true
|
23
|
-
end
|
24
|
-
|
25
|
-
Rake::Task['functional'].invoke
|
15
|
+
Rake::TestTask.new(:test) do |t|
|
16
|
+
t.pattern = "test/**/*_test.rb"
|
17
|
+
t.verbose = true
|
18
|
+
t.warning = true
|
26
19
|
end
|
27
20
|
|
28
|
-
task :
|
21
|
+
task default: :test
|
@@ -1,5 +1,5 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "socket"
|
2
|
+
require "ipaddr"
|
3
3
|
module Net
|
4
4
|
class TCPClient
|
5
5
|
# Host name, ip address and port to connect to
|
@@ -11,7 +11,7 @@ module Net
|
|
11
11
|
def self.ip_addresses(dns_name)
|
12
12
|
ips = []
|
13
13
|
Socket.getaddrinfo(dns_name, nil, Socket::AF_INET, Socket::SOCK_STREAM).each do |s|
|
14
|
-
ips << s[3] if s[0] ==
|
14
|
+
ips << s[3] if s[0] == "AF_INET"
|
15
15
|
end
|
16
16
|
ips.uniq
|
17
17
|
end
|
@@ -32,9 +32,15 @@ module Net
|
|
32
32
|
# "host_name:1234"
|
33
33
|
# "192.168.1.10:80"
|
34
34
|
def self.addresses_for_server_name(server_name)
|
35
|
-
dns_name, port = server_name.split(
|
35
|
+
dns_name, port = server_name.split(":")
|
36
36
|
port = port.to_i
|
37
|
-
|
37
|
+
unless dns_name && port&.positive?
|
38
|
+
raise(
|
39
|
+
ArgumentError,
|
40
|
+
"Invalid host_name: #{server_name.inspect}. Must be formatted as 'host_name:1234' or '192.168.1.10:80'"
|
41
|
+
)
|
42
|
+
end
|
43
|
+
|
38
44
|
addresses(dns_name, port)
|
39
45
|
end
|
40
46
|
|
@@ -48,6 +54,5 @@ module Net
|
|
48
54
|
"#{host_name}[#{ip_address}]:#{port}"
|
49
55
|
end
|
50
56
|
end
|
51
|
-
|
52
57
|
end
|
53
58
|
end
|
@@ -1,10 +1,11 @@
|
|
1
1
|
module Net
|
2
2
|
class TCPClient
|
3
|
-
|
4
3
|
class ConnectionTimeout < ::SocketError
|
5
4
|
end
|
5
|
+
|
6
6
|
class ReadTimeout < ::SocketError
|
7
7
|
end
|
8
|
+
|
8
9
|
class WriteTimeout < ::SocketError
|
9
10
|
end
|
10
11
|
|
@@ -27,12 +28,11 @@ module Net
|
|
27
28
|
#
|
28
29
|
# cause [Exception]
|
29
30
|
# Original Exception if any, otherwise nil
|
30
|
-
def initialize(message, server, cause=nil)
|
31
|
+
def initialize(message, server, cause = nil)
|
31
32
|
@server = server
|
32
33
|
@cause = cause
|
33
34
|
super(message)
|
34
35
|
end
|
35
36
|
end
|
36
|
-
|
37
37
|
end
|
38
38
|
end
|
@@ -26,13 +26,15 @@ module Net
|
|
26
26
|
# end
|
27
27
|
def each(&block)
|
28
28
|
count = 1
|
29
|
-
while address = @block.call(addresses, count)
|
30
|
-
|
29
|
+
while (address = @block.call(addresses, count))
|
30
|
+
unless address.is_a?(Net::TCPClient::Address) || address.nil?
|
31
|
+
raise(ArgumentError, "Proc must return Net::TCPClient::Address, or nil")
|
32
|
+
end
|
33
|
+
|
31
34
|
block.call(address)
|
32
35
|
count += 1
|
33
36
|
end
|
34
37
|
end
|
35
|
-
|
36
38
|
end
|
37
39
|
end
|
38
40
|
end
|
@@ -5,9 +5,8 @@ module Net
|
|
5
5
|
class Random < Base
|
6
6
|
# Calls the block once for each server, with the addresses in random order
|
7
7
|
def each(&block)
|
8
|
-
addresses.shuffle.each {|address| block.call(address)}
|
8
|
+
addresses.shuffle.each { |address| block.call(address) }
|
9
9
|
end
|
10
|
-
|
11
10
|
end
|
12
11
|
end
|
13
12
|
end
|