poseidon 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3d5bb4f86848c948a0395678c366213e43a69129
4
- data.tar.gz: f9ef623ef716cfe2197c55cb50031c41eb45f785
3
+ metadata.gz: 4c4852d5b615cd1fe50528b0136602756087d0db
4
+ data.tar.gz: 2172c5cd70c8047cb0b0bdd171d5f9ed5cb82b73
5
5
  SHA512:
6
- metadata.gz: ff293ca0f11064c40e3411a57ab8df729013524cf2afb9c2dd018153457f34e200bd8fdfd6ee32aaf4a7af3fa2ce6e19447f9a70275c8bda8332285180e2b509
7
- data.tar.gz: 4c4ab22ed0aa8d84cdfce68051788c0cdfb5fb60d468c64740285af4bda8b217473c11e1974aaa4c4220f4fe6ca7542e8c9a71de5e081a8d2e33aa83323bb91f
6
+ metadata.gz: 3949ab96ce033255e31bc588db0f0895c6a72a91d9bfb56137995f0d5f52bc467dfa660359d440fddca89fe64fd3f6af7a2b28f2476698ba35319f999358a721
7
+ data.tar.gz: 2348e329e244a3b4a777e8635143d33ec591c10ee411f40aa69a629487643585e8b303c13f120d51e85a2dde13f5dea5b0cb3290b152e619d3fa07dc6f4769d4
data/CHANGES.md CHANGED
@@ -1,3 +1,8 @@
1
+ # 0.0.4
2
+
3
+ * Don't truncate UTF8 Messages [GH-18]
4
+ * Gracefully handle truncated fetch reponses [GH-19]
5
+
1
6
  # 0.0.3
2
7
 
3
8
  * Better distribute messages across partitions.
@@ -115,7 +115,7 @@ module Poseidon
115
115
  def send_request(request)
116
116
  buffer = Protocol::RequestBuffer.new
117
117
  request.write(buffer)
118
- @socket.write([buffer.to_s.size].pack("N") + buffer.to_s)
118
+ @socket.write([buffer.to_s.bytesize].pack("N") + buffer.to_s)
119
119
  rescue Errno::EPIPE, Errno::ECONNRESET
120
120
  @socket = nil
121
121
  raise ConnectionFailedError
@@ -82,9 +82,13 @@ module Poseidon
82
82
  #
83
83
  # @api public
84
84
  def fetch(options = {})
85
- fetch_max_wait = options[:max_wait] || max_wait_ms
86
- fetch_max_bytes = options[:max_bytes] || max_bytes
87
- fetch_min_bytes = options[:min_bytes] || min_bytes
85
+ fetch_max_wait = options.delete(:max_wait) || max_wait_ms
86
+ fetch_max_bytes = options.delete(:max_bytes) || max_bytes
87
+ fetch_min_bytes = options.delete(:min_bytes) || min_bytes
88
+
89
+ if options.keys.any?
90
+ raise ArgumentError, "Unknown options: #{options.keys.inspect}"
91
+ end
88
92
 
89
93
  topic_fetches = build_topic_fetch_request(fetch_max_bytes)
90
94
  fetch_response = @connection.fetch(fetch_max_wait, fetch_min_bytes, topic_fetches)
@@ -158,6 +158,11 @@ module Poseidon
158
158
 
159
159
  def read(buffer)
160
160
  if self.class.prepend_size?
161
+ if !have_header?(buffer)
162
+ @truncated = true
163
+ return
164
+ end
165
+
161
166
  @size = buffer.int32
162
167
 
163
168
  if self.class.prepend_crc32?
@@ -171,7 +176,6 @@ module Poseidon
171
176
  expected_bytes_remaining = @size
172
177
  end
173
178
 
174
-
175
179
  if self.class.truncatable? && expected_bytes_remaining > buffer.bytes_remaining
176
180
  @truncated = true
177
181
  return
@@ -190,6 +194,20 @@ module Poseidon
190
194
  end
191
195
  end
192
196
 
197
+ def have_header?(buffer)
198
+ if self.class.truncatable?
199
+ if self.class.prepend_crc32?
200
+ header_bytes = 8
201
+ else
202
+ header_bytes = 4
203
+ end
204
+
205
+ return buffer.bytes_remaining >= header_bytes
206
+ else
207
+ return true
208
+ end
209
+ end
210
+
193
211
  def read_member(buffer, member)
194
212
  case type = type_map[member]
195
213
  when Array
@@ -40,7 +40,7 @@ module Poseidon
40
40
  if string.nil?
41
41
  int16(-1)
42
42
  else
43
- int16(string.size)
43
+ int16(string.bytesize)
44
44
  append(string)
45
45
  end
46
46
  end
@@ -49,13 +49,13 @@ module Poseidon
49
49
  if string.nil?
50
50
  int32(-1)
51
51
  else
52
- int32(string.size)
52
+ int32(string.bytesize)
53
53
  append(string)
54
54
  end
55
55
  end
56
56
 
57
57
  def prepend_crc32
58
- checksum_pos = @s.size
58
+ checksum_pos = @s.bytesize
59
59
  @s += " "
60
60
  yield
61
61
  @s[checksum_pos] = [Zlib::crc32(@s[(checksum_pos+1)..-1])].pack("N")
@@ -63,10 +63,10 @@ module Poseidon
63
63
  end
64
64
 
65
65
  def prepend_size
66
- size_pos = @s.size
66
+ size_pos = @s.bytesize
67
67
  @s += " "
68
68
  yield
69
- @s[size_pos] = [(@s.size-1) - size_pos].pack("N")
69
+ @s[size_pos] = [(@s.bytesize-1) - size_pos].pack("N")
70
70
  nil
71
71
  end
72
72
 
@@ -57,11 +57,11 @@ module Poseidon
57
57
  end
58
58
 
59
59
  def bytes_remaining
60
- @s.size - @pos
60
+ @s.bytesize - @pos
61
61
  end
62
62
 
63
63
  def eof?
64
- @pos == @s.size
64
+ @pos == @s.bytesize
65
65
  end
66
66
 
67
67
  def to_s
@@ -1,4 +1,4 @@
1
1
  module Poseidon
2
2
  # Unstable! API May Change!
3
- VERSION = "0.0.3"
3
+ VERSION = "0.0.4"
4
4
  end
@@ -0,0 +1,44 @@
1
+ require 'integration/simple/spec_helper'
2
+
3
+ describe "truncated messages" do
4
+ before(:all) do
5
+ @s1 = "a" * 335
6
+ @s2 = "b" * 338
7
+
8
+ @producer = Producer.new(["localhost:9092"],
9
+ "test_client",
10
+ :type => :sync)
11
+
12
+ @producer.send_messages([Message.new(:topic => 'test_max_bytes', :value => @s1), Message.new(:topic => 'test_max_bytes', :value => @s2)])
13
+ end
14
+
15
+ it "correctly handles max_byte lengths smallert than a message" do
16
+ 0.upto(360) do |n|
17
+ consumer = PartitionConsumer.new("test_consumer", "localhost", 9092,
18
+ "test_max_bytes", 0, :earliest_offset)
19
+ expect(consumer.fetch(:max_bytes => n)).to eq([])
20
+ end
21
+ end
22
+
23
+ it "correctly handles max_byte lengths that should return a single message" do
24
+ 361.upto(724) do |n|
25
+ consumer = PartitionConsumer.new("test_consumer", "localhost", 9092,
26
+ "test_max_bytes", 0, :earliest_offset)
27
+
28
+ messages = consumer.fetch(:max_bytes => n)
29
+ expect(messages.size).to eq(1)
30
+ expect(messages.first.value).to eq(@s1)
31
+ end
32
+ end
33
+
34
+ it "correctly handles max_byte lengths that should return two messages" do
35
+ 725.upto(1000) do |n|
36
+ consumer = PartitionConsumer.new("test_consumer", "localhost", 9092,
37
+ "test_max_bytes", 0, :earliest_offset)
38
+
39
+ messages = consumer.fetch(:max_bytes => n)
40
+ expect(messages.size).to eq(2)
41
+ expect(messages.map(&:value)).to eq([@s1, @s2])
42
+ end
43
+ end
44
+ end
@@ -24,9 +24,13 @@ describe MessageConductor do
24
24
 
25
25
  context "for unkeyed messages" do
26
26
  it "round robins which partition the message should go to" do
27
- [0,1,0,1].each do |destination|
28
- expect(@mc.destination("test").first).to eq(destination)
27
+ destinations = 4.times.map do
28
+ @mc.destination("test").first
29
29
  end
30
+
31
+ first = [destinations[0], destinations[2]]
32
+ second = [destinations[1], destinations[3]]
33
+ expect([first.uniq, second.uniq].sort).to eq([[0],[1]])
30
34
  end
31
35
 
32
36
  context "unknown topic" do
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
  require 'spec_helper'
2
3
 
3
4
  describe Message do
@@ -87,6 +88,22 @@ describe Message do
87
88
  end
88
89
  end
89
90
 
91
+ context "utf8 string with multibyte characters" do
92
+ it "roundtrips correctly" do
93
+ s = "the µ is two bytes"
94
+ m = Message.new(:value => s,
95
+ :key => "key",
96
+ :topic => "topic")
97
+
98
+ req_buf = Protocol::RequestBuffer.new
99
+ m.write(req_buf)
100
+
101
+ resp_buf = Protocol::ResponseBuffer.new(req_buf.to_s)
102
+
103
+ expect(Message.read(resp_buf).value).to eq(s.force_encoding("ASCII-8BIT"))
104
+ end
105
+ end
106
+
90
107
  context "frozen string for value" do
91
108
  it "builds the payload without error" do
92
109
  s = "asdffasdf".freeze
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: poseidon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bob Potter
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-09-25 00:00:00.000000000 Z
11
+ date: 2013-09-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -121,6 +121,7 @@ files:
121
121
  - spec/integration/simple/multiple_brokers_spec.rb
122
122
  - spec/integration/simple/simple_producer_and_consumer_spec.rb
123
123
  - spec/integration/simple/spec_helper.rb
124
+ - spec/integration/simple/truncated_messages_spec.rb
124
125
  - spec/integration/simple/unavailable_broker_spec.rb
125
126
  - spec/spec_helper.rb
126
127
  - spec/test_cluster.rb
@@ -176,6 +177,7 @@ test_files:
176
177
  - spec/integration/simple/multiple_brokers_spec.rb
177
178
  - spec/integration/simple/simple_producer_and_consumer_spec.rb
178
179
  - spec/integration/simple/spec_helper.rb
180
+ - spec/integration/simple/truncated_messages_spec.rb
179
181
  - spec/integration/simple/unavailable_broker_spec.rb
180
182
  - spec/spec_helper.rb
181
183
  - spec/test_cluster.rb