kafka-rb 0.0.6 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE CHANGED
@@ -1,20 +1,202 @@
1
- Copyright (c) 2010 Alejandro Crosa
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining
4
- a copy of this software and associated documentation files (the
5
- "Software"), to deal in the Software without restriction, including
6
- without limitation the rights to use, copy, modify, merge, publish,
7
- distribute, sublicense, and/or sell copies of the Software, and to
8
- permit persons to whom the Software is furnished to do so, subject to
9
- the following conditions:
10
-
11
- The above copyright notice and this permission notice shall be
12
- included in all copies or substantial portions of the Software.
13
-
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
178
+
179
+ APPENDIX: How to apply the Apache License to your work.
180
+
181
+ To apply the Apache License to your work, attach the following
182
+ boilerplate notice, with the fields enclosed by brackets "[]"
183
+ replaced with your own identifying information. (Don't include
184
+ the brackets!) The text should be enclosed in the appropriate
185
+ comment syntax for the file format. We also recommend that a
186
+ file or class name and description of purpose be included on the
187
+ same "printed page" as the copyright notice for easier
188
+ identification within third-party archives.
189
+
190
+ Copyright [yyyy] [name of copyright owner]
191
+
192
+ Licensed under the Apache License, Version 2.0 (the "License");
193
+ you may not use this file except in compliance with the License.
194
+ You may obtain a copy of the License at
195
+
196
+ http://www.apache.org/licenses/LICENSE-2.0
197
+
198
+ Unless required by applicable law or agreed to in writing, software
199
+ distributed under the License is distributed on an "AS IS" BASIS,
200
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
+ See the License for the specific language governing permissions and
202
+ limitations under the License.
data/README.md CHANGED
@@ -1,13 +1,19 @@
1
1
  # kafka-rb
2
- kafka-rb allows you to produce messages to the Kafka distributed publish/subscribe messaging service.
2
+ kafka-rb allows you to produce and consume messages to / from the Kafka distributed messaging service.
3
+ This is an improved version of the original Ruby client written by Alejandro Crosa,
4
+ and is used in production at wooga.
3
5
 
4
6
  ## Requirements
5
- You need to have access to your Kafka instance and be able to connect through TCP. You can obtain a copy and instructions on how to setup kafka at https://github.com/kafka-dev/kafka
7
+ You need to have access to your Kafka instance and be able to connect through TCP.
8
+ You can obtain a copy and instructions on how to setup kafka at http://incubator.apache.org/kafka/
9
+
6
10
 
7
11
  ## Installation
8
- sudo gem install kafka-rb
9
12
 
10
- (the code works fine with JRuby, Ruby 1.8x and Ruby 1.9.x)
13
+ sudo gem install wooga-kafka-rb
14
+
15
+ (should work fine with JRuby, Ruby 1.8 and 1.9)
16
+
11
17
 
12
18
  ## Usage
13
19
 
@@ -55,8 +61,8 @@ sudo gem install kafka-rb
55
61
  end
56
62
 
57
63
 
58
- Contact for questions
59
-
64
+ ## Questions?
60
65
  alejandrocrosa at(@) gmail.com
61
-
62
66
  http://twitter.com/alejandrocrosa
67
+
68
+ tim.lossen@wooga.net
data/Rakefile CHANGED
@@ -1,41 +1,52 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright ownership.
4
+ # The ASF licenses this file to You under the Apache License, Version 2.0
5
+ # (the "License"); you may not use this file except in compliance with
6
+ # the License. You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
1
16
  require 'rubygems'
2
17
  require 'rake/gempackagetask'
3
18
  require 'rubygems/specification'
4
19
  require 'date'
5
20
  require 'rspec/core/rake_task'
6
21
 
7
- GEM = 'kafka-rb'
8
- GEM_NAME = 'Kafka Client'
9
- GEM_VERSION = '0.0.5'
10
- AUTHORS = ['Alejandro Crosa']
11
- EMAIL = "alejandrocrosa@gmail.com"
12
- HOMEPAGE = "http://github.com/acrosa/kafka-rb"
13
- SUMMARY = "A Ruby client for the Kafka distributed publish/subscribe messaging service"
14
- DESCRIPTION = "kafka-rb allows you to produce and consume messages using the Kafka distributed publish/subscribe messaging service."
15
-
16
22
  spec = Gem::Specification.new do |s|
17
- s.name = GEM
18
- s.version = GEM_VERSION
19
- s.platform = Gem::Platform::RUBY
20
- s.has_rdoc = true
23
+ s.name = %q{kafka-rb}
24
+ s.version = "0.0.8"
25
+
26
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
27
+ s.authors = ["Alejandro Crosa", "Stefan Mees", "Tim Lossen"]
28
+ s.autorequire = %q{kafka-rb}
29
+ s.date = Time.now.strftime("%Y-%m-%d")
30
+ s.description = %q{kafka-rb allows you to produce and consume messages using the Kafka distributed publish/subscribe messaging service.}
21
31
  s.extra_rdoc_files = ["LICENSE"]
22
- s.summary = SUMMARY
23
- s.description = DESCRIPTION
24
- s.authors = AUTHORS
25
- s.email = EMAIL
26
- s.homepage = HOMEPAGE
27
- s.add_development_dependency "rspec"
28
- s.require_path = 'lib'
29
- s.autorequire = GEM
30
- s.files = %w(LICENSE README.md Rakefile) + Dir.glob("{lib,tasks,spec}/**/*")
31
- end
32
+ s.files = ["LICENSE", "README.md", "Rakefile", "lib/kafka", "lib/kafka/batch.rb", "lib/kafka/consumer.rb", "lib/kafka/io.rb", "lib/kafka/message.rb", "lib/kafka/producer.rb", "lib/kafka/request_type.rb", "lib/kafka/error_codes.rb", "lib/kafka.rb", "spec/batch_spec.rb", "spec/consumer_spec.rb", "spec/io_spec.rb", "spec/kafka_spec.rb", "spec/message_spec.rb", "spec/producer_spec.rb", "spec/spec_helper.rb"]
33
+ s.homepage = %q{http://github.com/wooga/kafka-rb}
34
+ s.require_paths = ["lib"]
35
+ s.rubygems_version = %q{1.3.7}
36
+ s.summary = %q{A Ruby client for the Kafka distributed publish/subscribe messaging service}
32
37
 
33
- task :default => :spec
38
+ if s.respond_to? :specification_version then
39
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
40
+ s.specification_version = 3
34
41
 
35
- desc "Run specs"
36
- RSpec::Core::RakeTask.new do |t|
37
- t.pattern = FileList['spec/**/*_spec.rb']
38
- t.rspec_opts = %w(-fs --color)
42
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
43
+ s.add_development_dependency(%q<rspec>, [">= 0"])
44
+ else
45
+ s.add_dependency(%q<rspec>, [">= 0"])
46
+ end
47
+ else
48
+ s.add_dependency(%q<rspec>, [">= 0"])
49
+ end
39
50
  end
40
51
 
41
52
  Rake::GemPackageTask.new(spec) do |pkg|
@@ -44,14 +55,7 @@ end
44
55
 
45
56
  desc "install the gem locally"
46
57
  task :install => [:package] do
47
- sh %{sudo gem install pkg/#{GEM_NAME}-#{GEM_VERSION}}
48
- end
49
-
50
- desc "create a gemspec file"
51
- task :make_spec do
52
- File.open("#{GEM}.gemspec", "w") do |file|
53
- file.puts spec.to_ruby
54
- end
58
+ sh %{sudo gem install pkg/#{GEM}-#{GEM_VERSION}}
55
59
  end
56
60
 
57
61
  desc "Run all examples with RCov"
@@ -59,3 +63,12 @@ RSpec::Core::RakeTask.new(:rcov) do |t|
59
63
  t.pattern = FileList['spec/**/*_spec.rb']
60
64
  t.rcov = true
61
65
  end
66
+
67
+ desc "Run specs"
68
+ RSpec::Core::RakeTask.new do |t|
69
+ t.pattern = FileList['spec/**/*_spec.rb']
70
+ t.rspec_opts = %w(-fs --color)
71
+ end
72
+
73
+ task :default => :spec
74
+
data/lib/kafka/batch.rb CHANGED
@@ -1,3 +1,18 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright ownership.
4
+ # The ASF licenses this file to You under the Apache License, Version 2.0
5
+ # (the "License"); you may not use this file except in compliance with
6
+ # the License. You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
1
16
  module Kafka
2
17
  class Batch
3
18
  attr_accessor :messages
@@ -1,76 +1,105 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright ownership.
4
+ # The ASF licenses this file to You under the Apache License, Version 2.0
5
+ # (the "License"); you may not use this file except in compliance with
6
+ # the License. You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
1
16
  module Kafka
2
17
  class Consumer
3
18
 
4
19
  include Kafka::IO
5
20
 
6
- CONSUME_REQUEST_TYPE = Kafka::RequestType::FETCH
7
- MAX_SIZE = 1048576 # 1 MB
8
- DEFAULT_POLLING_INTERVAL = 2 # 2 seconds
21
+ MAX_SIZE = 1024 * 1024 # 1 megabyte
22
+ DEFAULT_POLLING_INTERVAL = 2 # 2 seconds
23
+ MAX_OFFSETS = 1
24
+ LATEST_OFFSET = -1
25
+ EARLIEST_OFFSET = -2
9
26
 
10
27
  attr_accessor :topic, :partition, :offset, :max_size, :request_type, :polling
11
28
 
12
29
  def initialize(options = {})
13
- self.topic = options[:topic] || "test"
14
- self.partition = options[:partition] || 0
15
- self.host = options[:host] || "localhost"
16
- self.port = options[:port] || 9092
17
- self.offset = options[:offset] || 0
18
- self.max_size = options[:max_size] || MAX_SIZE
19
- self.request_type = options[:request_type] || CONSUME_REQUEST_TYPE
20
- self.polling = options[:polling] || DEFAULT_POLLING_INTERVAL
21
- self.connect(self.host, self.port)
30
+ self.topic = options[:topic] || "test"
31
+ self.partition = options[:partition] || 0
32
+ self.host = options[:host] || "localhost"
33
+ self.port = options[:port] || 9092
34
+ self.offset = options[:offset]
35
+ self.max_size = options[:max_size] || MAX_SIZE
36
+ self.polling = options[:polling] || DEFAULT_POLLING_INTERVAL
37
+ connect(host, port)
22
38
  end
23
39
 
24
- # REQUEST TYPE ID + TOPIC LENGTH + TOPIC + PARTITION + OFFSET + MAX SIZE
25
- def request_size
26
- 2 + 2 + topic.length + 4 + 8 + 4
40
+ def loop(&block)
41
+ messages = []
42
+ while (true) do
43
+ messages = consume
44
+ block.call(messages) if messages && !messages.empty?
45
+ sleep(polling)
46
+ end
27
47
  end
28
48
 
29
- def encode_request_size
30
- [self.request_size].pack("N")
49
+ def consume
50
+ self.offset ||= fetch_latest_offset
51
+ send_consume_request
52
+ data = read_data_response
53
+ parse_message_set_from(data)
54
+ rescue SocketError
55
+ nil
31
56
  end
32
57
 
33
- def encode_request(request_type, topic, partition, offset, max_size)
34
- request_type = [request_type].pack("n")
35
- topic = [topic.length].pack('n') + topic
36
- partition = [partition].pack("N")
37
- offset = [offset].pack("Q").reverse # DIY 64bit big endian integer
38
- max_size = [max_size].pack("N")
58
+ def fetch_latest_offset
59
+ send_offsets_request
60
+ read_offsets_response
61
+ end
39
62
 
40
- request_type + topic + partition + offset + max_size
63
+ def send_offsets_request
64
+ write(encoded_request_size)
65
+ write(encode_request(Kafka::RequestType::OFFSETS, topic, partition, LATEST_OFFSET, MAX_OFFSETS))
41
66
  end
42
67
 
43
- def consume
44
- self.send_consume_request # request data
45
- data = self.read_data_response # read data response
46
- self.parse_message_set_from(data) # parse message set
68
+ def read_offsets_response
69
+ read_data_response[4,8].reverse.unpack('q')[0]
47
70
  end
48
71
 
49
- def loop(&block)
50
- messages = []
51
- while(true) do
52
- messages = self.consume
53
- block.call(messages) if messages && !messages.empty?
54
- sleep(self.polling)
55
- end
72
+ def send_consume_request
73
+ write(encoded_request_size)
74
+ write(encode_request(Kafka::RequestType::FETCH, topic, partition, offset, max_size))
56
75
  end
57
76
 
58
77
  def read_data_response
59
- data_length = self.socket.read(4).unpack("N").shift # read length
60
- data = self.socket.read(data_length) # read message set
61
- data[2, data.length] # we start with a 2 byte offset
78
+ data_length = read(4).unpack("N").shift
79
+ data = read(data_length)
80
+ # TODO: inspect error code instead of skipping it
81
+ data[2, data.length]
62
82
  end
63
83
 
64
- def send_consume_request
65
- self.write(self.encode_request_size) # write request_size
66
- self.write(self.encode_request(self.request_type, self.topic, self.partition, self.offset, self.max_size)) # write request
84
+ def encoded_request_size
85
+ size = 2 + 2 + topic.length + 4 + 8 + 4
86
+ [size].pack("N")
87
+ end
88
+
89
+ def encode_request(request_type, topic, partition, offset, max_size)
90
+ request_type = [request_type].pack("n")
91
+ topic = [topic.length].pack('n') + topic
92
+ partition = [partition].pack("N")
93
+ offset = [offset].pack("q").reverse # DIY 64bit big endian integer
94
+ max_size = [max_size].pack("N")
95
+ request_type + topic + partition + offset + max_size
67
96
  end
68
97
 
69
98
  def parse_message_set_from(data)
70
99
  messages = []
71
100
  processed = 0
72
101
  length = data.length - 4
73
- while(processed <= length) do
102
+ while (processed <= length) do
74
103
  message_size = data[processed, 4].unpack("N").shift + 4
75
104
  message_data = data[processed, message_size]
76
105
  break unless message_data.size == message_size
@@ -80,5 +109,6 @@ module Kafka
80
109
  self.offset += processed
81
110
  messages
82
111
  end
112
+
83
113
  end
84
114
  end
@@ -0,0 +1,35 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright ownership.
4
+ # The ASF licenses this file to You under the Apache License, Version 2.0
5
+ # (the "License"); you may not use this file except in compliance with
6
+ # the License. You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ module Kafka
16
+ module ErrorCodes
17
+ NO_ERROR = 0
18
+ OFFSET_OUT_OF_RANGE = 1
19
+ INVALID_MESSAGE_CODE = 2
20
+ WRONG_PARTITION_CODE = 3
21
+ INVALID_RETCH_SIZE_CODE = 4
22
+
23
+ STRINGS = {
24
+ 0 => 'No error',
25
+ 1 => 'Offset out of range',
26
+ 2 => 'Invalid message code',
27
+ 3 => 'Wrong partition code',
28
+ 4 => 'Invalid retch size code',
29
+ }
30
+
31
+ def self.to_s(code)
32
+ STRINGS[code] || 'Unknown error'
33
+ end
34
+ end
35
+ end
data/lib/kafka/io.rb CHANGED
@@ -1,3 +1,17 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright ownership.
4
+ # The ASF licenses this file to You under the Apache License, Version 2.0
5
+ # (the "License"); you may not use this file except in compliance with
6
+ # the License. You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
1
15
  module Kafka
2
16
  module IO
3
17
  attr_accessor :socket, :host, :port
@@ -10,8 +24,10 @@ module Kafka
10
24
  end
11
25
 
12
26
  def reconnect
27
+ self.socket = TCPSocket.new(self.host, self.port)
28
+ rescue
13
29
  self.disconnect
14
- self.socket = self.connect(self.host, self.port)
30
+ raise
15
31
  end
16
32
 
17
33
  def disconnect
@@ -19,21 +35,20 @@ module Kafka
19
35
  self.socket = nil
20
36
  end
21
37
 
38
+ def read(length)
39
+ self.socket.read(length) || raise(SocketError, "no data")
40
+ rescue
41
+ self.disconnect
42
+ raise SocketError, "cannot read: #{$!.message}"
43
+ end
44
+
22
45
  def write(data)
23
46
  self.reconnect unless self.socket
24
47
  self.socket.write(data)
25
- rescue Errno::ECONNRESET, Errno::EPIPE, Errno::ECONNABORTED
26
- self.reconnect
27
- self.socket.write(data) # retry
48
+ rescue
49
+ self.disconnect
50
+ raise SocketError, "cannot write: #{$!.message}"
28
51
  end
29
52
 
30
- def read(length)
31
- begin
32
- self.socket.read(length)
33
- rescue Errno::EAGAIN
34
- self.disconnect
35
- raise Errno::EAGAIN, "Timeout reading from the socket"
36
- end
37
- end
38
53
  end
39
54
  end
data/lib/kafka/message.rb CHANGED
@@ -1,3 +1,17 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright ownership.
4
+ # The ASF licenses this file to You under the Apache License, Version 2.0
5
+ # (the "License"); you may not use this file except in compliance with
6
+ # the License. You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
1
15
  module Kafka
2
16
 
3
17
  # A message. The format of an N byte message is the following:
@@ -1,3 +1,17 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright ownership.
4
+ # The ASF licenses this file to You under the Apache License, Version 2.0
5
+ # (the "License"); you may not use this file except in compliance with
6
+ # the License. You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
1
15
  module Kafka
2
16
  class Producer
3
17
 
@@ -1,3 +1,17 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright ownership.
4
+ # The ASF licenses this file to You under the Apache License, Version 2.0
5
+ # (the "License"); you may not use this file except in compliance with
6
+ # the License. You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
1
15
  module Kafka
2
16
  module RequestType
3
17
  PRODUCE = 0
data/lib/kafka.rb CHANGED
@@ -1,3 +1,17 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright ownership.
4
+ # The ASF licenses this file to You under the Apache License, Version 2.0
5
+ # (the "License"); you may not use this file except in compliance with
6
+ # the License. You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
1
15
  require 'socket'
2
16
  require 'zlib'
3
17
  if RUBY_VERSION[0,3] == "1.8"
@@ -6,10 +20,14 @@ end
6
20
 
7
21
  require File.join(File.dirname(__FILE__), "kafka", "io")
8
22
  require File.join(File.dirname(__FILE__), "kafka", "request_type")
23
+ require File.join(File.dirname(__FILE__), "kafka", "error_codes")
9
24
  require File.join(File.dirname(__FILE__), "kafka", "batch")
10
25
  require File.join(File.dirname(__FILE__), "kafka", "message")
11
26
  require File.join(File.dirname(__FILE__), "kafka", "producer")
12
27
  require File.join(File.dirname(__FILE__), "kafka", "consumer")
13
28
 
14
29
  module Kafka
30
+
31
+ class SocketError < RuntimeError; end
32
+
15
33
  end
data/spec/batch_spec.rb CHANGED
@@ -1,3 +1,17 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright ownership.
4
+ # The ASF licenses this file to You under the Apache License, Version 2.0
5
+ # (the "License"); you may not use this file except in compliance with
6
+ # the License. You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
1
15
  require File.dirname(__FILE__) + '/spec_helper'
2
16
 
3
17
  describe Batch do
@@ -1,3 +1,17 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright ownership.
4
+ # The ASF licenses this file to You under the Apache License, Version 2.0
5
+ # (the "License"); you may not use this file except in compliance with
6
+ # the License. You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
1
15
  require File.dirname(__FILE__) + '/spec_helper'
2
16
 
3
17
  describe Consumer do
@@ -5,13 +19,13 @@ describe Consumer do
5
19
  before(:each) do
6
20
  @mocked_socket = mock(TCPSocket)
7
21
  TCPSocket.stub!(:new).and_return(@mocked_socket) # don't use a real socket
8
- @consumer = Consumer.new
22
+ @consumer = Consumer.new(:offset => 0)
9
23
  end
10
24
 
11
25
  describe "Kafka Consumer" do
12
26
 
13
- it "should have a CONSUME_REQUEST_TYPE" do
14
- Consumer::CONSUME_REQUEST_TYPE.should eql(1)
27
+ it "should have a Kafka::RequestType::FETCH" do
28
+ Consumer::Kafka::RequestType::FETCH.should eql(1)
15
29
  @consumer.should respond_to(:request_type)
16
30
  end
17
31
 
@@ -40,8 +54,9 @@ describe Consumer do
40
54
  @consumer.port.should eql(9092)
41
55
  end
42
56
 
43
- it "should have a default offset, and be able to set it" do
44
- @consumer.offset.should eql(0)
57
+ it "should not have a default offset but be able to set it" do
58
+ @consumer = Consumer.new
59
+ @consumer.offset.should be_nil
45
60
  @consumer = Consumer.new({ :offset => 1111 })
46
61
  @consumer.offset.should eql(1111)
47
62
  end
@@ -52,25 +67,24 @@ describe Consumer do
52
67
  end
53
68
 
54
69
  it "should return the size of the request" do
55
- @consumer.request_size.should eql(24)
56
70
  @consumer.topic = "someothertopicname"
57
- @consumer.request_size.should eql(38)
58
- @consumer.encode_request_size.should eql([@consumer.request_size].pack("N"))
71
+ @consumer.encoded_request_size.should eql([38].pack("N"))
59
72
  end
60
73
 
61
74
  it "should encode a request to consume" do
62
- bytes = [Kafka::Consumer::CONSUME_REQUEST_TYPE].pack("n") + ["test".length].pack("n") + "test" + [0].pack("N") + [0].pack("L_") + [Kafka::Consumer::MAX_SIZE].pack("N")
63
- @consumer.encode_request(Kafka::Consumer::CONSUME_REQUEST_TYPE, "test", 0, 0, Kafka::Consumer::MAX_SIZE).should eql(bytes)
75
+ bytes = [Kafka::RequestType::FETCH].pack("n") + ["test".length].pack("n") + "test" + [0].pack("N") + [0].pack("q").reverse + [Kafka::Consumer::MAX_SIZE].pack("N")
76
+ @consumer.encode_request(Kafka::RequestType::FETCH, "test", 0, 0, Kafka::Consumer::MAX_SIZE).should eql(bytes)
64
77
  end
65
78
 
66
79
  it "should read the response data" do
67
- bytes = [8].pack("N") + [0].pack("C") + [1120192889].pack("N") + "ale"
68
- @mocked_socket.should_receive(:read).exactly(:twice).and_return(bytes)
69
- @consumer.read_data_response.should eql(bytes[2, bytes.length])
80
+ bytes = [0].pack("n") + [1120192889].pack("N") + "ale"
81
+ @mocked_socket.should_receive(:read).and_return([9].pack("N"))
82
+ @mocked_socket.should_receive(:read).with(9).and_return(bytes)
83
+ @consumer.read_data_response.should eql(bytes[2,7])
70
84
  end
71
85
 
72
86
  it "should send a consumer request" do
73
- @consumer.stub!(:encode_request_size).and_return(666)
87
+ @consumer.stub!(:encoded_request_size).and_return(666)
74
88
  @consumer.stub!(:encode_request).and_return("someencodedrequest")
75
89
  @consumer.should_receive(:write).with("someencodedrequest").exactly(:once).and_return(true)
76
90
  @consumer.should_receive(:write).with(666).exactly(:once).and_return(true)
@@ -93,7 +107,7 @@ describe Consumer do
93
107
  messages = @consumer.parse_message_set_from(bytes)
94
108
  messages.size.should eql(1)
95
109
  end
96
-
110
+
97
111
  it "should skip an incomplete message at the end of the response which has the same length as an empty message" do
98
112
  bytes = [8].pack("N") + [0].pack("C") + [1120192889].pack("N") + "ale"
99
113
  # incomplete message because payload is missing
@@ -101,7 +115,7 @@ describe Consumer do
101
115
  messages = @consumer.parse_message_set_from(bytes)
102
116
  messages.size.should eql(1)
103
117
  end
104
-
118
+
105
119
  it "should read empty messages correctly" do
106
120
  # empty message
107
121
  bytes = [5].pack("N") + [0].pack("C") + [0].pack("N") + ""
@@ -140,5 +154,26 @@ describe Consumer do
140
154
 
141
155
  executed_times.should eql(2)
142
156
  end
157
+
158
+ it "should fetch initial offset if no offset is given" do
159
+ @consumer = Consumer.new
160
+ @consumer.should_receive(:fetch_latest_offset).exactly(:once).and_return(1000)
161
+ @consumer.should_receive(:send_consume_request).and_return(true)
162
+ @consumer.should_receive(:read_data_response).and_return("")
163
+ @consumer.consume
164
+ @consumer.offset.should eql(1000)
165
+ end
166
+
167
+ it "should encode an offset request" do
168
+ bytes = [Kafka::RequestType::OFFSETS].pack("n") + ["test".length].pack("n") + "test" + [0].pack("N") + [-1].pack("q").reverse + [Kafka::Consumer::MAX_OFFSETS].pack("N")
169
+ @consumer.encode_request(Kafka::RequestType::OFFSETS, "test", 0, -1, Kafka::Consumer::MAX_OFFSETS).should eql(bytes)
170
+ end
171
+
172
+ it "should parse an offsets response" do
173
+ bytes = [0].pack("n") + [1].pack('N') + [21346].pack('q').reverse
174
+ @mocked_socket.should_receive(:read).and_return([14].pack("N"))
175
+ @mocked_socket.should_receive(:read).and_return(bytes)
176
+ @consumer.read_offsets_response.should eql(21346)
177
+ end
143
178
  end
144
179
  end
data/spec/io_spec.rb CHANGED
@@ -1,3 +1,17 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright ownership.
4
+ # The ASF licenses this file to You under the Apache License, Version 2.0
5
+ # (the "License"); you may not use this file except in compliance with
6
+ # the License. You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
1
15
  require File.dirname(__FILE__) + '/spec_helper'
2
16
 
3
17
  class IOTest
@@ -41,7 +55,7 @@ describe IO do
41
55
 
42
56
  it "should read from a socket" do
43
57
  length = 200
44
- @mocked_socket.should_receive(:read).with(length).and_return(nil)
58
+ @mocked_socket.should_receive(:read).with(length).and_return("foo")
45
59
  @io.read(length)
46
60
  end
47
61
 
@@ -49,7 +63,7 @@ describe IO do
49
63
  length = 200
50
64
  @mocked_socket.should_receive(:read).with(length).and_raise(Errno::EAGAIN)
51
65
  @io.should_receive(:disconnect)
52
- lambda { @io.read(length) }.should raise_error(Errno::EAGAIN)
66
+ lambda { @io.read(length) }.should raise_error(Kafka::SocketError)
53
67
  end
54
68
 
55
69
  it "should disconnect" do
@@ -59,18 +73,15 @@ describe IO do
59
73
  end
60
74
 
61
75
  it "should reconnect" do
62
- @mocked_socket.should_receive(:close)
63
- @io.should_receive(:connect)
76
+ TCPSocket.should_receive(:new)
64
77
  @io.reconnect
65
78
  end
66
79
 
67
- it "should reconnect on a broken pipe error" do
80
+ it "should disconnect on a broken pipe error" do
68
81
  [Errno::ECONNABORTED, Errno::EPIPE, Errno::ECONNRESET].each do |error|
69
- @mocked_socket.should_receive(:write).exactly(:twice).and_raise(error)
82
+ @mocked_socket.should_receive(:write).exactly(:once).and_raise(error)
70
83
  @mocked_socket.should_receive(:close).exactly(:once).and_return(nil)
71
- lambda {
72
- @io.write("some data to send")
73
- }.should raise_error(error)
84
+ lambda { @io.write("some data to send") }.should raise_error(Kafka::SocketError)
74
85
  end
75
86
  end
76
87
  end
data/spec/kafka_spec.rb CHANGED
@@ -1,3 +1,17 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright ownership.
4
+ # The ASF licenses this file to You under the Apache License, Version 2.0
5
+ # (the "License"); you may not use this file except in compliance with
6
+ # the License. You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
1
15
  require File.dirname(__FILE__) + '/spec_helper'
2
16
 
3
17
  describe Kafka do
data/spec/message_spec.rb CHANGED
@@ -1,3 +1,17 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright ownership.
4
+ # The ASF licenses this file to You under the Apache License, Version 2.0
5
+ # (the "License"); you may not use this file except in compliance with
6
+ # the License. You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
1
15
  require File.dirname(__FILE__) + '/spec_helper'
2
16
 
3
17
  describe Message do
@@ -1,4 +1,19 @@
1
1
  # encoding: utf-8
2
+
3
+ # Licensed to the Apache Software Foundation (ASF) under one or more
4
+ # contributor license agreements. See the NOTICE file distributed with
5
+ # this work for additional information regarding copyright ownership.
6
+ # The ASF licenses this file to You under the Apache License, Version 2.0
7
+ # (the "License"); you may not use this file except in compliance with
8
+ # the License. You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
2
17
  require File.dirname(__FILE__) + '/spec_helper'
3
18
 
4
19
  describe Producer do
@@ -54,7 +69,7 @@ describe Producer do
54
69
  ic = Iconv.new('UTF-8//IGNORE', 'UTF-8')
55
70
  ic.iconv(Kafka::Message.parse_from(data).payload).should eql("ümlaut")
56
71
  else
57
- Kafka::Message.parse_from(data).payload.force_encoding(Encoding::ASCII_8BIT).should eql("ümlaut")
72
+ Kafka::Message.parse_from(data).payload.force_encoding(Encoding::UTF_8).should eql("ümlaut")
58
73
  end
59
74
  end
60
75
  end
data/spec/spec_helper.rb CHANGED
@@ -1,3 +1,17 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright ownership.
4
+ # The ASF licenses this file to You under the Apache License, Version 2.0
5
+ # (the "License"); you may not use this file except in compliance with
6
+ # the License. You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
1
15
  require 'rubygems'
2
16
  require 'kafka'
3
17
 
metadata CHANGED
@@ -1,22 +1,23 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kafka-rb
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
5
- prerelease: false
4
+ hash: 15
5
+ prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 6
10
- version: 0.0.6
9
+ - 8
10
+ version: 0.0.8
11
11
  platform: ruby
12
12
  authors:
13
13
  - Alejandro Crosa
14
+ - Stefan Mees
15
+ - Tim Lossen
14
16
  autorequire: kafka-rb
15
17
  bindir: bin
16
18
  cert_chain: []
17
19
 
18
- date: 2011-01-13 00:00:00 -08:00
19
- default_executable:
20
+ date: 2012-01-14 00:00:00 Z
20
21
  dependencies:
21
22
  - !ruby/object:Gem::Dependency
22
23
  name: rspec
@@ -33,7 +34,7 @@ dependencies:
33
34
  type: :development
34
35
  version_requirements: *id001
35
36
  description: kafka-rb allows you to produce and consume messages using the Kafka distributed publish/subscribe messaging service.
36
- email: alejandrocrosa@gmail.com
37
+ email:
37
38
  executables: []
38
39
 
39
40
  extensions: []
@@ -50,6 +51,7 @@ files:
50
51
  - lib/kafka/message.rb
51
52
  - lib/kafka/producer.rb
52
53
  - lib/kafka/request_type.rb
54
+ - lib/kafka/error_codes.rb
53
55
  - lib/kafka.rb
54
56
  - spec/batch_spec.rb
55
57
  - spec/consumer_spec.rb
@@ -58,8 +60,7 @@ files:
58
60
  - spec/message_spec.rb
59
61
  - spec/producer_spec.rb
60
62
  - spec/spec_helper.rb
61
- has_rdoc: true
62
- homepage: http://github.com/acrosa/kafka-rb
63
+ homepage: http://github.com/wooga/kafka-rb
63
64
  licenses: []
64
65
 
65
66
  post_install_message:
@@ -88,7 +89,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
88
89
  requirements: []
89
90
 
90
91
  rubyforge_project:
91
- rubygems_version: 1.3.7
92
+ rubygems_version: 1.8.11
92
93
  signing_key:
93
94
  specification_version: 3
94
95
  summary: A Ruby client for the Kafka distributed publish/subscribe messaging service