sanford-protocol 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +12 -0
- data/lib/sanford-protocol/connection.rb +29 -13
- data/lib/sanford-protocol/version.rb +1 -1
- data/test/unit/connection_tests.rb +15 -0
- metadata +3 -3
data/README.md
CHANGED
@@ -110,6 +110,18 @@ connection.write(outgoing_data)
|
|
110
110
|
|
111
111
|
For incoming messages, it reads them off the socket, validate them, and return the decoded body data. For outgoing messages, it encodes the message body from given data, adds the appropiate message headers, and writes the message to the socket.
|
112
112
|
|
113
|
+
#### Timeout
|
114
|
+
|
115
|
+
When reading data from a connection, you can optionally pass a timeout value. If given, the connection will block and wait until data is ready to be read. If a timeout occurs, the connection will raise `TimeoutError`.
|
116
|
+
|
117
|
+
```ruby
|
118
|
+
begin
|
119
|
+
connection.read(10) # timeout after waiting on data for 10s
|
120
|
+
rescue Sanford::Protocol::TimeoutError => err
|
121
|
+
puts "timeout - so sad :("
|
122
|
+
end
|
123
|
+
```
|
124
|
+
|
113
125
|
### Requests And Responses
|
114
126
|
|
115
127
|
Request and response objects have helpers for sending and receiving data using a connection.
|
@@ -19,7 +19,8 @@ module Sanford::Protocol
|
|
19
19
|
# | msg version | msg body size | msg body |
|
20
20
|
# |-----------------|-----------------|----------------------|
|
21
21
|
|
22
|
-
def read
|
22
|
+
def read(timeout=nil)
|
23
|
+
wait_for_data(timeout) if timeout
|
23
24
|
MsgVersion.new{ @socket.read msg_version.bytesize }.validate!
|
24
25
|
size = MsgSize.new{ @socket.decode msg_size, msg_size.bytes }.validate!.value
|
25
26
|
return MsgBody.new{ @socket.decode msg_body, size }.validate!.value
|
@@ -32,23 +33,38 @@ module Sanford::Protocol
|
|
32
33
|
@socket.write(msg_version, size, body)
|
33
34
|
end
|
34
35
|
|
35
|
-
|
36
|
-
def decode(handler, num_bytes)
|
37
|
-
handler.decode(read(num_bytes))
|
38
|
-
end
|
36
|
+
private
|
39
37
|
|
40
|
-
|
41
|
-
|
38
|
+
def wait_for_data(timeout)
|
39
|
+
if IO.select([ @socket.tcp_socket ], nil, nil, timeout).nil?
|
40
|
+
raise TimeoutError.new(timeout)
|
42
41
|
end
|
42
|
+
end
|
43
43
|
|
44
|
-
|
45
|
-
tcp_socket.recvfrom(number_of_bytes).first
|
46
|
-
end
|
44
|
+
end
|
47
45
|
|
48
|
-
|
49
|
-
|
50
|
-
|
46
|
+
class Socket < Struct.new(:tcp_socket)
|
47
|
+
def decode(handler, num_bytes)
|
48
|
+
handler.decode(read(num_bytes))
|
49
|
+
end
|
50
|
+
|
51
|
+
def encode(handler, data)
|
52
|
+
handler.encode data
|
51
53
|
end
|
52
54
|
|
55
|
+
def read(number_of_bytes)
|
56
|
+
tcp_socket.recvfrom(number_of_bytes).first
|
57
|
+
end
|
58
|
+
|
59
|
+
def write(*binary_strings)
|
60
|
+
tcp_socket.send(binary_strings.join, 0)
|
61
|
+
end
|
53
62
|
end
|
63
|
+
|
64
|
+
class TimeoutError < RuntimeError
|
65
|
+
def initialize(timeout)
|
66
|
+
super "Timed out waiting for data to read (#{timeout}s)."
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
54
70
|
end
|
@@ -24,4 +24,19 @@ class Sanford::Protocol::Connection
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
+
class TimeoutTests < BaseTests
|
28
|
+
desc "when timing out on a read"
|
29
|
+
setup do
|
30
|
+
IO.stubs(:select).returns(nil) # mock IO.select behavior when it times out
|
31
|
+
end
|
32
|
+
teardown do
|
33
|
+
IO.unstub(:select)
|
34
|
+
end
|
35
|
+
|
36
|
+
should "raise `TimeoutError` if given a timeout value" do
|
37
|
+
assert_raises(Sanford::Protocol::TimeoutError) { subject.read(1) }
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
27
42
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sanford-protocol
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 15
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 4
|
9
9
|
- 0
|
10
|
-
version: 0.
|
10
|
+
version: 0.4.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Collin Redding
|