karafka 2.0.13 → 2.0.15
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/.github/workflows/ci.yml +4 -4
- data/.rspec +2 -0
- data/CHANGELOG.md +11 -0
- data/Gemfile.lock +1 -1
- data/bin/integrations +7 -6
- data/lib/karafka/admin.rb +4 -1
- data/lib/karafka/connection/client.rb +2 -4
- data/lib/karafka/embedded.rb +23 -0
- data/lib/karafka/instrumentation/vendors/datadog/dashboard.json +1 -1
- data/lib/karafka/instrumentation/vendors/datadog/listener.rb +23 -1
- data/lib/karafka/pro/processing/partitioner.rb +11 -16
- data/lib/karafka/process.rb +7 -0
- data/lib/karafka/server.rb +9 -2
- data/lib/karafka/status.rb +3 -0
- data/lib/karafka/time_trackers/pause.rb +28 -9
- data/lib/karafka/time_trackers/poll.rb +2 -1
- data/lib/karafka/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +3 -2
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 79c991a988c67b681c8bdf16d06d61b3781be5bbc070d23a1258ea0152058d41
|
4
|
+
data.tar.gz: 478d2155761e7fa4bb6b766a5fd598f3524b5810edddc36229185bb9ce396c3c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d9a3ba7e201947f0ced657eb61aa8f4af348f70a85167a9194f34039d070248551aa3a09d270930ccac399d774fc89305a4f2bc36da715066cd789997fbb40d9
|
7
|
+
data.tar.gz: b5cf1015aa851c7ab78fa89e2b2317085c18f24c8b5a03f5b82c8c3c7ac2ef95fe6a1888defc97f62492c107c2b0b2cd1b72bbe5811fb99dd92e39e93f912608
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/.github/workflows/ci.yml
CHANGED
@@ -18,7 +18,7 @@ jobs:
|
|
18
18
|
strategy:
|
19
19
|
fail-fast: false
|
20
20
|
steps:
|
21
|
-
- uses: actions/checkout@
|
21
|
+
- uses: actions/checkout@v3
|
22
22
|
with:
|
23
23
|
fetch-depth: 0
|
24
24
|
|
@@ -39,7 +39,7 @@ jobs:
|
|
39
39
|
strategy:
|
40
40
|
fail-fast: false
|
41
41
|
steps:
|
42
|
-
- uses: actions/checkout@
|
42
|
+
- uses: actions/checkout@v3
|
43
43
|
with:
|
44
44
|
fetch-depth: 0
|
45
45
|
- name: Run Coditsu
|
@@ -64,7 +64,7 @@ jobs:
|
|
64
64
|
- ruby: '3.1'
|
65
65
|
coverage: 'true'
|
66
66
|
steps:
|
67
|
-
- uses: actions/checkout@
|
67
|
+
- uses: actions/checkout@v3
|
68
68
|
- name: Install package dependencies
|
69
69
|
run: "[ -e $APT_DEPS ] || sudo apt-get install -y --no-install-recommends $APT_DEPS"
|
70
70
|
|
@@ -97,7 +97,7 @@ jobs:
|
|
97
97
|
- ruby: '3.1'
|
98
98
|
coverage: 'true'
|
99
99
|
steps:
|
100
|
-
- uses: actions/checkout@
|
100
|
+
- uses: actions/checkout@v3
|
101
101
|
- name: Install package dependencies
|
102
102
|
run: "[ -e $APT_DEPS ] || sudo apt-get install -y --no-install-recommends $APT_DEPS"
|
103
103
|
|
data/.rspec
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,16 @@
|
|
1
1
|
# Karafka framework changelog
|
2
2
|
|
3
|
+
## 2.0.15 (2022-10-20)
|
4
|
+
- Sanitize admin config prior to any admin action.
|
5
|
+
- Make messages partitioner outcome for virtual partitions consistently distributed in regards to concurrency.
|
6
|
+
- Improve DataDog/StatsD metrics reporting by reporting per topic partition lags and trends.
|
7
|
+
- Replace synchronous offset commit with async on resuming paused partition (#1087).
|
8
|
+
|
9
|
+
## 2.0.14 (2022-10-16)
|
10
|
+
- Prevent consecutive stop signals from starting multiple supervision shutdowns.
|
11
|
+
- Provide `Karafka::Embedded` to simplify the start/stop process when running Karafka from within other process (Puma, Sidekiq, etc).
|
12
|
+
- Fix a race condition when un-pausing a long-running-job exactly upon listener resuming would crash the listener loop (#1072).
|
13
|
+
|
3
14
|
## 2.0.13 (2022-10-14)
|
4
15
|
- Early exit upon attempts to commit current or earlier offset twice.
|
5
16
|
- Add more integration specs covering edge cases.
|
data/Gemfile.lock
CHANGED
data/bin/integrations
CHANGED
@@ -24,7 +24,7 @@ ROOT_PATH = Pathname.new(File.expand_path(File.join(File.dirname(__FILE__), '../
|
|
24
24
|
# When the value is high, there's a problem with thread allocation on Github CI, tht is why
|
25
25
|
# we limit it. Locally we can run a lot of those, as many of them have sleeps and do not use a lot
|
26
26
|
# of CPU
|
27
|
-
CONCURRENCY = ENV.key?('CI') ?
|
27
|
+
CONCURRENCY = ENV.key?('CI') ? 4 : Etc.nprocessors * 2
|
28
28
|
|
29
29
|
# How may bytes do we want to keep from the stdout in the buffer for when we need to print it
|
30
30
|
MAX_BUFFER_OUTPUT = 51_200
|
@@ -39,10 +39,10 @@ class Scenario
|
|
39
39
|
# This includes exactly those
|
40
40
|
EXIT_CODES = {
|
41
41
|
default: [0],
|
42
|
-
'consumption/
|
43
|
-
'shutdown/
|
44
|
-
'shutdown/
|
45
|
-
'shutdown/
|
42
|
+
'consumption/worker_critical_error_behaviour_spec.rb' => [0, 2].freeze,
|
43
|
+
'shutdown/on_hanging_jobs_and_a_shutdown_spec.rb' => [2].freeze,
|
44
|
+
'shutdown/on_hanging_on_shutdown_job_and_a_shutdown_spec.rb' => [2].freeze,
|
45
|
+
'shutdown/on_hanging_listener_and_shutdown_spec.rb' => [2].freeze
|
46
46
|
}.freeze
|
47
47
|
|
48
48
|
private_constant :MAX_RUN_TIME, :EXIT_CODES
|
@@ -202,7 +202,7 @@ class Scenario
|
|
202
202
|
end
|
203
203
|
|
204
204
|
# Load all the specs
|
205
|
-
specs = Dir[ROOT_PATH.join('spec/integrations
|
205
|
+
specs = Dir[ROOT_PATH.join('spec/integrations/**/*_spec.rb')]
|
206
206
|
|
207
207
|
# If filters is provided, apply
|
208
208
|
# Allows to provide several filters one after another and applies all of them
|
@@ -210,6 +210,7 @@ ARGV.each do |filter|
|
|
210
210
|
specs.delete_if { |name| !name.include?(filter) }
|
211
211
|
end
|
212
212
|
|
213
|
+
|
213
214
|
raise ArgumentError, "No integration specs with filters: #{ARGV.join(', ')}" if specs.empty?
|
214
215
|
|
215
216
|
# Randomize order
|
data/lib/karafka/admin.rb
CHANGED
@@ -52,7 +52,10 @@ module Karafka
|
|
52
52
|
|
53
53
|
# Creates admin instance and yields it. After usage it closes the admin instance
|
54
54
|
def with_admin
|
55
|
-
|
55
|
+
# Admin needs a producer config
|
56
|
+
config = Karafka::Setup::AttributesMap.producer(Karafka::App.config.kafka.dup)
|
57
|
+
|
58
|
+
admin = ::Rdkafka::Config.new(config).admin
|
56
59
|
result = yield(admin)
|
57
60
|
result
|
58
61
|
ensure
|
@@ -179,10 +179,8 @@ module Karafka
|
|
179
179
|
|
180
180
|
return if @closed
|
181
181
|
|
182
|
-
#
|
183
|
-
|
184
|
-
# We can skip performance penalty since resuming should not happen too often
|
185
|
-
internal_commit_offsets(async: false)
|
182
|
+
# We now commit offsets on rebalances, thus we can do it async just to make sure
|
183
|
+
internal_commit_offsets(async: true)
|
186
184
|
|
187
185
|
# If we were not able, let's try to reuse the one we have (if we have)
|
188
186
|
tpl = topic_partition_list(topic, partition) || @paused_tpls[topic][partition]
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Karafka
|
4
|
+
# Allows to start and stop Karafka as part of a different process
|
5
|
+
module Embedded
|
6
|
+
class << self
|
7
|
+
# Starts Karafka without supervision and without ownership of signals in a background thread
|
8
|
+
# so it won't interrupt other things running
|
9
|
+
def start
|
10
|
+
Thread.new { Karafka::Server.start }
|
11
|
+
end
|
12
|
+
|
13
|
+
# Stops Karafka upon any event
|
14
|
+
#
|
15
|
+
# @note This method is blocking because we want to wait until Karafka is stopped with final
|
16
|
+
# process shutdown
|
17
|
+
def stop
|
18
|
+
# Stop needs to be blocking to wait for all the things to finalize
|
19
|
+
Karafka::Server.stop
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -1 +1 @@
|
|
1
|
-
{"title":"Karafka monitoring dashboard","description":"","widgets":[{"id":7444969424381053,"definition":{"title":"Stability & errors","type":"group","show_title":true,"layout_type":"ordered","widgets":[{"id":8304008422587936,"definition":{"title":"Client connects and disconnects","title_size":"16","title_align":"left","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"alias":"Connects","formula":"query1"},{"alias":"Disconnects","formula":"query2"}],"response_format":"timeseries","queries":[{"query":"sum:karafka.connection.connects{*} by {host}.as_count()","data_source":"metrics","name":"query1"},{"query":"sum:karafka.connection.disconnects{*} by {host}.as_count()","data_source":"metrics","name":"query2"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"bars"}]},"layout":{"x":0,"y":0,"width":4,"height":2}},{"id":3722865443336921,"definition":{"title":"Errors encountered (any)","title_size":"16","title_align":"left","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"alias":"in-karafka errors","formula":"query1"},{"alias":"librdkafka consume errors","formula":"query2"},{"alias":"librdkafka receive errors","formula":"query3"}],"response_format":"timeseries","queries":[{"query":"sum:karafka.error_occurred{*} by {type}.as_count()","data_source":"metrics","name":"query1"},{"query":"sum:karafka.consume.errors{*}.as_count()","data_source":"metrics","name":"query2"},{"query":"sum:karafka.receive.errors{*}.as_count()","data_source":"metrics","name":"query3"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}]},"layout":{"x":4,"y":0,"width":4,"height":2}},{"id":5477381252952760,"definition":{"title":"Processing errors","title_size":"16","title_align":"left","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"formula":"query1"}],"response_format":"timeseries","queries":[{"query":"sum:karafka.error_occurred{type:consumer.consume.error} by {partition,topic}.as_count()","data_source":"metrics","name":"query1"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}]},"layout":{"x":8,"y":0,"width":4,"height":2}},{"id":2357301680769076,"definition":{"title":"Processing errors rate per topic","title_size":"16","title_align":"left","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"alias":"% error rate per topic","formula":"(query1 / (query1 + query2)) * 100"}],"response_format":"timeseries","queries":[{"query":"sum:karafka.error_occurred{type:consumer.consume.error} by {topic,partition}.as_count()","data_source":"metrics","name":"query1"},{"query":"sum:karafka.consumer.batches{*} by {topic,partition}.as_count()","data_source":"metrics","name":"query2"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"bars"}]},"layout":{"x":0,"y":2,"width":4,"height":2}},{"id":3902930069982135,"definition":{"title":"Batches successful vs failures","title_size":"16","title_align":"left","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"alias":"Successfully processed batch","formula":"query1"},{"alias":"Batch processing with error","formula":"query2"}],"response_format":"timeseries","queries":[{"query":"sum:karafka.consumer.batches{*} by {partition,topic}.as_count()","data_source":"metrics","name":"query1"},{"query":"avg:karafka.error_occurred{type:consumer.consume.error} by {partition,topic}.as_count()","data_source":"metrics","name":"query2"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}]},"layout":{"x":4,"y":2,"width":4,"height":2}},{"id":718749162159145,"definition":{"title":"Consumer instances revocations and shutdowns","title_size":"16","title_align":"left","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"alias":"Consumer instances revokations","formula":"query1"},{"alias":"Consumer instances shutdowns","formula":"query2"}],"response_format":"timeseries","queries":[{"query":"sum:karafka.consumer.revoked{*}.as_count()","data_source":"metrics","name":"query1"},{"query":"sum:karafka.consumer.shutdown{*}.as_count()","data_source":"metrics","name":"query2"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}]},"layout":{"x":8,"y":2,"width":4,"height":2}}]},"layout":{"x":0,"y":0,"width":12,"height":5}},{"id":5988438511387100,"definition":{"title":"Workers poll","type":"group","show_title":true,"layout_type":"ordered","widgets":[{"id":8769294644934352,"definition":{"title":"Enqueued jobs","title_size":"16","title_align":"left","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"alias":"Enqueued jobs","formula":"query1"}],"response_format":"timeseries","queries":[{"query":"sum:karafka.worker.enqueued_jobs.avg{*}","data_source":"metrics","name":"query1"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}]},"layout":{"x":0,"y":0,"width":4,"height":2}},{"id":2714502141463873,"definition":{"title":"Workers usage","title_size":"16","title_align":"left","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"alias":"Busy workers (p95)","formula":"query1"},{"alias":"Total workers","formula":"query2"}],"response_format":"timeseries","queries":[{"query":"sum:karafka.worker.processing.95percentile{*}","data_source":"metrics","name":"query1"},{"query":"sum:karafka.worker.total_threads{*}","data_source":"metrics","name":"query2"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}]},"layout":{"x":4,"y":0,"width":4,"height":2}},{"id":5370086629441984,"definition":{"title":"Workers % utilization","title_size":"16","title_align":"left","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"alias":"% workers utilization","formula":"(query1 / query2) * 100"}],"response_format":"timeseries","queries":[{"query":"sum:karafka.worker.processing.95percentile{*}","data_source":"metrics","name":"query1"},{"query":"sum:karafka.worker.total_threads{*}","data_source":"metrics","name":"query2"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}]},"layout":{"x":8,"y":0,"width":4,"height":2}}]},"layout":{"x":0,"y":5,"width":12,"height":3}},{"id":8544040083223278,"definition":{"title":"Throughput ","type":"group","show_title":true,"layout_type":"ordered","widgets":[{"id":3740207481939733,"definition":{"title":"Offset lag changes","title_size":"16","title_align":"left","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"formula":"derivative(query1)"}],"response_format":"timeseries","queries":[{"query":"max:karafka.consumer.offset{*} by {topic,partition}","data_source":"metrics","name":"query1"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}]},"layout":{"x":0,"y":0,"width":4,"height":2}},{"id":6319110548544878,"definition":{"title":"Batches processed per topic","title_size":"16","title_align":"left","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"formula":"query1"}],"response_format":"timeseries","queries":[{"query":"sum:karafka.consumer.batches{*} by {partition,topic}.as_count()","data_source":"metrics","name":"query1"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}]},"layout":{"x":4,"y":0,"width":4,"height":2}},{"id":6232784865331443,"definition":{"title":"Messages consumed per topic","title_size":"16","title_align":"left","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"alias":"Messages consumed","formula":"query1"},{"alias":"Average batch size","formula":"query1 / query2"}],"response_format":"timeseries","queries":[{"query":"sum:karafka.consumer.messages{*} by {partition,topic}.as_count()","data_source":"metrics","name":"query1"},{"query":"sum:karafka.consumer.batches{*} by {partition,topic}.as_count()","data_source":"metrics","name":"query2"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}]},"layout":{"x":8,"y":0,"width":4,"height":2}},{"id":2321394598982770,"definition":{"title":"Consumption lag (in seconds)","title_size":"16","title_align":"left","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"alias":"Consumption lag in s (max)","formula":"query2 / 1000"},{"alias":"Consumption lag in s (avg)","formula":"query3 / 1000"},{"alias":"Consumption lag in s (p95)","formula":"query1 / 1000"}],"response_format":"timeseries","queries":[{"query":"max:karafka.consumer.consumption_lag.max{*}","data_source":"metrics","name":"query2"},{"query":"max:karafka.consumer.consumption_lag.avg{*}","data_source":"metrics","name":"query3"},{"query":"max:karafka.consumer.consumption_lag.95percentile{*}","data_source":"metrics","name":"query1"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}]},"layout":{"x":0,"y":2,"width":4,"height":2}},{"id":1062074781483741,"definition":{"title":"Processing lag (in ms)","title_size":"16","title_align":"left","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"alias":"Processing lag in ms (p95)","formula":"query1"},{"alias":"Processing lag in ms (max)","formula":"query2"},{"alias":"Processing lag in ms (avg)","formula":"query3"}],"response_format":"timeseries","queries":[{"query":"max:karafka.consumer.processing_lag.95percentile{*}","data_source":"metrics","name":"query1"},{"query":"max:karafka.consumer.processing_lag.max{*}","data_source":"metrics","name":"query2"},{"query":"max:karafka.consumer.processing_lag.avg{*}","data_source":"metrics","name":"query3"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}]},"layout":{"x":4,"y":2,"width":4,"height":2}},{"id":7497794728674267,"definition":{"title":"Batch processing time","title_size":"16","title_align":"left","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"formula":"query1"},{"formula":"query2"},{"formula":"query3"}],"response_format":"timeseries","queries":[{"query":"max:karafka.consumer.consumed.time_taken.95percentile{*} by {topic,partition}","data_source":"metrics","name":"query1"},{"query":"max:karafka.consumer.consumed.time_taken.max{*} by {topic,partition}","data_source":"metrics","name":"query2"},{"query":"max:karafka.consumer.consumed.time_taken.avg{*} by {topic,partition}","data_source":"metrics","name":"query3"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}]},"layout":{"x":8,"y":2,"width":4,"height":2}},{"id":4192833027984161,"definition":{"title":"Batch size per topic","title_size":"16","title_align":"left","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"alias":"Batch size p95","formula":"query1"},{"alias":"Batch size avg","formula":"query2"},{"alias":"Batch size max","formula":"query3"}],"response_format":"timeseries","queries":[{"query":"sum:karafka.consumer.batch_size.95percentile{*} by {partition,topic}","data_source":"metrics","name":"query1"},{"query":"sum:karafka.consumer.batch_size.avg{*} by {partition,topic}","data_source":"metrics","name":"query2"},{"query":"sum:karafka.consumer.batch_size.max{*} by {partition,topic}","data_source":"metrics","name":"query3"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}]},"layout":{"x":0,"y":4,"width":4,"height":2}},{"id":4741598444771147,"definition":{"title":"Messages consumed overall","title_size":"16","title_align":"left","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"alias":"Messages consumed","formula":"query1"},{"alias":"Average batch size","formula":"query1 / query2"}],"response_format":"timeseries","queries":[{"query":"sum:karafka.consumer.messages{*}.as_count()","data_source":"metrics","name":"query1"},{"query":"sum:karafka.consumer.batches{*}.as_count()","data_source":"metrics","name":"query2"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}]},"layout":{"x":4,"y":4,"width":4,"height":2}},{"id":4502534794102513,"definition":{"title":"Polling times (ms)","title_size":"16","title_align":"left","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"time":{},"type":"timeseries","requests":[{"formulas":[{"alias":"p95 ms polling time","formula":"query1"},{"alias":"max ms polling time","formula":"query2"},{"alias":"average ms polling time","formula":"query3"}],"queries":[{"name":"query1","data_source":"metrics","query":"avg:karafka.listener.polling.time_taken.95percentile{*}"},{"name":"query2","data_source":"metrics","query":"avg:karafka.listener.polling.time_taken.max{*}"},{"name":"query3","data_source":"metrics","query":"avg:karafka.listener.polling.time_taken.avg{*}"}],"response_format":"timeseries","style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}]},"layout":{"x":8,"y":4,"width":4,"height":2}}]},"layout":{"x":0,"y":0,"width":12,"height":7,"is_column_break":true}}],"template_variables":[],"layout_type":"ordered","is_read_only":false,"notify_list":[],"reflow_type":"fixed","id":"s3u-z47-i6u"}
|
1
|
+
{"title":"Karafka monitoring dashboard","description":"","widgets":[{"id":5988438511387100,"definition":{"title":"Workers poll","type":"group","show_title":true,"layout_type":"ordered","widgets":[{"id":8769294644934352,"definition":{"title":"Enqueued jobs","title_size":"16","title_align":"left","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"alias":"Enqueued jobs","formula":"query1"}],"response_format":"timeseries","queries":[{"query":"sum:karafka.worker.enqueued_jobs.avg{*}","data_source":"metrics","name":"query1"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}]},"layout":{"x":0,"y":0,"width":4,"height":2}},{"id":2714502141463873,"definition":{"title":"Workers usage","title_size":"16","title_align":"left","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"alias":"Busy workers (p95)","formula":"query1"},{"alias":"Total workers","formula":"query2"}],"response_format":"timeseries","queries":[{"query":"sum:karafka.worker.processing.95percentile{*}","data_source":"metrics","name":"query1"},{"query":"sum:karafka.worker.total_threads{*}","data_source":"metrics","name":"query2"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}]},"layout":{"x":4,"y":0,"width":4,"height":2}},{"id":5370086629441984,"definition":{"title":"Workers % utilization","title_size":"16","title_align":"left","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"alias":"% workers utilization","formula":"(query1 / query2) * 100"}],"response_format":"timeseries","queries":[{"query":"sum:karafka.worker.processing.95percentile{*}","data_source":"metrics","name":"query1"},{"query":"sum:karafka.worker.total_threads{*}","data_source":"metrics","name":"query2"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}]},"layout":{"x":8,"y":0,"width":4,"height":2}}]},"layout":{"x":0,"y":0,"width":12,"height":3}},{"id":7444969424381053,"definition":{"title":"Stability & errors","type":"group","show_title":true,"layout_type":"ordered","widgets":[{"id":8304008422587936,"definition":{"title":"Client connects and disconnects","title_size":"16","title_align":"left","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"alias":"Connects","formula":"query1"},{"alias":"Disconnects","formula":"query2"}],"response_format":"timeseries","queries":[{"query":"sum:karafka.connection.connects{*} by {host}.as_count()","data_source":"metrics","name":"query1"},{"query":"sum:karafka.connection.disconnects{*} by {host}.as_count()","data_source":"metrics","name":"query2"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"bars"}]},"layout":{"x":0,"y":0,"width":4,"height":2}},{"id":3722865443336921,"definition":{"title":"Errors encountered (any)","title_size":"16","title_align":"left","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"alias":"in-karafka errors","formula":"query1"},{"alias":"librdkafka consume errors","formula":"query2"},{"alias":"librdkafka receive errors","formula":"query3"}],"response_format":"timeseries","queries":[{"query":"sum:karafka.error_occurred{*} by {type}.as_count()","data_source":"metrics","name":"query1"},{"query":"sum:karafka.consume.errors{*}.as_count()","data_source":"metrics","name":"query2"},{"query":"sum:karafka.receive.errors{*}.as_count()","data_source":"metrics","name":"query3"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}]},"layout":{"x":4,"y":0,"width":4,"height":2}},{"id":5477381252952760,"definition":{"title":"Processing errors","title_size":"16","title_align":"left","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"formula":"query1"}],"response_format":"timeseries","queries":[{"query":"sum:karafka.error_occurred{type:consumer.consume.error} by {partition,topic}.as_count()","data_source":"metrics","name":"query1"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}]},"layout":{"x":8,"y":0,"width":4,"height":2}},{"id":2357301680769076,"definition":{"title":"Processing errors rate per topic","title_size":"16","title_align":"left","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"alias":"% error rate per topic","formula":"(query1 / (query1 + query2)) * 100"}],"response_format":"timeseries","queries":[{"query":"sum:karafka.error_occurred{type:consumer.consume.error} by {topic,partition}.as_count()","data_source":"metrics","name":"query1"},{"query":"sum:karafka.consumer.batches{*} by {topic,partition}.as_count()","data_source":"metrics","name":"query2"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"bars"}]},"layout":{"x":0,"y":2,"width":4,"height":2}},{"id":3902930069982135,"definition":{"title":"Batches successful vs failures","title_size":"16","title_align":"left","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"alias":"Successfully processed batch","formula":"query1"},{"alias":"Batch processing with error","formula":"query2"}],"response_format":"timeseries","queries":[{"query":"sum:karafka.consumer.batches{*} by {partition,topic}.as_count()","data_source":"metrics","name":"query1"},{"query":"avg:karafka.error_occurred{type:consumer.consume.error} by {partition,topic}.as_count()","data_source":"metrics","name":"query2"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}]},"layout":{"x":4,"y":2,"width":4,"height":2}},{"id":718749162159145,"definition":{"title":"Consumer instances revocations and shutdowns","title_size":"16","title_align":"left","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"alias":"Consumer instances revokations","formula":"query1"},{"alias":"Consumer instances shutdowns","formula":"query2"}],"response_format":"timeseries","queries":[{"query":"sum:karafka.consumer.revoked{*}.as_count()","data_source":"metrics","name":"query1"},{"query":"sum:karafka.consumer.shutdown{*}.as_count()","data_source":"metrics","name":"query2"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}]},"layout":{"x":8,"y":2,"width":4,"height":2}}]},"layout":{"x":0,"y":3,"width":12,"height":5}},{"id":7288186528768428,"definition":{"title":"Topics overview","type":"group","show_title":true,"layout_type":"ordered","widgets":[{"id":1533435157804573,"definition":{"title":"Topics lags","title_size":"16","title_align":"left","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"time":{},"type":"timeseries","requests":[{"formulas":[{"formula":"query1"}],"queries":[{"name":"query1","data_source":"metrics","query":"avg:karafka.consumer.lags{*} by {partition,topic}"}],"response_format":"timeseries","style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}]},"layout":{"x":0,"y":0,"width":6,"height":2}},{"id":1411506453982604,"definition":{"title":"Topics lag trends","title_size":"16","title_align":"left","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"time":{},"type":"timeseries","requests":[{"formulas":[{"formula":"query1"}],"queries":[{"name":"query1","data_source":"metrics","query":"avg:karafka.consumer.lags_delta{*} by {partition,topic}"}],"response_format":"timeseries","style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}]},"layout":{"x":6,"y":0,"width":6,"height":2}}]},"layout":{"x":0,"y":0,"width":12,"height":3,"is_column_break":true}},{"id":8544040083223278,"definition":{"title":"Throughput ","type":"group","show_title":true,"layout_type":"ordered","widgets":[{"id":3740207481939733,"definition":{"title":"Offset lag changes","title_size":"16","title_align":"left","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"formula":"derivative(query1)"}],"response_format":"timeseries","queries":[{"query":"max:karafka.consumer.offset{*} by {topic,partition}","data_source":"metrics","name":"query1"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}]},"layout":{"x":0,"y":0,"width":4,"height":2}},{"id":6319110548544878,"definition":{"title":"Batches processed per topic","title_size":"16","title_align":"left","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"formula":"query1"}],"response_format":"timeseries","queries":[{"query":"sum:karafka.consumer.batches{*} by {partition,topic}.as_count()","data_source":"metrics","name":"query1"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}]},"layout":{"x":4,"y":0,"width":4,"height":2}},{"id":6232784865331443,"definition":{"title":"Messages consumed per topic","title_size":"16","title_align":"left","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"alias":"Messages consumed","formula":"query1"},{"alias":"Average batch size","formula":"query1 / query2"}],"response_format":"timeseries","queries":[{"query":"sum:karafka.consumer.messages{*} by {partition,topic}.as_count()","data_source":"metrics","name":"query1"},{"query":"sum:karafka.consumer.batches{*} by {partition,topic}.as_count()","data_source":"metrics","name":"query2"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}]},"layout":{"x":8,"y":0,"width":4,"height":2}},{"id":2321394598982770,"definition":{"title":"Consumption lag (in seconds)","title_size":"16","title_align":"left","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"alias":"Consumption lag in s (max)","formula":"query2 / 1000"},{"alias":"Consumption lag in s (avg)","formula":"query3 / 1000"},{"alias":"Consumption lag in s (p95)","formula":"query1 / 1000"}],"response_format":"timeseries","queries":[{"query":"max:karafka.consumer.consumption_lag.max{*}","data_source":"metrics","name":"query2"},{"query":"max:karafka.consumer.consumption_lag.avg{*}","data_source":"metrics","name":"query3"},{"query":"max:karafka.consumer.consumption_lag.95percentile{*}","data_source":"metrics","name":"query1"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}]},"layout":{"x":0,"y":2,"width":4,"height":2}},{"id":1062074781483741,"definition":{"title":"Processing lag (in ms)","title_size":"16","title_align":"left","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"alias":"Processing lag in ms (p95)","formula":"query1"},{"alias":"Processing lag in ms (max)","formula":"query2"},{"alias":"Processing lag in ms (avg)","formula":"query3"}],"response_format":"timeseries","queries":[{"query":"max:karafka.consumer.processing_lag.95percentile{*}","data_source":"metrics","name":"query1"},{"query":"max:karafka.consumer.processing_lag.max{*}","data_source":"metrics","name":"query2"},{"query":"max:karafka.consumer.processing_lag.avg{*}","data_source":"metrics","name":"query3"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}]},"layout":{"x":4,"y":2,"width":4,"height":2}},{"id":7497794728674267,"definition":{"title":"Batch processing time","title_size":"16","title_align":"left","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"formula":"query1"},{"formula":"query2"},{"formula":"query3"}],"response_format":"timeseries","queries":[{"query":"max:karafka.consumer.consumed.time_taken.95percentile{*} by {topic,partition}","data_source":"metrics","name":"query1"},{"query":"max:karafka.consumer.consumed.time_taken.max{*} by {topic,partition}","data_source":"metrics","name":"query2"},{"query":"max:karafka.consumer.consumed.time_taken.avg{*} by {topic,partition}","data_source":"metrics","name":"query3"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}]},"layout":{"x":8,"y":2,"width":4,"height":2}},{"id":4192833027984161,"definition":{"title":"Batch size per topic","title_size":"16","title_align":"left","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"alias":"Batch size p95","formula":"query1"},{"alias":"Batch size avg","formula":"query2"},{"alias":"Batch size max","formula":"query3"}],"response_format":"timeseries","queries":[{"query":"sum:karafka.consumer.batch_size.95percentile{*} by {partition,topic}","data_source":"metrics","name":"query1"},{"query":"sum:karafka.consumer.batch_size.avg{*} by {partition,topic}","data_source":"metrics","name":"query2"},{"query":"sum:karafka.consumer.batch_size.max{*} by {partition,topic}","data_source":"metrics","name":"query3"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}]},"layout":{"x":0,"y":4,"width":4,"height":2}},{"id":4741598444771147,"definition":{"title":"Messages consumed overall","title_size":"16","title_align":"left","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"alias":"Messages consumed","formula":"query1"},{"alias":"Average batch size","formula":"query1 / query2"}],"response_format":"timeseries","queries":[{"query":"sum:karafka.consumer.messages{*}.as_count()","data_source":"metrics","name":"query1"},{"query":"sum:karafka.consumer.batches{*}.as_count()","data_source":"metrics","name":"query2"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}]},"layout":{"x":4,"y":4,"width":4,"height":2}},{"id":4502534794102513,"definition":{"title":"Polling times (ms)","title_size":"16","title_align":"left","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"alias":"p95 ms polling time","formula":"query1"},{"alias":"max ms polling time","formula":"query2"},{"alias":"average ms polling time","formula":"query3"}],"response_format":"timeseries","queries":[{"query":"avg:karafka.listener.polling.time_taken.95percentile{*}","data_source":"metrics","name":"query1"},{"query":"avg:karafka.listener.polling.time_taken.max{*}","data_source":"metrics","name":"query2"},{"query":"avg:karafka.listener.polling.time_taken.avg{*}","data_source":"metrics","name":"query3"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}]},"layout":{"x":8,"y":4,"width":4,"height":2}}]},"layout":{"x":0,"y":3,"width":12,"height":7}}],"template_variables":[],"layout_type":"ordered","is_read_only":false,"notify_list":[],"reflow_type":"fixed","id":"s3u-z47-i6u"}
|
@@ -46,7 +46,11 @@ module Karafka
|
|
46
46
|
RdKafkaMetric.new(:count, :brokers, 'connection.disconnects', 'disconnects_d'),
|
47
47
|
RdKafkaMetric.new(:gauge, :brokers, 'network.latency.avg', %w[rtt avg]),
|
48
48
|
RdKafkaMetric.new(:gauge, :brokers, 'network.latency.p95', %w[rtt p95]),
|
49
|
-
RdKafkaMetric.new(:gauge, :brokers, 'network.latency.p99', %w[rtt p99])
|
49
|
+
RdKafkaMetric.new(:gauge, :brokers, 'network.latency.p99', %w[rtt p99]),
|
50
|
+
|
51
|
+
# Topics metrics
|
52
|
+
RdKafkaMetric.new(:gauge, :topics, 'consumer.lags', 'consumer_lag_stored'),
|
53
|
+
RdKafkaMetric.new(:gauge, :topics, 'consumer.lags_delta', 'consumer_lag_stored_d')
|
50
54
|
].freeze
|
51
55
|
|
52
56
|
configure
|
@@ -221,6 +225,24 @@ module Karafka
|
|
221
225
|
tags: default_tags + ["broker:#{broker_statistics['nodename']}"]
|
222
226
|
)
|
223
227
|
end
|
228
|
+
when :topics
|
229
|
+
statistics.fetch('topics').each do |topic_name, topic_values|
|
230
|
+
topic_values['partitions'].each do |partition_name, partition_statistics|
|
231
|
+
next if partition_name == '-1'
|
232
|
+
# Skip until lag info is available
|
233
|
+
next if partition_statistics['consumer_lag'] == -1
|
234
|
+
|
235
|
+
public_send(
|
236
|
+
metric.type,
|
237
|
+
metric.name,
|
238
|
+
partition_statistics.dig(*metric.key_location),
|
239
|
+
tags: default_tags + [
|
240
|
+
"topic:#{topic_name}",
|
241
|
+
"partition:#{partition_name}"
|
242
|
+
]
|
243
|
+
)
|
244
|
+
end
|
245
|
+
end
|
224
246
|
else
|
225
247
|
raise ArgumentError, metric.scope
|
226
248
|
end
|
@@ -25,28 +25,23 @@ module Karafka
|
|
25
25
|
# process the data. With one thread it is not worth partitioning the work as the work
|
26
26
|
# itself will be assigned to one thread (pointless work)
|
27
27
|
if ktopic.virtual_partitions? && ktopic.virtual_partitions.max_partitions > 1
|
28
|
-
# We need to reduce it to
|
28
|
+
# We need to reduce it to the max concurrency, so the group_id is not a direct effect
|
29
29
|
# of the end user action. Otherwise the persistence layer for consumers would cache
|
30
30
|
# it forever and it would cause memory leaks
|
31
|
-
groupings = messages
|
32
|
-
.group_by { |msg| ktopic.virtual_partitions.partitioner.call(msg) }
|
33
|
-
.values
|
34
|
-
|
35
|
-
# Reduce the number of virtual partitions to a size that matches the max_partitions
|
36
|
-
# As mentioned above we cannot use the partitioning keys directly as it could cause
|
37
|
-
# memory leaks
|
38
31
|
#
|
39
|
-
#
|
40
|
-
#
|
41
|
-
#
|
42
|
-
|
43
|
-
|
32
|
+
# This also needs to be consistent because the aggregation here needs to warrant, that
|
33
|
+
# the same partitioned message will always be assigned to the same virtual partition.
|
34
|
+
# Otherwise in case of a window aggregation with VP spanning across several polls, the
|
35
|
+
# data could not be complete.
|
36
|
+
groupings = messages.group_by do |msg|
|
37
|
+
key = ktopic.virtual_partitions.partitioner.call(msg).to_s.sum
|
44
38
|
|
45
|
-
|
46
|
-
groupings << (groupings.pop + groupings.pop).sort_by!(&:offset)
|
39
|
+
key % ktopic.virtual_partitions.max_partitions
|
47
40
|
end
|
48
41
|
|
49
|
-
groupings.
|
42
|
+
groupings.each do |key, messages_group|
|
43
|
+
yield(key, messages_group)
|
44
|
+
end
|
50
45
|
else
|
51
46
|
# When no virtual partitioner, works as regular one
|
52
47
|
yield(0, messages)
|
data/lib/karafka/process.rb
CHANGED
@@ -29,12 +29,19 @@ module Karafka
|
|
29
29
|
# Creates an instance of process and creates empty hash for callbacks
|
30
30
|
def initialize
|
31
31
|
@callbacks = Hash.new { |hsh, key| hsh[key] = [] }
|
32
|
+
@supervised = false
|
32
33
|
end
|
33
34
|
|
34
35
|
# Method catches all HANDLED_SIGNALS and performs appropriate callbacks (if defined)
|
35
36
|
# @note If there are no callbacks, this method will just ignore a given signal that was sent
|
36
37
|
def supervise
|
37
38
|
HANDLED_SIGNALS.each { |signal| trap_signal(signal) }
|
39
|
+
@supervised = true
|
40
|
+
end
|
41
|
+
|
42
|
+
# Is the current process supervised and are trap signals installed
|
43
|
+
def supervised?
|
44
|
+
@supervised
|
38
45
|
end
|
39
46
|
|
40
47
|
private
|
data/lib/karafka/server.rb
CHANGED
@@ -31,6 +31,7 @@ module Karafka
|
|
31
31
|
process.on_sigint { Thread.new { stop } }
|
32
32
|
process.on_sigquit { Thread.new { stop } }
|
33
33
|
process.on_sigterm { Thread.new { stop } }
|
34
|
+
process.supervise
|
34
35
|
|
35
36
|
# Start is blocking until stop is called and when we stop, it will wait until
|
36
37
|
# all of the things are ready to stop
|
@@ -61,7 +62,6 @@ module Karafka
|
|
61
62
|
# @note We don't need to sleep because Karafka::Fetcher is locking and waiting to
|
62
63
|
# finish loop (and it won't happen until we explicitly want to stop)
|
63
64
|
def start
|
64
|
-
process.supervise
|
65
65
|
Karafka::App.run!
|
66
66
|
Karafka::Runner.new.call
|
67
67
|
end
|
@@ -73,6 +73,9 @@ module Karafka
|
|
73
73
|
# lock them forever. If you need to run Karafka shutdown from within workers threads,
|
74
74
|
# please start a separate thread to do so.
|
75
75
|
def stop
|
76
|
+
# Initialize the stopping process only if Karafka was running
|
77
|
+
return unless Karafka::App.running?
|
78
|
+
|
76
79
|
Karafka::App.stop!
|
77
80
|
|
78
81
|
timeout = Karafka::App.config.shutdown_timeout
|
@@ -110,8 +113,12 @@ module Karafka
|
|
110
113
|
|
111
114
|
Karafka::App.producer.close
|
112
115
|
|
116
|
+
# We also do not forcefully terminate everything when running in the embedded mode,
|
117
|
+
# otherwise we would overwrite the shutdown process of the process that started Karafka
|
118
|
+
return unless process.supervised?
|
119
|
+
|
113
120
|
# exit! is not within the instrumentation as it would not trigger due to exit
|
114
|
-
Kernel.exit!
|
121
|
+
Kernel.exit!(FORCEFUL_EXIT_CODE)
|
115
122
|
ensure
|
116
123
|
Karafka::App.stopped!
|
117
124
|
end
|
data/lib/karafka/status.rb
CHANGED
@@ -3,6 +3,12 @@
|
|
3
3
|
module Karafka
|
4
4
|
module TimeTrackers
|
5
5
|
# Handles Kafka topic partition pausing and resuming with exponential back-offs.
|
6
|
+
# Since expiring and pausing can happen from both consumer and listener, this needs to be
|
7
|
+
# thread-safe.
|
8
|
+
#
|
9
|
+
# @note We do not have to worry about performance implications of a mutex wrapping most of the
|
10
|
+
# code here, as this is not a frequently used tracker. It is active only once per batch in
|
11
|
+
# case of long-running-jobs and upon errors.
|
6
12
|
class Pause < Base
|
7
13
|
attr_reader :count
|
8
14
|
|
@@ -36,6 +42,7 @@ module Karafka
|
|
36
42
|
@timeout = timeout
|
37
43
|
@max_timeout = max_timeout
|
38
44
|
@exponential_backoff = exponential_backoff
|
45
|
+
@mutex = Mutex.new
|
39
46
|
super()
|
40
47
|
end
|
41
48
|
|
@@ -45,35 +52,47 @@ module Karafka
|
|
45
52
|
# @note Providing this value can be useful when we explicitly want to pause for a certain
|
46
53
|
# period of time, outside of any regular pausing logic
|
47
54
|
def pause(timeout = backoff_interval)
|
48
|
-
@
|
49
|
-
|
50
|
-
|
55
|
+
@mutex.synchronize do
|
56
|
+
@started_at = now
|
57
|
+
@ends_at = @started_at + timeout
|
58
|
+
@count += 1
|
59
|
+
end
|
51
60
|
end
|
52
61
|
|
53
62
|
# Marks the pause as resumed.
|
54
63
|
def resume
|
55
|
-
@
|
56
|
-
|
64
|
+
@mutex.synchronize do
|
65
|
+
@started_at = nil
|
66
|
+
@ends_at = nil
|
67
|
+
end
|
57
68
|
end
|
58
69
|
|
59
70
|
# Expires the pause, so it can be considered expired
|
60
71
|
def expire
|
61
|
-
@
|
72
|
+
@mutex.synchronize do
|
73
|
+
@ends_at = nil
|
74
|
+
end
|
62
75
|
end
|
63
76
|
|
64
77
|
# @return [Boolean] are we paused from processing
|
65
78
|
def paused?
|
66
|
-
|
79
|
+
@mutex.synchronize do
|
80
|
+
!@started_at.nil?
|
81
|
+
end
|
67
82
|
end
|
68
83
|
|
69
84
|
# @return [Boolean] did the pause expire
|
70
85
|
def expired?
|
71
|
-
@
|
86
|
+
@mutex.synchronize do
|
87
|
+
@ends_at ? now >= @ends_at : true
|
88
|
+
end
|
72
89
|
end
|
73
90
|
|
74
91
|
# Resets the pause counter.
|
75
92
|
def reset
|
76
|
-
@
|
93
|
+
@mutex.synchronize do
|
94
|
+
@count = 0
|
95
|
+
end
|
77
96
|
end
|
78
97
|
|
79
98
|
private
|
@@ -2,7 +2,8 @@
|
|
2
2
|
|
3
3
|
module Karafka
|
4
4
|
module TimeTrackers
|
5
|
-
# Object used to keep track of time we've used running certain operations.
|
5
|
+
# Object used to keep track of time we've used running certain operations. Polling is
|
6
|
+
# running in a single thread, thus we do not have to worry about this being thread-safe.
|
6
7
|
#
|
7
8
|
# @example Keep track of sleeping and stop after 3 seconds of 0.1 sleep intervals
|
8
9
|
# time_poll = Poll.new(3000)
|
data/lib/karafka/version.rb
CHANGED
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: karafka
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.15
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Maciej Mensfeld
|
@@ -35,7 +35,7 @@ cert_chain:
|
|
35
35
|
Qf04B9ceLUaC4fPVEz10FyobjaFoY4i32xRto3XnrzeAgfEe4swLq8bQsR3w/EF3
|
36
36
|
MGU0FeSV2Yj7Xc2x/7BzLK8xQn5l7Yy75iPF+KP3vVmDHnNl
|
37
37
|
-----END CERTIFICATE-----
|
38
|
-
date: 2022-10-
|
38
|
+
date: 2022-10-20 00:00:00.000000000 Z
|
39
39
|
dependencies:
|
40
40
|
- !ruby/object:Gem::Dependency
|
41
41
|
name: karafka-core
|
@@ -188,6 +188,7 @@ files:
|
|
188
188
|
- lib/karafka/contracts/consumer_group.rb
|
189
189
|
- lib/karafka/contracts/consumer_group_topic.rb
|
190
190
|
- lib/karafka/contracts/server_cli_options.rb
|
191
|
+
- lib/karafka/embedded.rb
|
191
192
|
- lib/karafka/env.rb
|
192
193
|
- lib/karafka/errors.rb
|
193
194
|
- lib/karafka/helpers/async.rb
|
metadata.gz.sig
CHANGED
Binary file
|