ruby-kafka 0.7.10 → 1.3.0
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.
- checksums.yaml +4 -4
- data/.circleci/config.yml +99 -0
- data/.github/workflows/stale.yml +19 -0
- data/.ruby-version +1 -1
- data/CHANGELOG.md +27 -0
- data/README.md +125 -0
- data/lib/kafka/async_producer.rb +24 -12
- data/lib/kafka/client.rb +72 -4
- data/lib/kafka/cluster.rb +52 -0
- data/lib/kafka/connection.rb +3 -0
- data/lib/kafka/consumer.rb +61 -11
- data/lib/kafka/consumer_group.rb +23 -5
- data/lib/kafka/consumer_group/assignor.rb +63 -0
- data/lib/kafka/datadog.rb +20 -13
- data/lib/kafka/fetcher.rb +5 -2
- data/lib/kafka/interceptors.rb +33 -0
- data/lib/kafka/offset_manager.rb +12 -1
- data/lib/kafka/partitioner.rb +1 -1
- data/lib/kafka/producer.rb +13 -5
- data/lib/kafka/prometheus.rb +78 -79
- data/lib/kafka/protocol/join_group_request.rb +8 -2
- data/lib/kafka/protocol/join_group_response.rb +9 -1
- data/lib/kafka/protocol/metadata_response.rb +1 -1
- data/lib/kafka/protocol/offset_fetch_request.rb +3 -1
- data/lib/kafka/round_robin_assignment_strategy.rb +15 -38
- data/lib/kafka/ssl_context.rb +4 -3
- data/lib/kafka/tagged_logger.rb +1 -0
- data/lib/kafka/transaction_manager.rb +13 -8
- data/lib/kafka/version.rb +1 -1
- data/ruby-kafka.gemspec +4 -4
- metadata +21 -13
@@ -7,13 +7,14 @@ module Kafka
|
|
7
7
|
class JoinGroupRequest
|
8
8
|
PROTOCOL_TYPE = "consumer"
|
9
9
|
|
10
|
-
def initialize(group_id:, session_timeout:, member_id:, topics: [])
|
10
|
+
def initialize(group_id:, session_timeout:, rebalance_timeout:, member_id:, topics: [], protocol_name:, user_data: nil)
|
11
11
|
@group_id = group_id
|
12
12
|
@session_timeout = session_timeout * 1000 # Kafka wants ms.
|
13
|
+
@rebalance_timeout = rebalance_timeout * 1000 # Kafka wants ms.
|
13
14
|
@member_id = member_id || ""
|
14
15
|
@protocol_type = PROTOCOL_TYPE
|
15
16
|
@group_protocols = {
|
16
|
-
|
17
|
+
protocol_name => ConsumerGroupProtocol.new(topics: topics, user_data: user_data),
|
17
18
|
}
|
18
19
|
end
|
19
20
|
|
@@ -21,6 +22,10 @@ module Kafka
|
|
21
22
|
JOIN_GROUP_API
|
22
23
|
end
|
23
24
|
|
25
|
+
def api_version
|
26
|
+
1
|
27
|
+
end
|
28
|
+
|
24
29
|
def response_class
|
25
30
|
JoinGroupResponse
|
26
31
|
end
|
@@ -28,6 +33,7 @@ module Kafka
|
|
28
33
|
def encode(encoder)
|
29
34
|
encoder.write_string(@group_id)
|
30
35
|
encoder.write_int32(@session_timeout)
|
36
|
+
encoder.write_int32(@rebalance_timeout)
|
31
37
|
encoder.write_string(@member_id)
|
32
38
|
encoder.write_string(@protocol_type)
|
33
39
|
|
@@ -3,6 +3,8 @@
|
|
3
3
|
module Kafka
|
4
4
|
module Protocol
|
5
5
|
class JoinGroupResponse
|
6
|
+
Metadata = Struct.new(:version, :topics, :user_data)
|
7
|
+
|
6
8
|
attr_reader :error_code
|
7
9
|
|
8
10
|
attr_reader :generation_id, :group_protocol
|
@@ -25,7 +27,13 @@ module Kafka
|
|
25
27
|
group_protocol: decoder.string,
|
26
28
|
leader_id: decoder.string,
|
27
29
|
member_id: decoder.string,
|
28
|
-
members: Hash[
|
30
|
+
members: Hash[
|
31
|
+
decoder.array do
|
32
|
+
member_id = decoder.string
|
33
|
+
d = Decoder.from_string(decoder.bytes)
|
34
|
+
[member_id, Metadata.new(d.int16, d.array { d.string }, d.bytes)]
|
35
|
+
end
|
36
|
+
],
|
29
37
|
)
|
30
38
|
end
|
31
39
|
end
|
@@ -1,54 +1,31 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "kafka/protocol/member_assignment"
|
4
|
-
|
5
3
|
module Kafka
|
6
4
|
|
7
5
|
# A consumer group partition assignment strategy that assigns partitions to
|
8
6
|
# consumers in a round-robin fashion.
|
9
7
|
class RoundRobinAssignmentStrategy
|
10
|
-
def
|
11
|
-
|
8
|
+
def protocol_name
|
9
|
+
"roundrobin"
|
12
10
|
end
|
13
11
|
|
14
12
|
# Assign the topic partitions to the group members.
|
15
13
|
#
|
16
|
-
# @param
|
17
|
-
# @param
|
18
|
-
#
|
19
|
-
#
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
begin
|
29
|
-
partitions = @cluster.partitions_for(topic).map(&:partition_id)
|
30
|
-
rescue UnknownTopicOrPartition
|
31
|
-
raise UnknownTopicOrPartition, "unknown topic #{topic}"
|
32
|
-
end
|
33
|
-
Array.new(partitions.count) { topic }.zip(partitions)
|
34
|
-
end
|
35
|
-
|
36
|
-
partitions_per_member = topic_partitions.group_by.with_index do |_, index|
|
37
|
-
index % members.count
|
38
|
-
end.values
|
39
|
-
|
40
|
-
members.zip(partitions_per_member).each do |member_id, member_partitions|
|
41
|
-
unless member_partitions.nil?
|
42
|
-
member_partitions.each do |topic, partition|
|
43
|
-
group_assignment[member_id].assign(topic, [partition])
|
44
|
-
end
|
45
|
-
end
|
14
|
+
# @param cluster [Kafka::Cluster]
|
15
|
+
# @param members [Hash<String, Kafka::Protocol::JoinGroupResponse::Metadata>] a hash
|
16
|
+
# mapping member ids to metadata
|
17
|
+
# @param partitions [Array<Kafka::ConsumerGroup::Assignor::Partition>] a list of
|
18
|
+
# partitions the consumer group processes
|
19
|
+
# @return [Hash<String, Array<Kafka::ConsumerGroup::Assignor::Partition>] a hash
|
20
|
+
# mapping member ids to partitions.
|
21
|
+
def call(cluster:, members:, partitions:)
|
22
|
+
member_ids = members.keys
|
23
|
+
partitions_per_member = Hash.new {|h, k| h[k] = [] }
|
24
|
+
partitions.each_with_index do |partition, index|
|
25
|
+
partitions_per_member[member_ids[index % member_ids.count]] << partition
|
46
26
|
end
|
47
27
|
|
48
|
-
|
49
|
-
rescue Kafka::LeaderNotAvailable
|
50
|
-
sleep 1
|
51
|
-
retry
|
28
|
+
partitions_per_member
|
52
29
|
end
|
53
30
|
end
|
54
31
|
end
|
data/lib/kafka/ssl_context.rb
CHANGED
@@ -54,11 +54,12 @@ module Kafka
|
|
54
54
|
store.set_default_paths
|
55
55
|
end
|
56
56
|
ssl_context.cert_store = store
|
57
|
-
ssl_context.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
58
|
-
# Verify certificate hostname if supported (ruby >= 2.4.0)
|
59
|
-
ssl_context.verify_hostname = verify_hostname if ssl_context.respond_to?(:verify_hostname=)
|
60
57
|
end
|
61
58
|
|
59
|
+
ssl_context.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
60
|
+
# Verify certificate hostname if supported (ruby >= 2.4.0)
|
61
|
+
ssl_context.verify_hostname = verify_hostname if ssl_context.respond_to?(:verify_hostname=)
|
62
|
+
|
62
63
|
ssl_context
|
63
64
|
end
|
64
65
|
end
|
data/lib/kafka/tagged_logger.rb
CHANGED
@@ -95,7 +95,7 @@ module Kafka
|
|
95
95
|
force_transactional!
|
96
96
|
|
97
97
|
if @transaction_state.uninitialized?
|
98
|
-
raise 'Transaction is uninitialized'
|
98
|
+
raise Kafka::InvalidTxnStateError, 'Transaction is uninitialized'
|
99
99
|
end
|
100
100
|
|
101
101
|
# Extract newly created partitions
|
@@ -138,8 +138,8 @@ module Kafka
|
|
138
138
|
|
139
139
|
def begin_transaction
|
140
140
|
force_transactional!
|
141
|
-
raise 'Transaction has already started' if @transaction_state.in_transaction?
|
142
|
-
raise 'Transaction is not ready' unless @transaction_state.ready?
|
141
|
+
raise Kafka::InvalidTxnStateError, 'Transaction has already started' if @transaction_state.in_transaction?
|
142
|
+
raise Kafka::InvalidTxnStateError, 'Transaction is not ready' unless @transaction_state.ready?
|
143
143
|
@transaction_state.transition_to!(TransactionStateMachine::IN_TRANSACTION)
|
144
144
|
|
145
145
|
@logger.info "Begin transaction #{@transactional_id}, Producer ID: #{@producer_id} (Epoch #{@producer_epoch})"
|
@@ -159,7 +159,7 @@ module Kafka
|
|
159
159
|
end
|
160
160
|
|
161
161
|
unless @transaction_state.in_transaction?
|
162
|
-
raise 'Transaction is not valid to commit'
|
162
|
+
raise Kafka::InvalidTxnStateError, 'Transaction is not valid to commit'
|
163
163
|
end
|
164
164
|
|
165
165
|
@transaction_state.transition_to!(TransactionStateMachine::COMMITTING_TRANSACTION)
|
@@ -192,7 +192,8 @@ module Kafka
|
|
192
192
|
end
|
193
193
|
|
194
194
|
unless @transaction_state.in_transaction?
|
195
|
-
|
195
|
+
@logger.warn('Aborting transaction that was never opened on brokers')
|
196
|
+
return
|
196
197
|
end
|
197
198
|
|
198
199
|
@transaction_state.transition_to!(TransactionStateMachine::ABORTING_TRANSACTION)
|
@@ -221,7 +222,7 @@ module Kafka
|
|
221
222
|
force_transactional!
|
222
223
|
|
223
224
|
unless @transaction_state.in_transaction?
|
224
|
-
raise 'Transaction is not valid to send offsets'
|
225
|
+
raise Kafka::InvalidTxnStateError, 'Transaction is not valid to send offsets'
|
225
226
|
end
|
226
227
|
|
227
228
|
add_response = transaction_coordinator.add_offsets_to_txn(
|
@@ -250,6 +251,10 @@ module Kafka
|
|
250
251
|
@transaction_state.error?
|
251
252
|
end
|
252
253
|
|
254
|
+
def ready?
|
255
|
+
@transaction_state.ready?
|
256
|
+
end
|
257
|
+
|
253
258
|
def close
|
254
259
|
if in_transaction?
|
255
260
|
@logger.warn("Aborting pending transaction ...")
|
@@ -264,11 +269,11 @@ module Kafka
|
|
264
269
|
|
265
270
|
def force_transactional!
|
266
271
|
unless transactional?
|
267
|
-
raise 'Please turn on transactional mode to use transaction'
|
272
|
+
raise Kafka::InvalidTxnStateError, 'Please turn on transactional mode to use transaction'
|
268
273
|
end
|
269
274
|
|
270
275
|
if @transactional_id.nil? || @transactional_id.empty?
|
271
|
-
raise 'Please provide a transaction_id to use transactional mode'
|
276
|
+
raise Kafka::InvalidTxnStateError, 'Please provide a transaction_id to use transactional mode'
|
272
277
|
end
|
273
278
|
end
|
274
279
|
|
data/lib/kafka/version.rb
CHANGED
data/ruby-kafka.gemspec
CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
|
|
18
18
|
DESC
|
19
19
|
|
20
20
|
spec.homepage = "https://github.com/zendesk/ruby-kafka"
|
21
|
-
spec.license = "Apache
|
21
|
+
spec.license = "Apache-2.0"
|
22
22
|
|
23
23
|
spec.required_ruby_version = '>= 2.1.0'
|
24
24
|
|
@@ -36,15 +36,15 @@ Gem::Specification.new do |spec|
|
|
36
36
|
spec.add_development_dependency "dotenv"
|
37
37
|
spec.add_development_dependency "docker-api"
|
38
38
|
spec.add_development_dependency "rspec-benchmark"
|
39
|
-
spec.add_development_dependency "activesupport"
|
39
|
+
spec.add_development_dependency "activesupport", ">= 4.0", "< 6.1"
|
40
40
|
spec.add_development_dependency "snappy"
|
41
41
|
spec.add_development_dependency "extlz4"
|
42
42
|
spec.add_development_dependency "zstd-ruby"
|
43
43
|
spec.add_development_dependency "colored"
|
44
44
|
spec.add_development_dependency "rspec_junit_formatter", "0.2.2"
|
45
|
-
spec.add_development_dependency "dogstatsd-ruby", ">=
|
45
|
+
spec.add_development_dependency "dogstatsd-ruby", ">= 4.0.0", "< 5.0.0"
|
46
46
|
spec.add_development_dependency "statsd-ruby"
|
47
|
-
spec.add_development_dependency "prometheus-client"
|
47
|
+
spec.add_development_dependency "prometheus-client", "~> 0.10.0"
|
48
48
|
spec.add_development_dependency "ruby-prof"
|
49
49
|
spec.add_development_dependency "timecop"
|
50
50
|
spec.add_development_dependency "rubocop", "~> 0.49.1"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-kafka
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Schierbeck
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-10-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: digest-crc
|
@@ -128,14 +128,20 @@ dependencies:
|
|
128
128
|
requirements:
|
129
129
|
- - ">="
|
130
130
|
- !ruby/object:Gem::Version
|
131
|
-
version: '0'
|
131
|
+
version: '4.0'
|
132
|
+
- - "<"
|
133
|
+
- !ruby/object:Gem::Version
|
134
|
+
version: '6.1'
|
132
135
|
type: :development
|
133
136
|
prerelease: false
|
134
137
|
version_requirements: !ruby/object:Gem::Requirement
|
135
138
|
requirements:
|
136
139
|
- - ">="
|
137
140
|
- !ruby/object:Gem::Version
|
138
|
-
version: '0'
|
141
|
+
version: '4.0'
|
142
|
+
- - "<"
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '6.1'
|
139
145
|
- !ruby/object:Gem::Dependency
|
140
146
|
name: snappy
|
141
147
|
requirement: !ruby/object:Gem::Requirement
|
@@ -212,7 +218,7 @@ dependencies:
|
|
212
218
|
requirements:
|
213
219
|
- - ">="
|
214
220
|
- !ruby/object:Gem::Version
|
215
|
-
version:
|
221
|
+
version: 4.0.0
|
216
222
|
- - "<"
|
217
223
|
- !ruby/object:Gem::Version
|
218
224
|
version: 5.0.0
|
@@ -222,7 +228,7 @@ dependencies:
|
|
222
228
|
requirements:
|
223
229
|
- - ">="
|
224
230
|
- !ruby/object:Gem::Version
|
225
|
-
version:
|
231
|
+
version: 4.0.0
|
226
232
|
- - "<"
|
227
233
|
- !ruby/object:Gem::Version
|
228
234
|
version: 5.0.0
|
@@ -244,16 +250,16 @@ dependencies:
|
|
244
250
|
name: prometheus-client
|
245
251
|
requirement: !ruby/object:Gem::Requirement
|
246
252
|
requirements:
|
247
|
-
- - "
|
253
|
+
- - "~>"
|
248
254
|
- !ruby/object:Gem::Version
|
249
|
-
version:
|
255
|
+
version: 0.10.0
|
250
256
|
type: :development
|
251
257
|
prerelease: false
|
252
258
|
version_requirements: !ruby/object:Gem::Requirement
|
253
259
|
requirements:
|
254
|
-
- - "
|
260
|
+
- - "~>"
|
255
261
|
- !ruby/object:Gem::Version
|
256
|
-
version:
|
262
|
+
version: 0.10.0
|
257
263
|
- !ruby/object:Gem::Dependency
|
258
264
|
name: ruby-prof
|
259
265
|
requirement: !ruby/object:Gem::Requirement
|
@@ -332,6 +338,7 @@ extensions: []
|
|
332
338
|
extra_rdoc_files: []
|
333
339
|
files:
|
334
340
|
- ".circleci/config.yml"
|
341
|
+
- ".github/workflows/stale.yml"
|
335
342
|
- ".gitignore"
|
336
343
|
- ".readygo"
|
337
344
|
- ".rspec"
|
@@ -369,6 +376,7 @@ files:
|
|
369
376
|
- lib/kafka/connection_builder.rb
|
370
377
|
- lib/kafka/consumer.rb
|
371
378
|
- lib/kafka/consumer_group.rb
|
379
|
+
- lib/kafka/consumer_group/assignor.rb
|
372
380
|
- lib/kafka/datadog.rb
|
373
381
|
- lib/kafka/fetch_operation.rb
|
374
382
|
- lib/kafka/fetched_batch.rb
|
@@ -379,6 +387,7 @@ files:
|
|
379
387
|
- lib/kafka/gzip_codec.rb
|
380
388
|
- lib/kafka/heartbeat.rb
|
381
389
|
- lib/kafka/instrumenter.rb
|
390
|
+
- lib/kafka/interceptors.rb
|
382
391
|
- lib/kafka/lz4_codec.rb
|
383
392
|
- lib/kafka/message_buffer.rb
|
384
393
|
- lib/kafka/offset_manager.rb
|
@@ -469,7 +478,7 @@ files:
|
|
469
478
|
- ruby-kafka.gemspec
|
470
479
|
homepage: https://github.com/zendesk/ruby-kafka
|
471
480
|
licenses:
|
472
|
-
- Apache
|
481
|
+
- Apache-2.0
|
473
482
|
metadata: {}
|
474
483
|
post_install_message:
|
475
484
|
rdoc_options: []
|
@@ -486,8 +495,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
486
495
|
- !ruby/object:Gem::Version
|
487
496
|
version: '0'
|
488
497
|
requirements: []
|
489
|
-
|
490
|
-
rubygems_version: 2.7.6
|
498
|
+
rubygems_version: 3.1.2
|
491
499
|
signing_key:
|
492
500
|
specification_version: 4
|
493
501
|
summary: A client library for the Kafka distributed commit log.
|