bertrpc 0.4.0 → 0.4.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/History.txt CHANGED
@@ -1,3 +1,7 @@
1
+ = 0.4.1 / 2009-11-26
2
+ * Major changes
3
+ * Backport timeout option
4
+
1
5
  = 0.4.0 / 2009-10-08
2
6
  * Major changes
3
7
  * Convert to use BERT gem.
data/README.md CHANGED
@@ -56,6 +56,18 @@ The underlying BERT-RPC transaction of the above cast is:
56
56
  <- {noreply}
57
57
 
58
58
 
59
+ Documentation
60
+ -------------
61
+
62
+ Creating a service:
63
+
64
+ # No timeout
65
+ svc = BERTRPC::Service.new('localhost', 9999)
66
+
67
+ # 10s socket read timeout, raises BERTRPC::ReadTimeoutError
68
+ svc = BERTRPC::Service.new('localhost', 9999, 10)
69
+
70
+
59
71
  Copyright
60
72
  ---------
61
73
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.0
1
+ 0.4.1
data/bertrpc.gemspec CHANGED
@@ -1,15 +1,15 @@
1
1
  # Generated by jeweler
2
- # DO NOT EDIT THIS FILE
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in rakefile, and run the gemspec command
4
4
  # -*- encoding: utf-8 -*-
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{bertrpc}
8
- s.version = "0.4.0"
8
+ s.version = "0.4.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Tom Preston-Werner"]
12
- s.date = %q{2009-10-08}
12
+ s.date = %q{2009-11-26}
13
13
  s.email = %q{tom@mojombo.com}
14
14
  s.extra_rdoc_files = [
15
15
  "LICENSE",
@@ -26,6 +26,7 @@ Gem::Specification.new do |s|
26
26
  "bertrpc.gemspec",
27
27
  "lib/bertrpc.rb",
28
28
  "lib/bertrpc/action.rb",
29
+ "lib/bertrpc/buffered_io.rb",
29
30
  "lib/bertrpc/encodes.rb",
30
31
  "lib/bertrpc/errors.rb",
31
32
  "lib/bertrpc/mod.rb",
@@ -70,3 +71,4 @@ Gem::Specification.new do |s|
70
71
  s.add_dependency(%q<erlectricity>, [">= 1.0.1"])
71
72
  end
72
73
  end
74
+
@@ -24,7 +24,7 @@ module BERTRPC
24
24
  end
25
25
 
26
26
  def transaction(bert_request)
27
- sock = TCPSocket.new(@svc.host, @svc.port)
27
+ sock = connect_to(@svc.host, @svc.port, @svc.timeout)
28
28
 
29
29
  if @req.options
30
30
  if @req.options[:cache] && @req.options[:cache][0] == :validation
@@ -44,6 +44,22 @@ module BERTRPC
44
44
  bert_response
45
45
  rescue Errno::ECONNREFUSED
46
46
  raise ConnectionError.new("Unable to connect to #{@svc.host}:#{@svc.port}")
47
+ rescue Timeout::Error
48
+ raise ReadTimeoutError.new(@svc.host, @svc.port, @svc.timeout)
49
+ end
50
+
51
+ # Creates a socket object which does speedy, non-blocking reads
52
+ # and can perform reliable read timeouts.
53
+ #
54
+ # Raises Timeout::Error on timeout.
55
+ #
56
+ # +host+ String address of the target TCP server
57
+ # +port+ Integer port of the target TCP server
58
+ # +timeout+ Optional Integer (in seconds) of the read timeout
59
+ def connect_to(host, port, timeout = nil)
60
+ io = BufferedIO.new(TCPSocket.new(host, port))
61
+ io.read_timeout = timeout
62
+ io
47
63
  end
48
64
  end
49
- end
65
+ end
@@ -0,0 +1,28 @@
1
+ module BERTRPC
2
+ # Taken with love from memcache-client.
3
+ #
4
+ # See http://is.gd/4CWRA for the code and
5
+ # http://is.gd/4CYde for the discussion.
6
+ class BufferedIO < Net::BufferedIO # :nodoc:
7
+ BUFSIZE = 1024 * 16
8
+
9
+ if RUBY_VERSION < '1.9.1'
10
+ def rbuf_fill
11
+ begin
12
+ @rbuf << @io.read_nonblock(BUFSIZE)
13
+ rescue Errno::EWOULDBLOCK
14
+ retry unless @read_timeout
15
+ if IO.select([@io], nil, nil, @read_timeout)
16
+ retry
17
+ else
18
+ raise Timeout::Error, 'IO timeout'
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ def setsockopt(*args)
25
+ @io.setsockopt(*args)
26
+ end
27
+ end
28
+ end
@@ -28,6 +28,16 @@ module BERTRPC
28
28
 
29
29
  end
30
30
 
31
+ # Raised when we don't get a response from a server in a timely
32
+ # manner. This typically occurs in spite of a successful connection.
33
+ class ReadTimeoutError < BERTRPCError
34
+ attr_reader :host, :port, :timeout
35
+ def initialize(host, port, timeout)
36
+ @host, @port, @timeout = host, port, timeout
37
+ super("No response from #{host}:#{port} in #{timeout}s")
38
+ end
39
+ end
40
+
31
41
  class ProtocolError < BERTRPCError
32
42
  NO_HEADER = [0, "Unable to read length header from server."]
33
43
  NO_DATA = [1, "Unable to read data from server."]
@@ -48,4 +58,4 @@ module BERTRPC
48
58
  class InvalidOption < BERTRPCError
49
59
 
50
60
  end
51
- end
61
+ end
@@ -1,10 +1,11 @@
1
1
  module BERTRPC
2
2
  class Service
3
- attr_accessor :host, :port
3
+ attr_accessor :host, :port, :timeout
4
4
 
5
- def initialize(host, port)
5
+ def initialize(host, port, timeout = nil)
6
6
  @host = host
7
7
  @port = port
8
+ @timeout = timeout
8
9
  end
9
10
 
10
11
  def call(options = nil)
@@ -31,4 +32,4 @@ module BERTRPC
31
32
  end
32
33
  end
33
34
  end
34
- end
35
+ end
data/lib/bertrpc.rb CHANGED
@@ -1,9 +1,11 @@
1
1
  require 'bert'
2
2
  require 'socket'
3
+ require 'net/protocol'
3
4
 
4
5
  require 'bertrpc/service'
5
6
  require 'bertrpc/request'
6
7
  require 'bertrpc/mod'
7
8
  require 'bertrpc/encodes'
8
9
  require 'bertrpc/action'
9
- require 'bertrpc/errors'
10
+ require 'bertrpc/errors'
11
+ require 'bertrpc/buffered_io'
data/test/action_test.rb CHANGED
@@ -49,7 +49,7 @@ class ActionTest < Test::Unit::TestCase
49
49
  @req = @svc.call
50
50
  @call = BERTRPC::Action.new(@svc, @req, :mymod, :myfun, [])
51
51
  end
52
-
52
+
53
53
  should "read and write BERT-Ps from the socket" do
54
54
  io = stub()
55
55
  io.expects(:write).with("\000\000\000\003")
@@ -57,7 +57,7 @@ class ActionTest < Test::Unit::TestCase
57
57
  io.expects(:read).with(4).returns("\000\000\000\003")
58
58
  io.expects(:read).with(3).returns("bar")
59
59
  io.expects(:close)
60
- TCPSocket.expects(:new).returns(io)
60
+ @call.expects(:connect_to).returns(io)
61
61
  assert_equal "bar", @call.transaction("foo")
62
62
  end
63
63
 
@@ -66,7 +66,7 @@ class ActionTest < Test::Unit::TestCase
66
66
  io.expects(:write).with("\000\000\000\003")
67
67
  io.expects(:write).with("foo")
68
68
  io.expects(:read).with(4).returns(nil)
69
- TCPSocket.expects(:new).returns(io)
69
+ @call.expects(:connect_to).returns(io)
70
70
  begin
71
71
  @call.transaction("foo")
72
72
  fail "Should have thrown an error"
@@ -74,14 +74,14 @@ class ActionTest < Test::Unit::TestCase
74
74
  assert_equal 0, e.code
75
75
  end
76
76
  end
77
-
77
+
78
78
  should "raise a ProtocolError when the data is invalid" do
79
79
  io = stub()
80
80
  io.expects(:write).with("\000\000\000\003")
81
81
  io.expects(:write).with("foo")
82
82
  io.expects(:read).with(4).returns("\000\000\000\003")
83
83
  io.expects(:read).with(3).returns(nil)
84
- TCPSocket.expects(:new).returns(io)
84
+ @call.expects(:connect_to).returns(io)
85
85
  begin
86
86
  @call.transaction("foo")
87
87
  fail "Should have thrown an error"
@@ -89,6 +89,22 @@ class ActionTest < Test::Unit::TestCase
89
89
  assert_equal 1, e.code
90
90
  end
91
91
  end
92
+
93
+ should "raise a ReadTimeoutError when the connection times out" do
94
+ io = stub()
95
+ io.expects(:write).with("\000\000\000\003")
96
+ io.expects(:write).with("foo")
97
+ io.expects(:read).with(4).raises(Timeout::Error)
98
+ @call.expects(:connect_to).returns(io)
99
+ begin
100
+ @call.transaction("foo")
101
+ fail "Should have thrown an error"
102
+ rescue BERTRPC::ReadTimeoutError => e
103
+ assert_equal 0, e.code
104
+ assert_equal 'localhost', e.host
105
+ assert_equal 9941, e.port
106
+ end
107
+ end
92
108
  end
93
109
  end
94
- end
110
+ end
data/test/service_test.rb CHANGED
@@ -2,10 +2,15 @@ require 'test_helper'
2
2
 
3
3
  class ServiceTest < Test::Unit::TestCase
4
4
  context "A Service" do
5
- should "be created with host and port" do
5
+ should "be creatable with host and port" do
6
6
  svc = BERTRPC::Service.new('localhost', 9941)
7
7
  assert svc.is_a?(BERTRPC::Service)
8
8
  end
9
+
10
+ should "be creatable with host, port, and timeout" do
11
+ svc = BERTRPC::Service.new('localhost', 9941, 5)
12
+ assert svc.is_a?(BERTRPC::Service)
13
+ end
9
14
  end
10
15
 
11
16
  context "A Service Instance's" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bertrpc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tom Preston-Werner
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-10-08 00:00:00 -07:00
12
+ date: 2009-11-26 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -52,6 +52,7 @@ files:
52
52
  - bertrpc.gemspec
53
53
  - lib/bertrpc.rb
54
54
  - lib/bertrpc/action.rb
55
+ - lib/bertrpc/buffered_io.rb
55
56
  - lib/bertrpc/encodes.rb
56
57
  - lib/bertrpc/errors.rb
57
58
  - lib/bertrpc/mod.rb