karafka 2.4.3 → 2.4.4
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
- checksums.yaml.gz.sig +0 -0
- data/.github/workflows/ci.yml +5 -0
- data/CHANGELOG.md +14 -0
- data/Gemfile.lock +15 -15
- data/karafka.gemspec +1 -1
- data/lib/karafka/connection/client.rb +3 -0
- data/lib/karafka/embedded.rb +44 -2
- data/lib/karafka/helpers/async.rb +10 -1
- data/lib/karafka/instrumentation/logger_listener.rb +21 -4
- data/lib/karafka/pro/connection/manager.rb +4 -0
- data/lib/karafka/pro/processing/coordinators/filters_applier.rb +17 -0
- data/lib/karafka/pro/processing/filters/base.rb +12 -0
- data/lib/karafka/pro/processing/filters/delayer.rb +2 -2
- data/lib/karafka/pro/processing/strategies/dlq/default.rb +2 -1
- data/lib/karafka/pro/processing/strategies/ftr/default.rb +13 -0
- data/lib/karafka/server.rb +21 -1
- data/lib/karafka/setup/attributes_map.rb +2 -0
- data/lib/karafka/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +4 -4
- 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: 1b7333a7812643bc128c721e411449dfd477adfa52968c7c291900e622cdcc04
|
|
4
|
+
data.tar.gz: 7062798152f0d4e097e5c4fcd228798103a680441579bbc1918c8bf5a65ce98b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bd24bd450ac1cda02d18d7d487317139988b943ecc92c606cb713f13c819db044d6feae978873d26445e1ebf8d8823bedfd7efae58bc53c8213be9ef56a84c1d
|
|
7
|
+
data.tar.gz: 0f2f4b50ea90cd76f6275e0cdc9eeada5e5cd30bf6c18a219209dfe4b717d90ef88d7c6b68797e9eb0615c83ba03ee738d41164014ce74aaf27970ef07ba5974
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/.github/workflows/ci.yml
CHANGED
|
@@ -148,6 +148,11 @@ jobs:
|
|
|
148
148
|
|
|
149
149
|
bundle config set without 'tools benchmarks docs'
|
|
150
150
|
|
|
151
|
+
- name: Fix directory permissions for Bundler
|
|
152
|
+
run: |
|
|
153
|
+
chmod -R o-w /opt/hostedtoolcache/Ruby/3*/x64/lib/ruby/gems/3*/gems
|
|
154
|
+
chmod +t /opt/hostedtoolcache/Ruby/3*/x64/lib/ruby/gems/3*/gems
|
|
155
|
+
|
|
151
156
|
- name: Bundle install
|
|
152
157
|
run: |
|
|
153
158
|
bundle config set without development
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Karafka framework changelog
|
|
2
2
|
|
|
3
|
+
## 2.4.4 (2024-07-04)
|
|
4
|
+
- [Enhancement] Allow for offset storing from the Filtering API.
|
|
5
|
+
- [Enhancement] Print more extensive error info on forceful shutdown.
|
|
6
|
+
- [Enhancement] Include `original_key` in the DLQ dispatch headers.
|
|
7
|
+
- [Enhancement] Support embedding mode control management from the trap context.
|
|
8
|
+
- [Enhancement] Make sure, that the listener thread is stopped before restarting.
|
|
9
|
+
- [Fix] Do not block on hanging listener shutdown when invoking forceful shutdown.
|
|
10
|
+
- [Fix] Static membership fencing error is not propagated explicitly enough.
|
|
11
|
+
- [Fix] Make sure DLQ dispatches raw headers and not deserialized headers (same as payload).
|
|
12
|
+
- [Fix] Fix a typo where `ms` in logger listener would not have space before it.
|
|
13
|
+
- [Maintenance] Require `karafka-core` `>=` `2.4.3`.
|
|
14
|
+
- [Maintenance] Allow for usage of `karafka-rdkafka` `~` `0.16` to support librdkafka `2.4.0`.
|
|
15
|
+
- [Maintenance] Lower the precision reporting to 100 microseconds in the logger listener.
|
|
16
|
+
|
|
3
17
|
## 2.4.3 (2024-06-12)
|
|
4
18
|
- [Enhancement] Allow for customization of Virtual Partitions reducer for enhanced parallelization.
|
|
5
19
|
- [Enhancement] Add more error codes to early report on polling issues (kidlab)
|
data/Gemfile.lock
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
karafka (2.4.
|
|
4
|
+
karafka (2.4.4)
|
|
5
5
|
base64 (~> 0.2)
|
|
6
|
-
karafka-core (>= 2.4.
|
|
6
|
+
karafka-core (>= 2.4.3, < 2.5.0)
|
|
7
7
|
waterdrop (>= 2.7.3, < 3.0.0)
|
|
8
8
|
zeitwerk (~> 2.3)
|
|
9
9
|
|
|
@@ -26,12 +26,12 @@ GEM
|
|
|
26
26
|
base64 (0.2.0)
|
|
27
27
|
bigdecimal (3.1.8)
|
|
28
28
|
byebug (11.1.3)
|
|
29
|
-
concurrent-ruby (1.3.
|
|
29
|
+
concurrent-ruby (1.3.3)
|
|
30
30
|
connection_pool (2.4.1)
|
|
31
31
|
diff-lcs (1.5.1)
|
|
32
32
|
docile (1.4.0)
|
|
33
33
|
drb (2.2.1)
|
|
34
|
-
erubi (1.
|
|
34
|
+
erubi (1.13.0)
|
|
35
35
|
factory_bot (6.4.6)
|
|
36
36
|
activesupport (>= 5.0.0)
|
|
37
37
|
ffi (1.17.0)
|
|
@@ -39,13 +39,13 @@ GEM
|
|
|
39
39
|
activesupport (>= 6.1)
|
|
40
40
|
i18n (1.14.5)
|
|
41
41
|
concurrent-ruby (~> 1.0)
|
|
42
|
-
karafka-core (2.4.
|
|
43
|
-
karafka-rdkafka (>= 0.15.0, < 0.
|
|
44
|
-
karafka-rdkafka (0.
|
|
42
|
+
karafka-core (2.4.3)
|
|
43
|
+
karafka-rdkafka (>= 0.15.0, < 0.17.0)
|
|
44
|
+
karafka-rdkafka (0.16.0)
|
|
45
45
|
ffi (~> 1.15)
|
|
46
46
|
mini_portile2 (~> 2.6)
|
|
47
47
|
rake (> 12)
|
|
48
|
-
karafka-testing (2.4.
|
|
48
|
+
karafka-testing (2.4.4)
|
|
49
49
|
karafka (>= 2.4.0, < 2.5.0)
|
|
50
50
|
waterdrop (>= 2.7.0)
|
|
51
51
|
karafka-web (0.9.1)
|
|
@@ -55,12 +55,12 @@ GEM
|
|
|
55
55
|
roda (~> 3.68, >= 3.69)
|
|
56
56
|
tilt (~> 2.0)
|
|
57
57
|
mini_portile2 (2.8.7)
|
|
58
|
-
minitest (5.
|
|
58
|
+
minitest (5.24.0)
|
|
59
59
|
mutex_m (0.2.0)
|
|
60
60
|
ostruct (0.6.0)
|
|
61
|
-
rack (3.
|
|
61
|
+
rack (3.1.4)
|
|
62
62
|
rake (13.2.1)
|
|
63
|
-
roda (3.
|
|
63
|
+
roda (3.81.0)
|
|
64
64
|
rack
|
|
65
65
|
rspec (3.13.0)
|
|
66
66
|
rspec-core (~> 3.13.0)
|
|
@@ -68,7 +68,7 @@ GEM
|
|
|
68
68
|
rspec-mocks (~> 3.13.0)
|
|
69
69
|
rspec-core (3.13.0)
|
|
70
70
|
rspec-support (~> 3.13.0)
|
|
71
|
-
rspec-expectations (3.13.
|
|
71
|
+
rspec-expectations (3.13.1)
|
|
72
72
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
73
73
|
rspec-support (~> 3.13.0)
|
|
74
74
|
rspec-mocks (3.13.1)
|
|
@@ -81,14 +81,14 @@ GEM
|
|
|
81
81
|
simplecov_json_formatter (~> 0.1)
|
|
82
82
|
simplecov-html (0.12.3)
|
|
83
83
|
simplecov_json_formatter (0.1.4)
|
|
84
|
-
tilt (2.
|
|
84
|
+
tilt (2.4.0)
|
|
85
85
|
tzinfo (2.0.6)
|
|
86
86
|
concurrent-ruby (~> 1.0)
|
|
87
87
|
waterdrop (2.7.3)
|
|
88
88
|
karafka-core (>= 2.4.0, < 3.0.0)
|
|
89
89
|
karafka-rdkafka (>= 0.15.1)
|
|
90
90
|
zeitwerk (~> 2.3)
|
|
91
|
-
zeitwerk (2.6.
|
|
91
|
+
zeitwerk (2.6.16)
|
|
92
92
|
|
|
93
93
|
PLATFORMS
|
|
94
94
|
ruby
|
|
@@ -106,4 +106,4 @@ DEPENDENCIES
|
|
|
106
106
|
simplecov
|
|
107
107
|
|
|
108
108
|
BUNDLED WITH
|
|
109
|
-
2.5.
|
|
109
|
+
2.5.14
|
data/karafka.gemspec
CHANGED
|
@@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
|
|
|
22
22
|
DESC
|
|
23
23
|
|
|
24
24
|
spec.add_dependency 'base64', '~> 0.2'
|
|
25
|
-
spec.add_dependency 'karafka-core', '>= 2.4.
|
|
25
|
+
spec.add_dependency 'karafka-core', '>= 2.4.3', '< 2.5.0'
|
|
26
26
|
spec.add_dependency 'waterdrop', '>= 2.7.3', '< 3.0.0'
|
|
27
27
|
spec.add_dependency 'zeitwerk', '~> 2.3'
|
|
28
28
|
|
|
@@ -559,6 +559,9 @@ module Karafka
|
|
|
559
559
|
early_report = true
|
|
560
560
|
when :cluster_authorization_failed # 31
|
|
561
561
|
early_report = true
|
|
562
|
+
# This can happen for many reasons, including issues with static membership being fenced
|
|
563
|
+
when :fatal # -150
|
|
564
|
+
early_report = true
|
|
562
565
|
# @see
|
|
563
566
|
# https://github.com/confluentinc/confluent-kafka-dotnet/issues/1366#issuecomment-821842990
|
|
564
567
|
# This will be raised each time poll detects a non-existing topic. When auto creation is
|
data/lib/karafka/embedded.rb
CHANGED
|
@@ -2,11 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
module Karafka
|
|
4
4
|
# Allows to start and stop Karafka as part of a different process
|
|
5
|
+
# Following limitations and restrictions apply:
|
|
6
|
+
#
|
|
7
|
+
# - `#start` cannot be called from a trap context - non blocking
|
|
8
|
+
# - `#quiet` - can be called from a trap context - non blocking
|
|
9
|
+
# - `#stop` - can be called from a trap context - blocking
|
|
5
10
|
module Embedded
|
|
6
11
|
class << self
|
|
12
|
+
# Lock for ensuring we do not control embedding in parallel
|
|
13
|
+
MUTEX = Mutex.new
|
|
14
|
+
|
|
15
|
+
private_constant :MUTEX
|
|
16
|
+
|
|
7
17
|
# Starts Karafka without supervision and without ownership of signals in a background thread
|
|
8
18
|
# so it won't interrupt other things running
|
|
9
19
|
def start
|
|
20
|
+
MUTEX.synchronize do
|
|
21
|
+
# Prevent from double-starting
|
|
22
|
+
return if @started
|
|
23
|
+
|
|
24
|
+
@started = true
|
|
25
|
+
end
|
|
26
|
+
|
|
10
27
|
Thread.new do
|
|
11
28
|
Thread.current.name = 'karafka.embedded'
|
|
12
29
|
|
|
@@ -19,9 +36,32 @@ module Karafka
|
|
|
19
36
|
#
|
|
20
37
|
# @note This method is blocking because we want to wait until Karafka is stopped with final
|
|
21
38
|
# process shutdown
|
|
39
|
+
#
|
|
40
|
+
# @note This method **is** safe to run from a trap context.
|
|
22
41
|
def stop
|
|
23
|
-
#
|
|
24
|
-
|
|
42
|
+
# Prevent from double stopping
|
|
43
|
+
unless @stopping
|
|
44
|
+
Thread.new do
|
|
45
|
+
Thread.current.name = 'karafka.embedded.stopping'
|
|
46
|
+
|
|
47
|
+
stop = false
|
|
48
|
+
|
|
49
|
+
# We spawn a new thread because `#stop` may be called from a trap context
|
|
50
|
+
MUTEX.synchronize do
|
|
51
|
+
break if @stopping
|
|
52
|
+
|
|
53
|
+
@stopping = true
|
|
54
|
+
stop = true
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
next unless stop
|
|
58
|
+
|
|
59
|
+
Karafka::Server.stop
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Since we want to have this blocking, we wait for the background thread
|
|
64
|
+
sleep(0.1) until Karafka::App.terminated?
|
|
25
65
|
end
|
|
26
66
|
|
|
27
67
|
# Quiets Karafka upon any event
|
|
@@ -29,6 +69,8 @@ module Karafka
|
|
|
29
69
|
# @note This method is not blocking and will not wait for Karafka to fully quiet.
|
|
30
70
|
# It will trigger the quiet procedure but won't wait.
|
|
31
71
|
#
|
|
72
|
+
# @note This method **can** be called from a trap context.
|
|
73
|
+
#
|
|
32
74
|
# @note Please keep in mind you need to `#stop` to actually stop the server anyhow.
|
|
33
75
|
def quiet
|
|
34
76
|
Karafka::Server.quiet
|
|
@@ -22,7 +22,16 @@ module Karafka
|
|
|
22
22
|
def included(base)
|
|
23
23
|
base.extend ::Forwardable
|
|
24
24
|
|
|
25
|
-
base.def_delegators :@thread, :join, :terminate, :
|
|
25
|
+
base.def_delegators :@thread, :join, :terminate, :name
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# @return [Boolean] true if thread is present and is running, false otherwise
|
|
30
|
+
def alive?
|
|
31
|
+
MUTEX.synchronize do
|
|
32
|
+
return false unless @thread
|
|
33
|
+
|
|
34
|
+
@thread.alive?
|
|
26
35
|
end
|
|
27
36
|
end
|
|
28
37
|
|
|
@@ -41,7 +41,7 @@ module Karafka
|
|
|
41
41
|
return unless log_polling?
|
|
42
42
|
|
|
43
43
|
listener = event[:caller]
|
|
44
|
-
time = event[:time]
|
|
44
|
+
time = event[:time].round(2)
|
|
45
45
|
messages_count = event[:messages_buffer].size
|
|
46
46
|
|
|
47
47
|
message = "[#{listener.id}] Polled #{messages_count} messages in #{time}ms"
|
|
@@ -69,14 +69,14 @@ module Karafka
|
|
|
69
69
|
# @param event [Karafka::Core::Monitoring::Event] event details including payload
|
|
70
70
|
def on_worker_processed(event)
|
|
71
71
|
job = event[:job]
|
|
72
|
-
time = event[:time]
|
|
72
|
+
time = event[:time].round(2)
|
|
73
73
|
job_type = job.class.to_s.split('::').last
|
|
74
74
|
consumer = job.executor.topic.consumer
|
|
75
75
|
topic = job.executor.topic.name
|
|
76
76
|
partition = job.executor.partition
|
|
77
77
|
info <<~MSG.tr("\n", ' ').strip!
|
|
78
78
|
[#{job.id}] #{job_type} job for #{consumer}
|
|
79
|
-
on #{topic}/#{partition} finished in #{time}ms
|
|
79
|
+
on #{topic}/#{partition} finished in #{time} ms
|
|
80
80
|
MSG
|
|
81
81
|
end
|
|
82
82
|
|
|
@@ -306,7 +306,24 @@ module Karafka
|
|
|
306
306
|
fatal "Runner crashed due to an error: #{error}"
|
|
307
307
|
fatal details
|
|
308
308
|
when 'app.stopping.error'
|
|
309
|
-
|
|
309
|
+
# Counts number of workers and listeners that were still active when forcing the
|
|
310
|
+
# shutdown. Please note, that unless all listeners are closed, workers will not finalize
|
|
311
|
+
# their operations as well.
|
|
312
|
+
# We need to check if listeners and workers are assigned as during super early stages of
|
|
313
|
+
# boot they are not.
|
|
314
|
+
listeners = Server.listeners ? Server.listeners.count(&:active?) : 0
|
|
315
|
+
workers = Server.workers ? Server.workers.count(&:alive?) : 0
|
|
316
|
+
|
|
317
|
+
message = <<~MSG.tr("\n", ' ').strip!
|
|
318
|
+
Forceful Karafka server stop with:
|
|
319
|
+
#{workers} active workers and
|
|
320
|
+
#{listeners} active listeners
|
|
321
|
+
MSG
|
|
322
|
+
|
|
323
|
+
error message
|
|
324
|
+
when 'app.forceful_stopping.error'
|
|
325
|
+
error "Forceful shutdown error occurred: #{error}"
|
|
326
|
+
error details
|
|
310
327
|
when 'librdkafka.error'
|
|
311
328
|
error "librdkafka internal error occurred: #{error}"
|
|
312
329
|
error details
|
|
@@ -216,6 +216,10 @@ module Karafka
|
|
|
216
216
|
next unless multi_part_sgs_families.include?(sg_listener.subscription_group.name)
|
|
217
217
|
# Skip already active connections
|
|
218
218
|
next unless sg_listener.pending? || sg_listener.stopped?
|
|
219
|
+
# Ensure that the listener thread under which we operate is already stopped and
|
|
220
|
+
# is not dangling. While not likely to happen, this may protect against a
|
|
221
|
+
# case where a shutdown critical crash would case a restart of the same listener
|
|
222
|
+
next if sg_listener.alive?
|
|
219
223
|
|
|
220
224
|
touch(sg_listener.subscription_group.id)
|
|
221
225
|
sg_listener.start!
|
|
@@ -89,6 +89,23 @@ module Karafka
|
|
|
89
89
|
applied.map(&:cursor).compact.min_by(&:offset)
|
|
90
90
|
end
|
|
91
91
|
|
|
92
|
+
# @return [Boolean] did any of the filters requested offset storage during filter
|
|
93
|
+
# application
|
|
94
|
+
def mark_as_consumed?
|
|
95
|
+
# We can manage filtering offset only when user wanted that and there is a cursor
|
|
96
|
+
# to use
|
|
97
|
+
applied.any?(&:mark_as_consumed?) && cursor
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# @return [Symbol] `:mark_as_consumed` or `:mark_as_consumed!`
|
|
101
|
+
def marking_method
|
|
102
|
+
candidates = applied.map(&:marking_method)
|
|
103
|
+
|
|
104
|
+
return :mark_as_consumed! if candidates.include?(:mark_as_consumed!)
|
|
105
|
+
|
|
106
|
+
:mark_as_consumed
|
|
107
|
+
end
|
|
108
|
+
|
|
92
109
|
private
|
|
93
110
|
|
|
94
111
|
# @return [Boolean] is filtering active
|
|
@@ -54,6 +54,18 @@ module Karafka
|
|
|
54
54
|
def timeout
|
|
55
55
|
0
|
|
56
56
|
end
|
|
57
|
+
|
|
58
|
+
# @return [Boolean] should we use the cursor value to mark as consumed. If any of the
|
|
59
|
+
# filters returns true, we return lowers applicable cursor value (if any)
|
|
60
|
+
def mark_as_consumed?
|
|
61
|
+
false
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# @return [Symbol] `:mark_as_consumed` or `:mark_as_consumed!`. Applicable only if
|
|
65
|
+
# marking is requested
|
|
66
|
+
def marking_method
|
|
67
|
+
:mark_as_consumed
|
|
68
|
+
end
|
|
57
69
|
end
|
|
58
70
|
end
|
|
59
71
|
end
|
|
@@ -33,7 +33,7 @@ module Karafka
|
|
|
33
33
|
|
|
34
34
|
# Time on message is in seconds with ms precision, so we need to convert the ttl that
|
|
35
35
|
# is in ms to this format
|
|
36
|
-
border = ::Time.now.utc - @delay / 1_000.
|
|
36
|
+
border = ::Time.now.utc - @delay / 1_000.0
|
|
37
37
|
|
|
38
38
|
messages.delete_if do |message|
|
|
39
39
|
too_young = message.timestamp > border
|
|
@@ -52,7 +52,7 @@ module Karafka
|
|
|
52
52
|
def timeout
|
|
53
53
|
return 0 unless @cursor
|
|
54
54
|
|
|
55
|
-
timeout = (@delay / 1_000.
|
|
55
|
+
timeout = (@delay / 1_000.0) - (::Time.now.utc - @cursor.timestamp)
|
|
56
56
|
|
|
57
57
|
timeout <= 0 ? 0 : timeout * 1_000
|
|
58
58
|
end
|
|
@@ -154,11 +154,12 @@ module Karafka
|
|
|
154
154
|
topic: topic.dead_letter_queue.topic,
|
|
155
155
|
key: original_partition,
|
|
156
156
|
payload: skippable_message.raw_payload,
|
|
157
|
-
headers: skippable_message.
|
|
157
|
+
headers: skippable_message.raw_headers.merge(
|
|
158
158
|
'original_topic' => topic.name,
|
|
159
159
|
'original_partition' => original_partition,
|
|
160
160
|
'original_offset' => skippable_message.offset.to_s,
|
|
161
161
|
'original_consumer_group' => topic.consumer_group.id,
|
|
162
|
+
'original_key' => skippable_message.raw_key.to_s,
|
|
162
163
|
'original_attempts' => attempt.to_s
|
|
163
164
|
)
|
|
164
165
|
}
|
|
@@ -66,6 +66,19 @@ module Karafka
|
|
|
66
66
|
# and this should not happen
|
|
67
67
|
throttle_timeout = filter.timeout
|
|
68
68
|
|
|
69
|
+
# If user requested marking when applying filter, we mark. We may be in the user
|
|
70
|
+
# flow but even then this is not a problem. Older offsets will be ignored since
|
|
71
|
+
# we do not force the offset update (expected) and newer are on the user to control.
|
|
72
|
+
# This can be primarily used when filtering large quantities of data to mark on the
|
|
73
|
+
# idle runs, so lag reporting is aware that those messages were not consumed but also
|
|
74
|
+
# are no longer relevant
|
|
75
|
+
if filter.mark_as_consumed?
|
|
76
|
+
send(
|
|
77
|
+
filter.marking_method,
|
|
78
|
+
filter.cursor
|
|
79
|
+
)
|
|
80
|
+
end
|
|
81
|
+
|
|
69
82
|
case filter.action
|
|
70
83
|
when :skip
|
|
71
84
|
nil
|
data/lib/karafka/server.rb
CHANGED
|
@@ -3,6 +3,12 @@
|
|
|
3
3
|
module Karafka
|
|
4
4
|
# Karafka consuming server class
|
|
5
5
|
class Server
|
|
6
|
+
# How long should we wait on the listeners forceful shutdown when they are stuck beyond the
|
|
7
|
+
# shutdown timeout before forcing a bypass
|
|
8
|
+
FORCEFUL_SHUTDOWN_WAIT = 5
|
|
9
|
+
|
|
10
|
+
private_constant :FORCEFUL_SHUTDOWN_WAIT
|
|
11
|
+
|
|
6
12
|
class << self
|
|
7
13
|
# Set of consuming threads. Each consumer thread contains a single consumer
|
|
8
14
|
attr_accessor :listeners
|
|
@@ -105,9 +111,23 @@ module Karafka
|
|
|
105
111
|
# We're done waiting, lets kill them!
|
|
106
112
|
workers.each(&:terminate)
|
|
107
113
|
listeners.active.each(&:terminate)
|
|
114
|
+
|
|
108
115
|
# We always need to shutdown clients to make sure we do not force the GC to close consumer.
|
|
109
116
|
# This can cause memory leaks and crashes.
|
|
110
|
-
|
|
117
|
+
# We run it in a separate thread in case this would hang and we ignore it after the time
|
|
118
|
+
# we assigned to it and force shutdown as we prefer to stop the process rather than wait
|
|
119
|
+
# indefinitely even with risk of VM crash as this is a last resort.
|
|
120
|
+
Thread.new do
|
|
121
|
+
listeners.each(&:shutdown)
|
|
122
|
+
rescue StandardError => e
|
|
123
|
+
# If anything wrong happened during shutdown, we also want to record it
|
|
124
|
+
Karafka.monitor.instrument(
|
|
125
|
+
'error.occurred',
|
|
126
|
+
caller: self,
|
|
127
|
+
error: e,
|
|
128
|
+
type: 'app.forceful_stopping.error'
|
|
129
|
+
)
|
|
130
|
+
end.join(FORCEFUL_SHUTDOWN_WAIT)
|
|
111
131
|
|
|
112
132
|
# We also do not forcefully terminate everything when running in the embedded mode,
|
|
113
133
|
# otherwise we would overwrite the shutdown process of the process that started Karafka
|
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.4.
|
|
4
|
+
version: 2.4.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Maciej Mensfeld
|
|
@@ -35,7 +35,7 @@ cert_chain:
|
|
|
35
35
|
AnG1dJU+yL2BK7vaVytLTstJME5mepSZ46qqIJXMuWob/YPDmVaBF39TDSG9e34s
|
|
36
36
|
msG3BiCqgOgHAnL23+CN3Rt8MsuRfEtoTKpJVcCfoEoNHOkc
|
|
37
37
|
-----END CERTIFICATE-----
|
|
38
|
-
date: 2024-
|
|
38
|
+
date: 2024-07-04 00:00:00.000000000 Z
|
|
39
39
|
dependencies:
|
|
40
40
|
- !ruby/object:Gem::Dependency
|
|
41
41
|
name: base64
|
|
@@ -57,7 +57,7 @@ dependencies:
|
|
|
57
57
|
requirements:
|
|
58
58
|
- - ">="
|
|
59
59
|
- !ruby/object:Gem::Version
|
|
60
|
-
version: 2.4.
|
|
60
|
+
version: 2.4.3
|
|
61
61
|
- - "<"
|
|
62
62
|
- !ruby/object:Gem::Version
|
|
63
63
|
version: 2.5.0
|
|
@@ -67,7 +67,7 @@ dependencies:
|
|
|
67
67
|
requirements:
|
|
68
68
|
- - ">="
|
|
69
69
|
- !ruby/object:Gem::Version
|
|
70
|
-
version: 2.4.
|
|
70
|
+
version: 2.4.3
|
|
71
71
|
- - "<"
|
|
72
72
|
- !ruby/object:Gem::Version
|
|
73
73
|
version: 2.5.0
|
metadata.gz.sig
CHANGED
|
Binary file
|