ruby-kafka 1.0.0 → 1.1.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/lib/kafka/client.rb +14 -1
- data/lib/kafka/consumer.rb +56 -11
- data/lib/kafka/datadog.rb +6 -0
- data/lib/kafka/fetcher.rb +1 -1
- data/lib/kafka/protocol/metadata_response.rb +1 -1
- data/lib/kafka/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1e5516c0741a1532bd320d8202e4cd23d18af5ddaf9581c6a39c69230b4c59e1
|
4
|
+
data.tar.gz: 66b47c941718a9a3a6e9f0523ec60dc6dd8b96ef2c82fda3571f7d150464cfeb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cb040bc7a76c13f131b59e2a15d9274542a4768595de221198b4e574aeb36ff5095ac14b0737b6a988cd4be7863f4bd44cccc7d2ad48ae2ee3f72f81256b08ca
|
7
|
+
data.tar.gz: 012474c8b6390eb2348906f320caa3759c12d8e9205713cd173f98a1463a432caa8c1c5cd700a2bea059e6601c5482b158d72af1fb199d3f9751f3cb1a3b5451
|
data/CHANGELOG.md
CHANGED
@@ -4,6 +4,14 @@ Changes and additions to the library will be listed here.
|
|
4
4
|
|
5
5
|
## Unreleased
|
6
6
|
|
7
|
+
## 1.1.0
|
8
|
+
|
9
|
+
- Instrument `create_time` from last message in batch (#811).
|
10
|
+
- Add client function for fetching topic replica count (#822).
|
11
|
+
- Allow consumers to refresh the topic lists (#818).
|
12
|
+
- Disconnect after leaving a group (#817).
|
13
|
+
- Use `max_wait_time` as the sleep instead of hardcoded 2 seconds (#825).
|
14
|
+
|
7
15
|
## 1.0.0
|
8
16
|
|
9
17
|
- Add client methods to manage configs (#759)
|
data/lib/kafka/client.rb
CHANGED
@@ -336,6 +336,9 @@ module Kafka
|
|
336
336
|
# @param fetcher_max_queue_size [Integer] max number of items in the fetch queue that
|
337
337
|
# are stored for further processing. Note, that each item in the queue represents a
|
338
338
|
# response from a single broker.
|
339
|
+
# @param refresh_topic_interval [Integer] interval of refreshing the topic list.
|
340
|
+
# If it is 0, the topic list won't be refreshed (default)
|
341
|
+
# If it is n (n > 0), the topic list will be refreshed every n seconds
|
339
342
|
# @return [Consumer]
|
340
343
|
def consumer(
|
341
344
|
group_id:,
|
@@ -345,7 +348,8 @@ module Kafka
|
|
345
348
|
offset_commit_threshold: 0,
|
346
349
|
heartbeat_interval: 10,
|
347
350
|
offset_retention_time: nil,
|
348
|
-
fetcher_max_queue_size: 100
|
351
|
+
fetcher_max_queue_size: 100,
|
352
|
+
refresh_topic_interval: 0
|
349
353
|
)
|
350
354
|
cluster = initialize_cluster
|
351
355
|
|
@@ -399,6 +403,7 @@ module Kafka
|
|
399
403
|
fetcher: fetcher,
|
400
404
|
session_timeout: session_timeout,
|
401
405
|
heartbeat: heartbeat,
|
406
|
+
refresh_topic_interval: refresh_topic_interval
|
402
407
|
)
|
403
408
|
end
|
404
409
|
|
@@ -694,6 +699,14 @@ module Kafka
|
|
694
699
|
@cluster.partitions_for(topic).count
|
695
700
|
end
|
696
701
|
|
702
|
+
# Counts the number of replicas for a topic's partition
|
703
|
+
#
|
704
|
+
# @param topic [String]
|
705
|
+
# @return [Integer] the number of replica nodes for the topic's partition
|
706
|
+
def replica_count_for(topic)
|
707
|
+
@cluster.partitions_for(topic).first.replicas.count
|
708
|
+
end
|
709
|
+
|
697
710
|
# Retrieve the offset of the last message in a partition. If there are no
|
698
711
|
# messages in the partition -1 is returned.
|
699
712
|
#
|
data/lib/kafka/consumer.rb
CHANGED
@@ -44,7 +44,7 @@ module Kafka
|
|
44
44
|
#
|
45
45
|
class Consumer
|
46
46
|
|
47
|
-
def initialize(cluster:, logger:, instrumenter:, group:, fetcher:, offset_manager:, session_timeout:, heartbeat:)
|
47
|
+
def initialize(cluster:, logger:, instrumenter:, group:, fetcher:, offset_manager:, session_timeout:, heartbeat:, refresh_topic_interval: 0)
|
48
48
|
@cluster = cluster
|
49
49
|
@logger = TaggedLogger.new(logger)
|
50
50
|
@instrumenter = instrumenter
|
@@ -53,6 +53,7 @@ module Kafka
|
|
53
53
|
@session_timeout = session_timeout
|
54
54
|
@fetcher = fetcher
|
55
55
|
@heartbeat = heartbeat
|
56
|
+
@refresh_topic_interval = refresh_topic_interval
|
56
57
|
|
57
58
|
@pauses = Hash.new {|h, k|
|
58
59
|
h[k] = Hash.new {|h2, k2|
|
@@ -73,6 +74,15 @@ module Kafka
|
|
73
74
|
# when user commits message other than last in a batch, this would make ruby-kafka refetch
|
74
75
|
# some already consumed messages
|
75
76
|
@current_offsets = Hash.new { |h, k| h[k] = {} }
|
77
|
+
|
78
|
+
# Map storing subscribed topics with their configuration
|
79
|
+
@subscribed_topics = Concurrent::Map.new
|
80
|
+
|
81
|
+
# Set storing topics that matched topics in @subscribed_topics
|
82
|
+
@matched_topics = Set.new
|
83
|
+
|
84
|
+
# Whether join_group must be executed again because new topics are added
|
85
|
+
@join_group_for_new_topics = false
|
76
86
|
end
|
77
87
|
|
78
88
|
# Subscribes the consumer to a topic.
|
@@ -97,13 +107,12 @@ module Kafka
|
|
97
107
|
def subscribe(topic_or_regex, default_offset: nil, start_from_beginning: true, max_bytes_per_partition: 1048576)
|
98
108
|
default_offset ||= start_from_beginning ? :earliest : :latest
|
99
109
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
end
|
110
|
+
@subscribed_topics[topic_or_regex] = {
|
111
|
+
default_offset: default_offset,
|
112
|
+
start_from_beginning: start_from_beginning,
|
113
|
+
max_bytes_per_partition: max_bytes_per_partition
|
114
|
+
}
|
115
|
+
scan_for_subscribing
|
107
116
|
|
108
117
|
nil
|
109
118
|
end
|
@@ -116,7 +125,6 @@ module Kafka
|
|
116
125
|
def stop
|
117
126
|
@running = false
|
118
127
|
@fetcher.stop
|
119
|
-
@cluster.disconnect
|
120
128
|
end
|
121
129
|
|
122
130
|
# Pause processing of a specific topic partition.
|
@@ -308,6 +316,7 @@ module Kafka
|
|
308
316
|
topic: batch.topic,
|
309
317
|
partition: batch.partition,
|
310
318
|
last_offset: batch.last_offset,
|
319
|
+
last_create_time: batch.messages.last.try(:create_time),
|
311
320
|
offset_lag: batch.offset_lag,
|
312
321
|
highwater_mark_offset: batch.highwater_mark_offset,
|
313
322
|
message_count: batch.messages.count,
|
@@ -401,6 +410,7 @@ module Kafka
|
|
401
410
|
while running?
|
402
411
|
begin
|
403
412
|
@instrumenter.instrument("loop.consumer") do
|
413
|
+
refresh_topic_list_if_enabled
|
404
414
|
yield
|
405
415
|
end
|
406
416
|
rescue HeartbeatError
|
@@ -432,6 +442,7 @@ module Kafka
|
|
432
442
|
# important that members explicitly tell Kafka when they're leaving.
|
433
443
|
make_final_offsets_commit!
|
434
444
|
@group.leave rescue nil
|
445
|
+
@cluster.disconnect
|
435
446
|
@running = false
|
436
447
|
@logger.pop_tags
|
437
448
|
end
|
@@ -452,6 +463,8 @@ module Kafka
|
|
452
463
|
end
|
453
464
|
|
454
465
|
def join_group
|
466
|
+
@join_group_for_new_topics = false
|
467
|
+
|
455
468
|
old_generation_id = @group.generation_id
|
456
469
|
|
457
470
|
@group.join
|
@@ -513,11 +526,19 @@ module Kafka
|
|
513
526
|
end
|
514
527
|
end
|
515
528
|
|
529
|
+
def refresh_topic_list_if_enabled
|
530
|
+
return if @refresh_topic_interval <= 0
|
531
|
+
return if @refreshed_at && @refreshed_at + @refresh_topic_interval > Time.now
|
532
|
+
|
533
|
+
scan_for_subscribing
|
534
|
+
@refreshed_at = Time.now
|
535
|
+
end
|
536
|
+
|
516
537
|
def fetch_batches
|
517
538
|
# Return early if the consumer has been stopped.
|
518
539
|
return [] if shutting_down?
|
519
540
|
|
520
|
-
join_group
|
541
|
+
join_group if !@group.member? || @join_group_for_new_topics
|
521
542
|
|
522
543
|
trigger_heartbeat
|
523
544
|
|
@@ -525,7 +546,7 @@ module Kafka
|
|
525
546
|
|
526
547
|
if !@fetcher.data?
|
527
548
|
@logger.debug "No batches to process"
|
528
|
-
sleep 2
|
549
|
+
sleep(@fetcher.max_wait_time || 2)
|
529
550
|
[]
|
530
551
|
else
|
531
552
|
tag, message = @fetcher.poll
|
@@ -571,10 +592,34 @@ module Kafka
|
|
571
592
|
end
|
572
593
|
end
|
573
594
|
|
595
|
+
def scan_for_subscribing
|
596
|
+
@subscribed_topics.each do |topic_or_regex, config|
|
597
|
+
default_offset = config.fetch(:default_offset)
|
598
|
+
start_from_beginning = config.fetch(:start_from_beginning)
|
599
|
+
max_bytes_per_partition = config.fetch(:max_bytes_per_partition)
|
600
|
+
if topic_or_regex.is_a?(Regexp)
|
601
|
+
subscribe_to_regex(topic_or_regex, default_offset, start_from_beginning, max_bytes_per_partition)
|
602
|
+
else
|
603
|
+
subscribe_to_topic(topic_or_regex, default_offset, start_from_beginning, max_bytes_per_partition)
|
604
|
+
end
|
605
|
+
end
|
606
|
+
end
|
607
|
+
|
608
|
+
def subscribe_to_regex(topic_regex, default_offset, start_from_beginning, max_bytes_per_partition)
|
609
|
+
cluster_topics.select { |topic| topic =~ topic_regex }.each do |topic|
|
610
|
+
subscribe_to_topic(topic, default_offset, start_from_beginning, max_bytes_per_partition)
|
611
|
+
end
|
612
|
+
end
|
613
|
+
|
574
614
|
def subscribe_to_topic(topic, default_offset, start_from_beginning, max_bytes_per_partition)
|
615
|
+
return if @matched_topics.include?(topic)
|
616
|
+
@matched_topics.add(topic)
|
617
|
+
@join_group_for_new_topics = true
|
618
|
+
|
575
619
|
@group.subscribe(topic)
|
576
620
|
@offset_manager.set_default_offset(topic, default_offset)
|
577
621
|
@fetcher.subscribe(topic, max_bytes_per_partition: max_bytes_per_partition)
|
622
|
+
@cluster.mark_as_stale!
|
578
623
|
end
|
579
624
|
|
580
625
|
def cluster_topics
|
data/lib/kafka/datadog.rb
CHANGED
@@ -160,6 +160,8 @@ module Kafka
|
|
160
160
|
def process_batch(event)
|
161
161
|
offset = event.payload.fetch(:last_offset)
|
162
162
|
messages = event.payload.fetch(:message_count)
|
163
|
+
create_time = event.payload.fetch(:last_create_time)
|
164
|
+
time_lag = create_time && ((Time.now - create_time) * 1000).to_i
|
163
165
|
|
164
166
|
tags = {
|
165
167
|
client: event.payload.fetch(:client_id),
|
@@ -176,6 +178,10 @@ module Kafka
|
|
176
178
|
end
|
177
179
|
|
178
180
|
gauge("consumer.offset", offset, tags: tags)
|
181
|
+
|
182
|
+
if time_lag
|
183
|
+
gauge("consumer.time_lag", time_lag, tags: tags)
|
184
|
+
end
|
179
185
|
end
|
180
186
|
|
181
187
|
def fetch_batch(event)
|
data/lib/kafka/fetcher.rb
CHANGED
data/lib/kafka/version.rb
CHANGED
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: 1.0.
|
4
|
+
version: 1.1.0.beta1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Schierbeck
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-05-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: digest-crc
|
@@ -489,9 +489,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
489
489
|
version: 2.1.0
|
490
490
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
491
491
|
requirements:
|
492
|
-
- - "
|
492
|
+
- - ">"
|
493
493
|
- !ruby/object:Gem::Version
|
494
|
-
version:
|
494
|
+
version: 1.3.1
|
495
495
|
requirements: []
|
496
496
|
rubyforge_project:
|
497
497
|
rubygems_version: 2.7.6
|