resilient_socket 0.4.0 → 0.5.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4ffdee0e077d518369067ed0b3248ec8c67f2aa2
4
+ data.tar.gz: 82f2d747a1bf0caee65bf4428be6d7e47ea83337
5
+ SHA512:
6
+ metadata.gz: 5c7d639d4af9a6493a34fcf14c06e20d36e95fe352608d01484fc230029d672623364ef79430a508cff5b1d8045250962ac8009fe37b823d24bb8698f75ddad4
7
+ data.tar.gz: 9120d0ee7557ca7f512afe84ed4d3546a2c3c749e5ecd7b1392387db9fbf24ced1363552aa31385f6f1457acdf84d23f32d5399ce6afc90e8de0294cbbc83e42
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'http://rubygems.org'
2
+
3
+ group :test do
4
+ gem "shoulda"
5
+ gem "bson_ext", :platform => 'ruby'
6
+ end
7
+
8
+ gem 'semantic_logger'
9
+
@@ -0,0 +1,38 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ activesupport (3.2.12)
5
+ i18n (~> 0.6)
6
+ multi_json (~> 1.0)
7
+ atomic (1.0.1)
8
+ bourne (1.1.2)
9
+ mocha (= 0.10.5)
10
+ bson (1.8.3)
11
+ bson_ext (1.8.3)
12
+ bson (~> 1.8.3)
13
+ i18n (0.6.4)
14
+ metaclass (0.0.1)
15
+ mocha (0.10.5)
16
+ metaclass (~> 0.0.1)
17
+ multi_json (1.6.1)
18
+ semantic_logger (2.0.0)
19
+ sync_attr
20
+ thread_safe
21
+ shoulda (3.3.2)
22
+ shoulda-context (~> 1.0.1)
23
+ shoulda-matchers (~> 1.4.1)
24
+ shoulda-context (1.0.2)
25
+ shoulda-matchers (1.4.2)
26
+ activesupport (>= 3.0.0)
27
+ bourne (~> 1.1.2)
28
+ sync_attr (0.1.1)
29
+ thread_safe (0.1.0)
30
+ atomic
31
+
32
+ PLATFORMS
33
+ ruby
34
+
35
+ DEPENDENCIES
36
+ bson_ext
37
+ semantic_logger
38
+ shoulda
data/Rakefile CHANGED
@@ -2,6 +2,7 @@ lib = File.expand_path('../lib/', __FILE__)
2
2
  $:.unshift lib unless $:.include?(lib)
3
3
 
4
4
  require 'rubygems'
5
+ require 'rubygems/package'
5
6
  require 'rake/clean'
6
7
  require 'rake/testtask'
7
8
  require 'date'
@@ -19,11 +20,12 @@ task :gem do |t|
19
20
  spec.date = Date.today.to_s
20
21
  spec.summary = "A Resilient TCP Socket Client with built-in timeouts, retries, and logging"
21
22
  spec.description = "A Resilient TCP Socket Client with built-in timeouts, retries, and logging"
22
- spec.files = FileList["./**/*"].exclude(/.gem$/, /.log$/,/^nbproject/).map{|f| f.sub(/^\.\//, '')}
23
+ spec.files = FileList["./**/*"].exclude(/\.gem$/, /\.log$/,/nbproject/).map{|f| f.sub(/^\.\//, '')}
24
+ spec.license = "Apache License V2.0"
23
25
  spec.has_rdoc = true
24
- spec.add_dependency 'semantic_logger'
26
+ spec.add_dependency 'semantic_logger', '>= 2.1'
25
27
  end
26
- Gem::Builder.new(gemspec).build
28
+ Gem::Package.build gemspec
27
29
  end
28
30
 
29
31
  desc "Run Test Suite"
@@ -29,9 +29,6 @@ module ResilientSocket
29
29
  # * write
30
30
  #
31
31
  # Future:
32
- #
33
- # * Automatic failover to another server should the current server not respond
34
- # to a connection request by supplying an array of host names
35
32
  # * Add auto-reconnect feature to sysread, syswrite, etc...
36
33
  # * To be a drop-in replacement to TCPSocket should also need to implement the
37
34
  # following TCPSocket instance methods: :addr, :peeraddr
@@ -41,6 +38,8 @@ module ResilientSocket
41
38
  # has to be completely destroyed and recreated after a connection failure
42
39
  #
43
40
  class TCPClient
41
+ include SemanticLogger::Loggable
42
+
44
43
  # Supports embedding user supplied data along with this connection
45
44
  # such as sequence number and other connection specific information
46
45
  attr_accessor :user_data
@@ -49,7 +48,7 @@ module ResilientSocket
49
48
  #
50
49
  # Example:
51
50
  # localhost:2000
52
- attr_reader :server, :buffered
51
+ attr_reader :server
53
52
 
54
53
  attr_accessor :read_timeout, :connect_timeout, :connect_retry_count,
55
54
  :retry_count, :connect_retry_interval, :server_selector, :close_on_error
@@ -131,10 +130,10 @@ module ResilientSocket
131
130
  # Default: Half of the :read_timeout ( 30 seconds )
132
131
  #
133
132
  # :log_level [Symbol]
134
- # Only set this level to override the global SemanticLogger logging level
135
- # Can be used to turn on trace or debug level logging in production
133
+ # Set the logging level for the TCPClient
136
134
  # Any valid SemanticLogger log level:
137
135
  # :trace, :debug, :info, :warn, :error, :fatal
136
+ # Default: SemanticLogger.default_level
138
137
  #
139
138
  # :buffered [Boolean]
140
139
  # Whether to use Nagle's Buffering algorithm (http://en.wikipedia.org/wiki/Nagle's_algorithm)
@@ -177,6 +176,15 @@ module ResilientSocket
177
176
  # :random
178
177
  # Randomly select a server from the list every time a connection
179
178
  # is established, including during automatic connection recovery.
179
+ # :nearest
180
+ # FUTURE - Not implemented yet
181
+ # The server with an IP address that most closely matches the
182
+ # local ip address will be attempted first
183
+ # This will result in connections to servers on the localhost
184
+ # first prior to looking at remote servers
185
+ # :ping_time
186
+ # FUTURE - Not implemented yet
187
+ # The server with the lowest ping time will be selected first
180
188
  # Proc:
181
189
  # When a Proc is supplied, it will be called passing in the list
182
190
  # of servers. The Proc must return one server name
@@ -226,8 +234,8 @@ module ResilientSocket
226
234
  raise "Missing mandatory :server or :servers" unless server = params.delete(:server)
227
235
  @servers = [ server ]
228
236
  end
229
- @logger = SemanticLogger::Logger.new("#{self.class.name} #{@servers.inspect}", params.delete(:log_level) || SemanticLogger::Logger.default_level)
230
- params.each_pair {|k,v| @logger.warn "Ignoring unknown option #{k} = #{v}"}
237
+ self.logger = SemanticLogger::Logger.new("#{self.class.name} #{@servers.inspect}", params.delete(:log_level))
238
+ params.each_pair {|k,v| logger.warn "Ignoring unknown option #{k} = #{v}"}
231
239
 
232
240
  # Connect to the Server
233
241
  connect
@@ -318,12 +326,12 @@ module ResilientSocket
318
326
  # For a description of the errors, see Socket#write
319
327
  #
320
328
  def write(data)
321
- @logger.trace("#write ==> sending", data)
322
- @logger.benchmark_debug("#write ==> sent #{data.length} bytes") do
329
+ logger.trace("#write ==> sending", data)
330
+ logger.benchmark_debug("#write ==> sent #{data.length} bytes") do
323
331
  begin
324
332
  @socket.write(data)
325
333
  rescue SystemCallError => exception
326
- @logger.warn "#write Connection failure: #{exception.class}: #{exception.message}"
334
+ logger.warn "#write Connection failure: #{exception.class}: #{exception.message}"
327
335
  close if close_on_error
328
336
  raise ConnectionFailure.new("Send Connection failure: #{exception.class}: #{exception.message}", @server, exception)
329
337
  rescue Exception
@@ -371,13 +379,13 @@ module ResilientSocket
371
379
  #
372
380
  def read(length, buffer=nil, timeout=nil)
373
381
  result = nil
374
- @logger.benchmark_debug("#read <== read #{length} bytes") do
382
+ logger.benchmark_debug("#read <== read #{length} bytes") do
375
383
  if timeout != -1
376
384
  # Block on data to read for @read_timeout seconds
377
385
  ready = begin
378
386
  ready = IO.select([@socket], nil, [@socket], timeout || @read_timeout)
379
387
  rescue IOError => exception
380
- @logger.warn "#read Connection failure while waiting for data: #{exception.class}: #{exception.message}"
388
+ logger.warn "#read Connection failure while waiting for data: #{exception.class}: #{exception.message}"
381
389
  close if close_on_error
382
390
  raise ConnectionFailure.new("#{exception.class}: #{exception.message}", @server, exception)
383
391
  rescue Exception
@@ -388,7 +396,7 @@ module ResilientSocket
388
396
  end
389
397
  unless ready
390
398
  close if close_on_error
391
- @logger.warn "#read Timeout waiting for server to reply"
399
+ logger.warn "#read Timeout waiting for server to reply"
392
400
  raise ReadTimeout.new("Timedout after #{timeout || @read_timeout} seconds trying to read from #{@server}")
393
401
  end
394
402
  end
@@ -396,17 +404,17 @@ module ResilientSocket
396
404
  # Read data from socket
397
405
  begin
398
406
  result = buffer.nil? ? @socket.read(length) : @socket.read(length, buffer)
399
- @logger.trace("#read <== received", result.inspect)
407
+ logger.trace("#read <== received", result.inspect)
400
408
 
401
409
  # EOF before all the data was returned
402
410
  if result.nil? || (result.length < length)
403
411
  close if close_on_error
404
- @logger.warn "#read server closed the connection before #{length} bytes were returned"
412
+ logger.warn "#read server closed the connection before #{length} bytes were returned"
405
413
  raise ConnectionFailure.new("Connection lost while reading data", @server, EOFError.new("end of file reached"))
406
414
  end
407
415
  rescue SystemCallError, IOError => exception
408
416
  close if close_on_error
409
- @logger.warn "#read Connection failure while reading data: #{exception.class}: #{exception.message}"
417
+ logger.warn "#read Connection failure while reading data: #{exception.class}: #{exception.message}"
410
418
  raise ConnectionFailure.new("#{exception.class}: #{exception.message}", @server, exception)
411
419
  rescue Exception
412
420
  # Close the connection on any other exception since the connection
@@ -468,15 +476,15 @@ module ResilientSocket
468
476
  exc_str = exception.cause ? "#{exception.cause.class}: #{exception.cause.message}" : exception.message
469
477
  # Re-raise exceptions that should not be retried
470
478
  if !self.class.reconnect_on_errors.include?(exception.cause.class)
471
- @logger.warn "#retry_on_connection_failure not configured to retry: #{exc_str}"
479
+ logger.warn "#retry_on_connection_failure not configured to retry: #{exc_str}"
472
480
  raise exception
473
481
  elsif retries < @retry_count
474
482
  retries += 1
475
- @logger.warn "#retry_on_connection_failure retry #{retries} due to #{exception.class}: #{exception.message}"
483
+ logger.warn "#retry_on_connection_failure retry #{retries} due to #{exception.class}: #{exception.message}"
476
484
  connect
477
485
  retry
478
486
  end
479
- @logger.error "#retry_on_connection_failure Connection failure: #{exception.class}: #{exception.message}. Giving up after #{retries} retries"
487
+ logger.error "#retry_on_connection_failure Connection failure: #{exception.class}: #{exception.message}. Giving up after #{retries} retries"
480
488
  raise ConnectionFailure.new("After #{retries} retries to host '#{server}': #{exc_str}", @server, exception.cause)
481
489
  end
482
490
  end
@@ -487,7 +495,7 @@ module ResilientSocket
487
495
  def close
488
496
  @socket.close unless @socket.closed?
489
497
  rescue IOError => exception
490
- @logger.warn "IOError when attempting to close socket: #{exception.class}: #{exception.message}"
498
+ logger.warn "IOError when attempting to close socket: #{exception.class}: #{exception.message}"
491
499
  end
492
500
 
493
501
  # Returns whether the socket is closed
@@ -539,7 +547,7 @@ module ResilientSocket
539
547
  # :accept, :accept_nonblock, :bind, :connect, :connect_nonblock, :getpeereid,
540
548
  # :ipv6only!, :listen, :recvfrom_nonblock, :sysaccept
541
549
  retries = 0
542
- @logger.benchmark_info "Connecting to server #{server}" do
550
+ logger.benchmark_info "Connected to #{server}" do
543
551
  host_name, port = server.split(":")
544
552
  port = port.to_i
545
553
 
@@ -570,11 +578,11 @@ module ResilientSocket
570
578
  rescue SystemCallError => exception
571
579
  if retries < @connect_retry_count && self.class.reconnect_on_errors.include?(exception.class)
572
580
  retries += 1
573
- @logger.warn "Connection failure: #{exception.class}: #{exception.message}. Retry: #{retries}"
581
+ logger.warn "Connection failure: #{exception.class}: #{exception.message}. Retry: #{retries}"
574
582
  sleep @connect_retry_interval
575
583
  retry
576
584
  end
577
- @logger.error "Connection failure: #{exception.class}: #{exception.message}. Giving up after #{retries} retries"
585
+ logger.error "Connection failure: #{exception.class}: #{exception.message}. Giving up after #{retries} retries"
578
586
  raise ConnectionFailure.new("After #{retries} connection attempts to host '#{server}': #{exception.class}: #{exception.message}", @server, exception)
579
587
  end
580
588
  end
@@ -1,3 +1,3 @@
1
1
  module ResilientSocket #:nodoc
2
- VERSION = "0.4.0"
2
+ VERSION = "0.5.0"
3
3
  end
@@ -107,8 +107,8 @@ class SimpleTCPServer
107
107
  end
108
108
 
109
109
  if $0 == __FILE__
110
- SemanticLogger::Logger.default_level = :trace
111
- SemanticLogger::Logger.appenders << SemanticLogger::Appender::File.new(STDOUT)
110
+ SemanticLogger.default_level = :trace
111
+ SemanticLogger.add_appender(STDOUT)
112
112
  server = SimpleTCPServer.new(2000)
113
113
  server.thread.join
114
114
  end
@@ -8,8 +8,8 @@ require 'shoulda'
8
8
  require 'resilient_socket'
9
9
  require 'simple_tcp_server'
10
10
 
11
- SemanticLogger::Logger.default_level = :trace
12
- SemanticLogger::Logger.appenders << SemanticLogger::Appender::File.new('test.log')
11
+ SemanticLogger.default_level = :trace
12
+ SemanticLogger.add_appender('test.log')
13
13
 
14
14
  # Unit Test for ResilientSocket::TCPClient
15
15
  class TCPClientTest < Test::Unit::TestCase
metadata CHANGED
@@ -1,32 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: resilient_socket
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
5
- prerelease:
4
+ version: 0.5.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Reid Morrison
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2012-11-13 00:00:00.000000000 Z
11
+ date: 2013-04-03 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: semantic_logger
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - '>='
20
18
  - !ruby/object:Gem::Version
21
- version: '0'
19
+ version: '2.1'
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - '>='
28
25
  - !ruby/object:Gem::Version
29
- version: '0'
26
+ version: '2.1'
30
27
  description: A Resilient TCP Socket Client with built-in timeouts, retries, and logging
31
28
  email:
32
29
  - reidmo@gmail.com
@@ -34,44 +31,39 @@ executables: []
34
31
  extensions: []
35
32
  extra_rdoc_files: []
36
33
  files:
34
+ - Gemfile
35
+ - Gemfile.lock
36
+ - LICENSE.txt
37
+ - README.md
38
+ - Rakefile
39
+ - lib/resilient_socket.rb
37
40
  - lib/resilient_socket/exceptions.rb
38
41
  - lib/resilient_socket/tcp_client.rb
39
42
  - lib/resilient_socket/version.rb
40
- - lib/resilient_socket.rb
41
- - LICENSE.txt
42
- - nbproject/private/config.properties
43
- - nbproject/private/private.properties
44
- - nbproject/private/private.xml
45
- - nbproject/private/rake-d.txt
46
- - nbproject/project.properties
47
- - nbproject/project.xml
48
- - Rakefile
49
- - README.md
50
43
  - test/simple_tcp_server.rb
51
44
  - test/tcp_client_test.rb
52
- - test.log.working
53
45
  homepage: https://github.com/ClarityServices/resilient_socket
54
- licenses: []
46
+ licenses:
47
+ - Apache License V2.0
48
+ metadata: {}
55
49
  post_install_message:
56
50
  rdoc_options: []
57
51
  require_paths:
58
52
  - lib
59
53
  required_ruby_version: !ruby/object:Gem::Requirement
60
- none: false
61
54
  requirements:
62
- - - ! '>='
55
+ - - '>='
63
56
  - !ruby/object:Gem::Version
64
57
  version: '0'
65
58
  required_rubygems_version: !ruby/object:Gem::Requirement
66
- none: false
67
59
  requirements:
68
- - - ! '>='
60
+ - - '>='
69
61
  - !ruby/object:Gem::Version
70
62
  version: '0'
71
63
  requirements: []
72
64
  rubyforge_project:
73
- rubygems_version: 1.8.24
65
+ rubygems_version: 2.0.2
74
66
  signing_key:
75
- specification_version: 3
67
+ specification_version: 4
76
68
  summary: A Resilient TCP Socket Client with built-in timeouts, retries, and logging
77
69
  test_files: []
File without changes
@@ -1,3 +0,0 @@
1
- file.reference.resilient_socket-lib=/Users/rmorrison/Sandbox/resilient_socket/lib
2
- file.reference.resilient_socket-test=/Users/rmorrison/Sandbox/resilient_socket/test
3
- platform.active=Ruby_0
@@ -1,4 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project-private xmlns="http://www.netbeans.org/ns/project-private/1">
3
- <editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/1"/>
4
- </project-private>
@@ -1,4 +0,0 @@
1
- clean=
2
- clobber=
3
- gem=
4
- test=
@@ -1,7 +0,0 @@
1
- file.reference.resilient_socket-lib=lib
2
- file.reference.resilient_socket-test=test
3
- main.file=
4
- platform.active=Ruby
5
- source.encoding=UTF-8
6
- src.dir=${file.reference.resilient_socket-lib}
7
- test.src.dir=${file.reference.resilient_socket-test}
@@ -1,15 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project xmlns="http://www.netbeans.org/ns/project/1">
3
- <type>org.netbeans.modules.ruby.rubyproject</type>
4
- <configuration>
5
- <data xmlns="http://www.netbeans.org/ns/ruby-project/1">
6
- <name>resilient_socket</name>
7
- <source-roots>
8
- <root id="src.dir"/>
9
- </source-roots>
10
- <test-roots>
11
- <root id="test.src.dir"/>
12
- </test-roots>
13
- </data>
14
- </configuration>
15
- </project>
Binary file