ralphrodkey-kafka-rb 0.0.15
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +202 -0
- data/README.md +123 -0
- data/Rakefile +40 -0
- data/bin/leffen-kafka-consumer +6 -0
- data/bin/leffen-kafka-publish +6 -0
- data/lib/kafka.rb +40 -0
- data/lib/kafka/batch.rb +28 -0
- data/lib/kafka/cli.rb +170 -0
- data/lib/kafka/consumer.rb +126 -0
- data/lib/kafka/encoder.rb +59 -0
- data/lib/kafka/error_codes.rb +53 -0
- data/lib/kafka/io.rb +57 -0
- data/lib/kafka/message.rb +209 -0
- data/lib/kafka/multi_producer.rb +35 -0
- data/lib/kafka/producer.rb +42 -0
- data/lib/kafka/producer_request.rb +26 -0
- data/lib/kafka/request_type.rb +23 -0
- data/lib/leffen-kafka.rb +16 -0
- data/lib/ralphrodkey-kafka.rb +16 -0
- data/spec/batch_spec.rb +35 -0
- data/spec/cli_spec.rb +133 -0
- data/spec/consumer_spec.rb +146 -0
- data/spec/encoder_spec.rb +251 -0
- data/spec/io_spec.rb +88 -0
- data/spec/kafka_spec.rb +20 -0
- data/spec/message_spec.rb +227 -0
- data/spec/multi_producer_spec.rb +74 -0
- data/spec/producer_request_spec.rb +38 -0
- data/spec/producer_spec.rb +71 -0
- data/spec/spec_helper.rb +18 -0
- metadata +108 -0
@@ -0,0 +1,209 @@
|
|
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
|
+
|
17
|
+
# A message. The format of a message is as follows:
|
18
|
+
#
|
19
|
+
# 4 byte big-endian int: length of message in bytes (including the rest of
|
20
|
+
# the header, but excluding the length field itself)
|
21
|
+
# 1 byte: "magic" identifier (format version number)
|
22
|
+
#
|
23
|
+
# If the magic byte == 0, there is one more header field:
|
24
|
+
#
|
25
|
+
# 4 byte big-endian int: CRC32 checksum of the payload
|
26
|
+
#
|
27
|
+
# If the magic byte == 1, there are two more header fields:
|
28
|
+
#
|
29
|
+
# 1 byte: "attributes" (flags for compression, codec etc)
|
30
|
+
# 4 byte big-endian int: CRC32 checksum of the payload
|
31
|
+
#
|
32
|
+
# All following bytes are the payload.
|
33
|
+
class Message
|
34
|
+
|
35
|
+
MAGIC_IDENTIFIER_DEFAULT = 0
|
36
|
+
MAGIC_IDENTIFIER_COMPRESSION = 1
|
37
|
+
NO_COMPRESSION = 0
|
38
|
+
GZIP_COMPRESSION = 1
|
39
|
+
SNAPPY_COMPRESSION = 2
|
40
|
+
BASIC_MESSAGE_HEADER = 'NC'.freeze
|
41
|
+
VERSION_0_HEADER = 'N'.freeze
|
42
|
+
VERSION_1_HEADER = 'CN'.freeze
|
43
|
+
COMPRESSION_CODEC_MASK = 0x03
|
44
|
+
|
45
|
+
attr_accessor :magic, :checksum, :payload
|
46
|
+
|
47
|
+
def initialize(payload = nil, magic = MAGIC_IDENTIFIER_DEFAULT, checksum = nil)
|
48
|
+
self.magic = magic
|
49
|
+
self.payload = payload || ""
|
50
|
+
self.checksum = checksum || self.calculate_checksum
|
51
|
+
@compression = NO_COMPRESSION
|
52
|
+
end
|
53
|
+
|
54
|
+
def calculate_checksum
|
55
|
+
Zlib.crc32(self.payload)
|
56
|
+
end
|
57
|
+
|
58
|
+
def valid?
|
59
|
+
self.checksum == calculate_checksum
|
60
|
+
end
|
61
|
+
|
62
|
+
# Takes a byte string containing one or more messages; returns a MessageSet
|
63
|
+
# with the messages parsed from the string, and the number of bytes
|
64
|
+
# consumed from the string.
|
65
|
+
def self.parse_from(data)
|
66
|
+
messages = []
|
67
|
+
bytes_processed = 0
|
68
|
+
|
69
|
+
while bytes_processed <= data.length - 5 # 5 = size of BASIC_MESSAGE_HEADER
|
70
|
+
message_size, magic = data[bytes_processed, 5].unpack(BASIC_MESSAGE_HEADER)
|
71
|
+
break if bytes_processed + message_size + 4 > data.length # message is truncated
|
72
|
+
|
73
|
+
case magic
|
74
|
+
when MAGIC_IDENTIFIER_DEFAULT
|
75
|
+
# | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 ...
|
76
|
+
# | | | |
|
77
|
+
# | message_size |magic| checksum | payload ...
|
78
|
+
payload_size = message_size - 5 # 5 = sizeof(magic) + sizeof(checksum)
|
79
|
+
checksum = data[bytes_processed + 5, 4].unpack(VERSION_0_HEADER).shift
|
80
|
+
payload = data[bytes_processed + 9, payload_size]
|
81
|
+
messages << Kafka::Message.new(payload, magic, checksum)
|
82
|
+
|
83
|
+
when MAGIC_IDENTIFIER_COMPRESSION
|
84
|
+
# | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 ...
|
85
|
+
# | | | | |
|
86
|
+
# | size |magic|attrs| checksum | payload ...
|
87
|
+
payload_size = message_size - 6 # 6 = sizeof(magic) + sizeof(attrs) + sizeof(checksum)
|
88
|
+
attributes, checksum = data[bytes_processed + 5, 5].unpack(VERSION_1_HEADER)
|
89
|
+
payload = data[bytes_processed + 10, payload_size]
|
90
|
+
|
91
|
+
case attributes & COMPRESSION_CODEC_MASK
|
92
|
+
when NO_COMPRESSION # a single uncompressed message
|
93
|
+
messages << Kafka::Message.new(payload, magic, checksum)
|
94
|
+
when GZIP_COMPRESSION # a gzip-compressed message set -- parse recursively
|
95
|
+
uncompressed = Zlib::GzipReader.new(StringIO.new(payload)).read
|
96
|
+
message_set = parse_from(uncompressed)
|
97
|
+
raise 'malformed compressed message' if message_set.size != uncompressed.size
|
98
|
+
messages.concat(message_set.messages)
|
99
|
+
when SNAPPY_COMPRESSION # a snappy-compresses message set -- parse recursively
|
100
|
+
ensure_snappy! do
|
101
|
+
uncompressed = Snappy::Reader.new(StringIO.new(payload)).read
|
102
|
+
message_set = parse_from(uncompressed)
|
103
|
+
raise 'malformed compressed message' if message_set.size != uncompressed.size
|
104
|
+
messages.concat(message_set.messages)
|
105
|
+
end
|
106
|
+
else
|
107
|
+
# https://cwiki.apache.org/confluence/display/KAFKA/Compression
|
108
|
+
raise "Unsupported Kafka compression codec: #{attributes & COMPRESSION_CODEC_MASK}"
|
109
|
+
end
|
110
|
+
|
111
|
+
else
|
112
|
+
raise "Unsupported Kafka message version: magic number #{magic}"
|
113
|
+
end
|
114
|
+
|
115
|
+
bytes_processed += message_size + 4 # 4 = sizeof(message_size)
|
116
|
+
end
|
117
|
+
|
118
|
+
MessageSet.new(bytes_processed, messages)
|
119
|
+
end
|
120
|
+
|
121
|
+
def encode(compression = NO_COMPRESSION)
|
122
|
+
@compression = compression
|
123
|
+
|
124
|
+
self.payload = asciify_payload
|
125
|
+
self.payload = compress_payload if compression?
|
126
|
+
|
127
|
+
data = magic_and_compression + [calculate_checksum].pack("N") + payload
|
128
|
+
[data.length].pack("N") + data
|
129
|
+
end
|
130
|
+
|
131
|
+
|
132
|
+
# Encapsulates a list of Kafka messages (as Kafka::Message objects in the
|
133
|
+
# +messages+ attribute) and their total serialized size in bytes (the +size+
|
134
|
+
# attribute).
|
135
|
+
class MessageSet < Struct.new(:size, :messages); end
|
136
|
+
|
137
|
+
def self.ensure_snappy!
|
138
|
+
if Object.const_defined? "Snappy"
|
139
|
+
yield
|
140
|
+
else
|
141
|
+
fail "Snappy not available!"
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def ensure_snappy! &block
|
146
|
+
self.class.ensure_snappy! &block
|
147
|
+
end
|
148
|
+
|
149
|
+
private
|
150
|
+
|
151
|
+
attr_reader :compression
|
152
|
+
|
153
|
+
def compression?
|
154
|
+
compression != NO_COMPRESSION
|
155
|
+
end
|
156
|
+
|
157
|
+
def magic_and_compression
|
158
|
+
if compression?
|
159
|
+
[MAGIC_IDENTIFIER_COMPRESSION, compression].pack("CC")
|
160
|
+
else
|
161
|
+
[MAGIC_IDENTIFIER_DEFAULT].pack("C")
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def asciify_payload
|
166
|
+
if RUBY_VERSION[0, 3] == "1.8"
|
167
|
+
payload
|
168
|
+
else
|
169
|
+
payload.to_s.force_encoding(Encoding::ASCII_8BIT)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def compress_payload
|
174
|
+
case compression
|
175
|
+
when GZIP_COMPRESSION
|
176
|
+
gzip
|
177
|
+
when SNAPPY_COMPRESSION
|
178
|
+
snappy
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def gzip
|
183
|
+
with_buffer do |buffer|
|
184
|
+
gz = Zlib::GzipWriter.new buffer, nil, nil
|
185
|
+
gz.write payload
|
186
|
+
gz.close
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def snappy
|
191
|
+
ensure_snappy! do
|
192
|
+
with_buffer do |buffer|
|
193
|
+
Snappy::Writer.new buffer do |w|
|
194
|
+
w << payload
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def with_buffer
|
201
|
+
buffer = StringIO.new
|
202
|
+
buffer.set_encoding Encoding::ASCII_8BIT unless RUBY_VERSION =~ /^1\.8/
|
203
|
+
yield buffer if block_given?
|
204
|
+
buffer.rewind
|
205
|
+
buffer.string
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
@@ -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
|
+
class MultiProducer
|
17
|
+
include Kafka::IO
|
18
|
+
|
19
|
+
def initialize(options={})
|
20
|
+
self.host = options[:host] || HOST
|
21
|
+
self.port = options[:port] || PORT
|
22
|
+
self.compression = options[:compression] || Message::NO_COMPRESSION
|
23
|
+
self.connect(self.host, self.port)
|
24
|
+
end
|
25
|
+
|
26
|
+
def push(topic, messages, options={})
|
27
|
+
partition = options[:partition] || 0
|
28
|
+
self.write(Encoder.produce(topic, partition, messages, compression))
|
29
|
+
end
|
30
|
+
|
31
|
+
def multi_push(producer_requests)
|
32
|
+
self.write(Encoder.multiproduce(producer_requests, compression))
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,42 @@
|
|
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
|
+
class Producer
|
17
|
+
|
18
|
+
include Kafka::IO
|
19
|
+
|
20
|
+
attr_accessor :topic, :partition
|
21
|
+
|
22
|
+
def initialize(options = {})
|
23
|
+
self.topic = options[:topic] || "test"
|
24
|
+
self.partition = options[:partition] || 0
|
25
|
+
self.host = options[:host] || HOST
|
26
|
+
self.port = options[:port] || PORT
|
27
|
+
self.compression = options[:compression] || Message::NO_COMPRESSION
|
28
|
+
self.connect(self.host, self.port)
|
29
|
+
end
|
30
|
+
|
31
|
+
def push(messages)
|
32
|
+
self.write(Encoder.produce(self.topic, self.partition, messages, compression))
|
33
|
+
end
|
34
|
+
|
35
|
+
def batch(&block)
|
36
|
+
batch = Kafka::Batch.new
|
37
|
+
block.call( batch )
|
38
|
+
push(batch.messages)
|
39
|
+
batch.messages.clear
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,26 @@
|
|
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
|
+
|
16
|
+
module Kafka
|
17
|
+
class ProducerRequest
|
18
|
+
attr_accessor :topic, :messages, :partition
|
19
|
+
|
20
|
+
def initialize(topic, messages, options={})
|
21
|
+
self.topic = topic
|
22
|
+
self.partition = options[:partition] || 0
|
23
|
+
self.messages = Array(messages)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,23 @@
|
|
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 RequestType
|
17
|
+
PRODUCE = 0
|
18
|
+
FETCH = 1
|
19
|
+
MULTIFETCH = 2
|
20
|
+
MULTIPRODUCE = 3
|
21
|
+
OFFSETS = 4
|
22
|
+
end
|
23
|
+
end
|
data/lib/leffen-kafka.rb
ADDED
@@ -0,0 +1,16 @@
|
|
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
|
+
|
16
|
+
require File.join(File.dirname(__FILE__), "kafka")
|
@@ -0,0 +1,16 @@
|
|
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
|
+
|
16
|
+
require File.join(File.dirname(__FILE__), "kafka")
|
data/spec/batch_spec.rb
ADDED
@@ -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
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
16
|
+
|
17
|
+
describe Batch do
|
18
|
+
|
19
|
+
before(:each) do
|
20
|
+
@batch = Batch.new
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "batch messages" do
|
24
|
+
it "holds all messages to be sent" do
|
25
|
+
@batch.should respond_to(:messages)
|
26
|
+
@batch.messages.class.should eql(Array)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "supports queueing/adding messages to be send" do
|
30
|
+
@batch.messages << mock(Kafka::Message.new("one"))
|
31
|
+
@batch.messages << mock(Kafka::Message.new("two"))
|
32
|
+
@batch.messages.length.should eql(2)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/spec/cli_spec.rb
ADDED
@@ -0,0 +1,133 @@
|
|
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
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
16
|
+
require 'kafka/cli'
|
17
|
+
|
18
|
+
describe CLI do
|
19
|
+
|
20
|
+
before(:each) do
|
21
|
+
CLI.instance_variable_set("@config", {})
|
22
|
+
CLI.stub(:puts)
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "should read from env" do
|
26
|
+
describe "kafka host" do
|
27
|
+
it "should read KAFKA_HOST from env" do
|
28
|
+
CLI.read_env("KAFKA_HOST" => "google.com")
|
29
|
+
CLI.config[:host].should == "google.com"
|
30
|
+
end
|
31
|
+
|
32
|
+
it "kafka port" do
|
33
|
+
CLI.read_env("KAFKA_PORT" => "1234")
|
34
|
+
CLI.config[:port].should == 1234
|
35
|
+
end
|
36
|
+
|
37
|
+
it "kafka topic" do
|
38
|
+
CLI.read_env("KAFKA_TOPIC" => "news")
|
39
|
+
CLI.config[:topic].should == "news"
|
40
|
+
end
|
41
|
+
|
42
|
+
it "kafka compression" do
|
43
|
+
CLI.read_env("KAFKA_COMPRESSION" => "no")
|
44
|
+
CLI.config[:compression].should == Message::NO_COMPRESSION
|
45
|
+
|
46
|
+
CLI.read_env("KAFKA_COMPRESSION" => "gzip")
|
47
|
+
CLI.config[:compression].should == Message::GZIP_COMPRESSION
|
48
|
+
|
49
|
+
CLI.read_env("KAFKA_COMPRESSION" => "snappy")
|
50
|
+
CLI.config[:compression].should == Message::SNAPPY_COMPRESSION
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "should read from command line" do
|
56
|
+
it "kafka host" do
|
57
|
+
CLI.parse_args(%w(--host google.com))
|
58
|
+
CLI.config[:host].should == "google.com"
|
59
|
+
|
60
|
+
CLI.parse_args(%w(-h google.com))
|
61
|
+
CLI.config[:host].should == "google.com"
|
62
|
+
end
|
63
|
+
|
64
|
+
it "kafka port" do
|
65
|
+
CLI.parse_args(%w(--port 1234))
|
66
|
+
CLI.config[:port].should == 1234
|
67
|
+
|
68
|
+
CLI.parse_args(%w(-p 1234))
|
69
|
+
CLI.config[:port].should == 1234
|
70
|
+
end
|
71
|
+
|
72
|
+
it "kafka topic" do
|
73
|
+
CLI.parse_args(%w(--topic news))
|
74
|
+
CLI.config[:topic].should == "news"
|
75
|
+
|
76
|
+
CLI.parse_args(%w(-t news))
|
77
|
+
CLI.config[:topic].should == "news"
|
78
|
+
end
|
79
|
+
|
80
|
+
it "kafka compression" do
|
81
|
+
CLI.stub(:publish? => true)
|
82
|
+
|
83
|
+
CLI.parse_args(%w(--compression no))
|
84
|
+
CLI.config[:compression].should == Message::NO_COMPRESSION
|
85
|
+
CLI.parse_args(%w(-c no))
|
86
|
+
CLI.config[:compression].should == Message::NO_COMPRESSION
|
87
|
+
|
88
|
+
CLI.parse_args(%w(--compression gzip))
|
89
|
+
CLI.config[:compression].should == Message::GZIP_COMPRESSION
|
90
|
+
CLI.parse_args(%w(-c gzip))
|
91
|
+
CLI.config[:compression].should == Message::GZIP_COMPRESSION
|
92
|
+
|
93
|
+
CLI.parse_args(%w(--compression snappy))
|
94
|
+
CLI.config[:compression].should == Message::SNAPPY_COMPRESSION
|
95
|
+
CLI.parse_args(%w(-c snappy))
|
96
|
+
CLI.config[:compression].should == Message::SNAPPY_COMPRESSION
|
97
|
+
end
|
98
|
+
|
99
|
+
it "message" do
|
100
|
+
CLI.stub(:publish? => true)
|
101
|
+
CLI.parse_args(%w(--message YEAH))
|
102
|
+
CLI.config[:message].should == "YEAH"
|
103
|
+
|
104
|
+
CLI.parse_args(%w(-m YEAH))
|
105
|
+
CLI.config[:message].should == "YEAH"
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
describe "config validation" do
|
111
|
+
it "should assign a default port" do
|
112
|
+
CLI.stub(:exit)
|
113
|
+
CLI.stub(:puts)
|
114
|
+
CLI.validate_config
|
115
|
+
CLI.config[:port].should == Kafka::IO::PORT
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
it "should assign a default host" do
|
120
|
+
CLI.stub(:exit)
|
121
|
+
CLI.validate_config
|
122
|
+
CLI.config[:host].should == Kafka::IO::HOST
|
123
|
+
end
|
124
|
+
|
125
|
+
|
126
|
+
it "read compression method" do
|
127
|
+
CLI.string_to_compression("no").should == Message::NO_COMPRESSION
|
128
|
+
CLI.string_to_compression("gzip").should == Message::GZIP_COMPRESSION
|
129
|
+
CLI.string_to_compression("snappy").should == Message::SNAPPY_COMPRESSION
|
130
|
+
lambda { CLI.push(:string_to_compression,nil) }.should raise_error
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|