karafka 2.2.13 → 2.3.0.alpha1
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 +38 -12
- data/.ruby-version +1 -1
- data/CHANGELOG.md +161 -125
- data/Gemfile.lock +12 -12
- data/README.md +0 -2
- data/SECURITY.md +23 -0
- data/config/locales/errors.yml +7 -1
- data/config/locales/pro_errors.yml +22 -0
- data/docker-compose.yml +3 -1
- data/karafka.gemspec +2 -2
- data/lib/karafka/admin/acl.rb +287 -0
- data/lib/karafka/admin.rb +118 -16
- data/lib/karafka/app.rb +12 -3
- data/lib/karafka/base_consumer.rb +32 -31
- data/lib/karafka/cli/base.rb +1 -1
- data/lib/karafka/connection/client.rb +94 -84
- data/lib/karafka/connection/conductor.rb +28 -0
- data/lib/karafka/connection/listener.rb +165 -46
- data/lib/karafka/connection/listeners_batch.rb +5 -11
- data/lib/karafka/connection/manager.rb +72 -0
- data/lib/karafka/connection/messages_buffer.rb +12 -0
- data/lib/karafka/connection/proxy.rb +17 -0
- data/lib/karafka/connection/status.rb +75 -0
- data/lib/karafka/contracts/config.rb +14 -10
- data/lib/karafka/contracts/consumer_group.rb +9 -1
- data/lib/karafka/contracts/topic.rb +3 -1
- data/lib/karafka/errors.rb +13 -0
- data/lib/karafka/instrumentation/assignments_tracker.rb +96 -0
- data/lib/karafka/instrumentation/callbacks/rebalance.rb +10 -7
- data/lib/karafka/instrumentation/logger_listener.rb +3 -9
- data/lib/karafka/instrumentation/notifications.rb +19 -9
- data/lib/karafka/instrumentation/vendors/appsignal/metrics_listener.rb +31 -28
- data/lib/karafka/instrumentation/vendors/datadog/logger_listener.rb +22 -3
- data/lib/karafka/instrumentation/vendors/datadog/metrics_listener.rb +15 -12
- data/lib/karafka/instrumentation/vendors/kubernetes/liveness_listener.rb +39 -36
- data/lib/karafka/pro/base_consumer.rb +47 -0
- data/lib/karafka/pro/connection/manager.rb +300 -0
- data/lib/karafka/pro/connection/multiplexing/listener.rb +40 -0
- data/lib/karafka/pro/instrumentation/performance_tracker.rb +85 -0
- data/lib/karafka/pro/iterator/tpl_builder.rb +1 -1
- data/lib/karafka/pro/iterator.rb +1 -6
- data/lib/karafka/pro/loader.rb +16 -2
- data/lib/karafka/pro/processing/coordinator.rb +2 -1
- data/lib/karafka/pro/processing/executor.rb +37 -0
- data/lib/karafka/pro/processing/expansions_selector.rb +32 -0
- data/lib/karafka/pro/processing/jobs/periodic.rb +41 -0
- data/lib/karafka/pro/processing/jobs/periodic_non_blocking.rb +32 -0
- data/lib/karafka/pro/processing/jobs_builder.rb +14 -3
- data/lib/karafka/pro/processing/offset_metadata/consumer.rb +44 -0
- data/lib/karafka/pro/processing/offset_metadata/fetcher.rb +131 -0
- data/lib/karafka/pro/processing/offset_metadata/listener.rb +46 -0
- data/lib/karafka/pro/processing/schedulers/base.rb +143 -0
- data/lib/karafka/pro/processing/schedulers/default.rb +107 -0
- data/lib/karafka/pro/processing/strategies/aj/lrj_mom_vp.rb +1 -1
- data/lib/karafka/pro/processing/strategies/default.rb +136 -3
- data/lib/karafka/pro/processing/strategies/dlq/default.rb +35 -0
- data/lib/karafka/pro/processing/strategies/lrj/default.rb +1 -1
- data/lib/karafka/pro/processing/strategies/lrj/mom.rb +1 -1
- data/lib/karafka/pro/processing/strategies/vp/default.rb +60 -26
- data/lib/karafka/pro/processing/virtual_offset_manager.rb +41 -11
- data/lib/karafka/pro/routing/features/long_running_job/topic.rb +2 -0
- data/lib/karafka/pro/routing/features/multiplexing/config.rb +38 -0
- data/lib/karafka/pro/routing/features/multiplexing/contracts/topic.rb +114 -0
- data/lib/karafka/pro/routing/features/multiplexing/patches/contracts/consumer_group.rb +42 -0
- data/lib/karafka/pro/routing/features/multiplexing/proxy.rb +38 -0
- data/lib/karafka/pro/routing/features/multiplexing/subscription_group.rb +42 -0
- data/lib/karafka/pro/routing/features/multiplexing/subscription_groups_builder.rb +40 -0
- data/lib/karafka/pro/routing/features/multiplexing.rb +59 -0
- data/lib/karafka/pro/routing/features/non_blocking_job/topic.rb +32 -0
- data/lib/karafka/pro/routing/features/non_blocking_job.rb +37 -0
- data/lib/karafka/pro/routing/features/offset_metadata/config.rb +33 -0
- data/lib/karafka/pro/routing/features/offset_metadata/contracts/topic.rb +42 -0
- data/lib/karafka/pro/routing/features/offset_metadata/topic.rb +65 -0
- data/lib/karafka/pro/routing/features/offset_metadata.rb +40 -0
- data/lib/karafka/pro/routing/features/patterns/contracts/consumer_group.rb +4 -0
- data/lib/karafka/pro/routing/features/patterns/detector.rb +18 -10
- data/lib/karafka/pro/routing/features/periodic_job/config.rb +37 -0
- data/lib/karafka/pro/routing/features/periodic_job/contracts/topic.rb +44 -0
- data/lib/karafka/pro/routing/features/periodic_job/topic.rb +94 -0
- data/lib/karafka/pro/routing/features/periodic_job.rb +27 -0
- data/lib/karafka/pro/routing/features/virtual_partitions/config.rb +1 -0
- data/lib/karafka/pro/routing/features/virtual_partitions/contracts/topic.rb +1 -0
- data/lib/karafka/pro/routing/features/virtual_partitions/topic.rb +7 -2
- data/lib/karafka/process.rb +5 -3
- data/lib/karafka/processing/coordinator.rb +5 -1
- data/lib/karafka/processing/executor.rb +43 -13
- data/lib/karafka/processing/executors_buffer.rb +22 -7
- data/lib/karafka/processing/jobs/base.rb +19 -2
- data/lib/karafka/processing/jobs/consume.rb +3 -3
- data/lib/karafka/processing/jobs/idle.rb +5 -0
- data/lib/karafka/processing/jobs/revoked.rb +5 -0
- data/lib/karafka/processing/jobs/shutdown.rb +5 -0
- data/lib/karafka/processing/jobs_queue.rb +19 -8
- data/lib/karafka/processing/schedulers/default.rb +42 -0
- data/lib/karafka/processing/strategies/base.rb +13 -4
- data/lib/karafka/processing/strategies/default.rb +23 -7
- data/lib/karafka/processing/strategies/dlq.rb +36 -0
- data/lib/karafka/processing/worker.rb +4 -1
- data/lib/karafka/routing/builder.rb +12 -2
- data/lib/karafka/routing/consumer_group.rb +5 -5
- data/lib/karafka/routing/features/base.rb +44 -8
- data/lib/karafka/routing/features/dead_letter_queue/config.rb +6 -1
- data/lib/karafka/routing/features/dead_letter_queue/contracts/topic.rb +1 -0
- data/lib/karafka/routing/features/dead_letter_queue/topic.rb +9 -2
- data/lib/karafka/routing/proxy.rb +4 -3
- data/lib/karafka/routing/subscription_group.rb +2 -2
- data/lib/karafka/routing/subscription_groups_builder.rb +11 -2
- data/lib/karafka/routing/topic.rb +8 -10
- data/lib/karafka/routing/topics.rb +1 -1
- data/lib/karafka/runner.rb +13 -3
- data/lib/karafka/server.rb +5 -9
- data/lib/karafka/setup/config.rb +21 -1
- data/lib/karafka/status.rb +23 -14
- data/lib/karafka/templates/karafka.rb.erb +7 -0
- data/lib/karafka/time_trackers/partition_usage.rb +56 -0
- data/lib/karafka/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +47 -13
- metadata.gz.sig +0 -0
- data/lib/karafka/connection/consumer_group_coordinator.rb +0 -48
- data/lib/karafka/pro/performance_tracker.rb +0 -84
- data/lib/karafka/pro/processing/scheduler.rb +0 -74
- data/lib/karafka/processing/scheduler.rb +0 -38
data/lib/karafka/errors.rb
CHANGED
|
@@ -63,5 +63,18 @@ module Karafka
|
|
|
63
63
|
|
|
64
64
|
# Raised when there is an attempt to run an unrecognized CLI command
|
|
65
65
|
UnrecognizedCommandError = Class.new(BaseError)
|
|
66
|
+
|
|
67
|
+
# Raised when we attempt to perform operation that is only allowed inside of a transaction and
|
|
68
|
+
# there is no transaction around us
|
|
69
|
+
TransactionRequiredError = Class.new(BaseError)
|
|
70
|
+
|
|
71
|
+
# Raised in case user would want to perform nested transactions.
|
|
72
|
+
TransactionAlreadyInitializedError = Class.new(BaseError)
|
|
73
|
+
|
|
74
|
+
# Raised in case a listener that was paused is being resumed
|
|
75
|
+
InvalidListenerResumeError = Class.new(BaseError)
|
|
76
|
+
|
|
77
|
+
# Raised when we want to un-pause listener that was not paused
|
|
78
|
+
InvalidListenerPauseError = Class.new(BaseError)
|
|
66
79
|
end
|
|
67
80
|
end
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Karafka
|
|
4
|
+
module Instrumentation
|
|
5
|
+
# Keeps track of active assignments and materializes them by returning the routing topics
|
|
6
|
+
# with appropriate partitions that are assigned at a given moment
|
|
7
|
+
#
|
|
8
|
+
# It is auto-subscribed as part of Karafka itself.
|
|
9
|
+
#
|
|
10
|
+
# It is not heavy from the computational point of view, as it only operates during rebalances.
|
|
11
|
+
#
|
|
12
|
+
# We keep assignments as flat topics structure because we can go from topics to both
|
|
13
|
+
# subscription and consumer groups if needed.
|
|
14
|
+
class AssignmentsTracker
|
|
15
|
+
include Singleton
|
|
16
|
+
|
|
17
|
+
def initialize
|
|
18
|
+
@mutex = Mutex.new
|
|
19
|
+
@assignments = Hash.new { |hash, key| hash[key] = [] }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Returns all the active/current assignments of this given process
|
|
23
|
+
#
|
|
24
|
+
# @return [Hash<Karafka::Routing::Topic, Array<Integer>>]
|
|
25
|
+
#
|
|
26
|
+
# @note Keep in mind, that those assignments can change any time, especially when working
|
|
27
|
+
# with multiple consumer groups or subscription groups.
|
|
28
|
+
#
|
|
29
|
+
# @note We return a copy because we modify internals and we do not want user to tamper with
|
|
30
|
+
# the data accidentally
|
|
31
|
+
def current
|
|
32
|
+
assignments = {}
|
|
33
|
+
|
|
34
|
+
@assignments.each do |topic, partitions|
|
|
35
|
+
assignments[topic] = partitions.dup.freeze
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
assignments.freeze
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Clears all the assignments
|
|
42
|
+
def clear
|
|
43
|
+
@mutex.synchronize do
|
|
44
|
+
@assignments.clear
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# When client is under reset due to critical issues, remove all of its assignments as we will
|
|
49
|
+
# get a new set of assignments
|
|
50
|
+
# @param event [Karafka::Core::Monitoring::Event]
|
|
51
|
+
def on_client_reset(event)
|
|
52
|
+
sg = event[:subscription_group]
|
|
53
|
+
|
|
54
|
+
@mutex.synchronize do
|
|
55
|
+
@assignments.delete_if do |topic, _partitions|
|
|
56
|
+
topic.subscription_group.id == sg.id
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Removes partitions from the current assignments hash
|
|
62
|
+
#
|
|
63
|
+
# @param event [Karafka::Core::Monitoring::Event]
|
|
64
|
+
def on_rebalance_partitions_revoked(event)
|
|
65
|
+
sg = event[:subscription_group]
|
|
66
|
+
|
|
67
|
+
@mutex.synchronize do
|
|
68
|
+
event[:tpl].to_h.each do |topic, partitions|
|
|
69
|
+
topic = sg.topics.find(topic)
|
|
70
|
+
|
|
71
|
+
@assignments[topic] -= partitions.map(&:partition)
|
|
72
|
+
@assignments[topic].sort!
|
|
73
|
+
# Remove completely topics for which we do not have any assignments left
|
|
74
|
+
@assignments.delete_if { |_topic, cur_partitions| cur_partitions.empty? }
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# # Adds partitions to the current assignments hash
|
|
80
|
+
#
|
|
81
|
+
# @param event [Karafka::Core::Monitoring::Event]
|
|
82
|
+
def on_rebalance_partitions_assigned(event)
|
|
83
|
+
sg = event[:subscription_group]
|
|
84
|
+
|
|
85
|
+
@mutex.synchronize do
|
|
86
|
+
event[:tpl].to_h.each do |topic, partitions|
|
|
87
|
+
topic = sg.topics.find(topic)
|
|
88
|
+
|
|
89
|
+
@assignments[topic] += partitions.map(&:partition)
|
|
90
|
+
@assignments[topic].sort!
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -6,11 +6,10 @@ module Karafka
|
|
|
6
6
|
# Callback that connects to the librdkafka rebalance callback and converts those events into
|
|
7
7
|
# our internal events
|
|
8
8
|
class Rebalance
|
|
9
|
-
# @param
|
|
10
|
-
#
|
|
11
|
-
def initialize(
|
|
12
|
-
@
|
|
13
|
-
@consumer_group_id = consumer_group_id
|
|
9
|
+
# @param subscription_group [Karafka::Routes::SubscriptionGroup] subscription group for
|
|
10
|
+
# which we want to manage rebalances
|
|
11
|
+
def initialize(subscription_group)
|
|
12
|
+
@subscription_group = subscription_group
|
|
14
13
|
end
|
|
15
14
|
|
|
16
15
|
# Publishes an event that partitions are going to be revoked.
|
|
@@ -53,8 +52,12 @@ module Karafka
|
|
|
53
52
|
::Karafka.monitor.instrument(
|
|
54
53
|
"rebalance.#{name}",
|
|
55
54
|
caller: self,
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
# We keep the id references here for backwards compatibility as some of the monitors
|
|
56
|
+
# may use the id references
|
|
57
|
+
subscription_group_id: @subscription_group.id,
|
|
58
|
+
subscription_group: @subscription_group,
|
|
59
|
+
consumer_group_id: @subscription_group.consumer_group.id,
|
|
60
|
+
consumer_group: @subscription_group.consumer_group,
|
|
58
61
|
tpl: tpl
|
|
59
62
|
)
|
|
60
63
|
end
|
|
@@ -241,21 +241,15 @@ module Karafka
|
|
|
241
241
|
when 'consumer.revoked.error'
|
|
242
242
|
error "Consumer on revoked failed due to an error: #{error}"
|
|
243
243
|
error details
|
|
244
|
-
when 'consumer.before_enqueue.error'
|
|
245
|
-
error "Consumer before enqueue failed due to an error: #{error}"
|
|
246
|
-
error details
|
|
247
|
-
when 'consumer.before_consume.error'
|
|
248
|
-
error "Consumer before consume failed due to an error: #{error}"
|
|
249
|
-
error details
|
|
250
|
-
when 'consumer.after_consume.error'
|
|
251
|
-
error "Consumer after consume failed due to an error: #{error}"
|
|
252
|
-
error details
|
|
253
244
|
when 'consumer.idle.error'
|
|
254
245
|
error "Consumer idle failed due to an error: #{error}"
|
|
255
246
|
error details
|
|
256
247
|
when 'consumer.shutdown.error'
|
|
257
248
|
error "Consumer on shutdown failed due to an error: #{error}"
|
|
258
249
|
error details
|
|
250
|
+
when 'consumer.tick.error'
|
|
251
|
+
error "Consumer tick failed due to an error: #{error}"
|
|
252
|
+
error details
|
|
259
253
|
when 'worker.process.error'
|
|
260
254
|
fatal "Worker processing failed due to an error: #{error}"
|
|
261
255
|
fatal details
|
|
@@ -20,6 +20,7 @@ module Karafka
|
|
|
20
20
|
active_job.consume
|
|
21
21
|
active_job.consumed
|
|
22
22
|
|
|
23
|
+
app.initializing
|
|
23
24
|
app.initialized
|
|
24
25
|
app.running
|
|
25
26
|
app.quieting
|
|
@@ -30,27 +31,31 @@ module Karafka
|
|
|
30
31
|
|
|
31
32
|
client.pause
|
|
32
33
|
client.resume
|
|
34
|
+
client.reset
|
|
33
35
|
|
|
34
36
|
connection.listener.before_fetch_loop
|
|
35
37
|
connection.listener.fetch_loop
|
|
36
38
|
connection.listener.fetch_loop.received
|
|
39
|
+
connection.listener.after_fetch_loop
|
|
37
40
|
|
|
38
|
-
|
|
39
|
-
connection.client.unsubscribe.error
|
|
40
|
-
|
|
41
|
-
rebalance.partitions_assign
|
|
42
|
-
rebalance.partitions_assigned
|
|
43
|
-
rebalance.partitions_revoke
|
|
44
|
-
rebalance.partitions_revoked
|
|
45
|
-
|
|
46
|
-
consumer.before_enqueue
|
|
41
|
+
consumer.before_schedule_consume
|
|
47
42
|
consumer.consume
|
|
48
43
|
consumer.consumed
|
|
49
44
|
consumer.consuming.pause
|
|
50
45
|
consumer.consuming.retry
|
|
46
|
+
|
|
47
|
+
consumer.before_schedule_idle
|
|
51
48
|
consumer.idle
|
|
49
|
+
|
|
50
|
+
consumer.before_schedule_revoked
|
|
52
51
|
consumer.revoke
|
|
53
52
|
consumer.revoked
|
|
53
|
+
|
|
54
|
+
consumer.before_schedule_tick
|
|
55
|
+
consumer.tick
|
|
56
|
+
consumer.ticked
|
|
57
|
+
|
|
58
|
+
consumer.before_schedule_shutdown
|
|
54
59
|
consumer.shutting_down
|
|
55
60
|
consumer.shutdown
|
|
56
61
|
|
|
@@ -61,6 +66,11 @@ module Karafka
|
|
|
61
66
|
|
|
62
67
|
process.notice_signal
|
|
63
68
|
|
|
69
|
+
rebalance.partitions_assign
|
|
70
|
+
rebalance.partitions_assigned
|
|
71
|
+
rebalance.partitions_revoke
|
|
72
|
+
rebalance.partitions_revoked
|
|
73
|
+
|
|
64
74
|
statistics.emitted
|
|
65
75
|
|
|
66
76
|
worker.process
|
|
@@ -42,6 +42,16 @@ module Karafka
|
|
|
42
42
|
|
|
43
43
|
configure
|
|
44
44
|
|
|
45
|
+
# Types of errors originating from user code in the consumer flow
|
|
46
|
+
USER_CONSUMER_ERROR_TYPES = %w[
|
|
47
|
+
consumer.consume.error
|
|
48
|
+
consumer.revoked.error
|
|
49
|
+
consumer.shutdown.error
|
|
50
|
+
consumer.tick.error
|
|
51
|
+
].freeze
|
|
52
|
+
|
|
53
|
+
private_constant :USER_CONSUMER_ERROR_TYPES
|
|
54
|
+
|
|
45
55
|
# Before each consumption process, lets start a transaction associated with it
|
|
46
56
|
# We also set some basic metadata about the given consumption that can be useful for
|
|
47
57
|
# debugging
|
|
@@ -94,34 +104,27 @@ module Karafka
|
|
|
94
104
|
client.register_probe(:karafka, -> { minute_probe })
|
|
95
105
|
end
|
|
96
106
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
# Keeps track of revocation user code execution
|
|
113
|
-
#
|
|
114
|
-
# @param event [Karafka::Core::Monitoring::Event]
|
|
115
|
-
def on_consumer_shutting_down(event)
|
|
116
|
-
consumer = event.payload[:caller]
|
|
117
|
-
start_transaction(consumer, 'shutdown')
|
|
118
|
-
end
|
|
107
|
+
[
|
|
108
|
+
%i[revoke revoked revoked],
|
|
109
|
+
%i[shutting_down shutdown shutdown],
|
|
110
|
+
%i[tick ticked tick]
|
|
111
|
+
].each do |before, after, name|
|
|
112
|
+
class_eval <<~RUBY, __FILE__, __LINE__ + 1
|
|
113
|
+
# Keeps track of user code execution
|
|
114
|
+
#
|
|
115
|
+
# @param event [Karafka::Core::Monitoring::Event]
|
|
116
|
+
def on_consumer_#{before}(event)
|
|
117
|
+
consumer = event.payload[:caller]
|
|
118
|
+
start_transaction(consumer, '#{name}')
|
|
119
|
+
end
|
|
119
120
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
121
|
+
# Finishes the transaction
|
|
122
|
+
#
|
|
123
|
+
# @param _event [Karafka::Core::Monitoring::Event]
|
|
124
|
+
def on_consumer_#{after}(_event)
|
|
125
|
+
stop_transaction
|
|
126
|
+
end
|
|
127
|
+
RUBY
|
|
125
128
|
end
|
|
126
129
|
|
|
127
130
|
# Counts DLQ dispatches
|
|
@@ -141,7 +144,7 @@ module Karafka
|
|
|
141
144
|
# @param event [Karafka::Core::Monitoring::Event] error event details
|
|
142
145
|
def on_error_occurred(event)
|
|
143
146
|
# If this is a user consumption related error, we bump the counters for metrics
|
|
144
|
-
if event[:type]
|
|
147
|
+
if USER_CONSUMER_ERROR_TYPES.include?(event[:type])
|
|
145
148
|
consumer = event.payload[:caller]
|
|
146
149
|
|
|
147
150
|
with_multiple_resolutions(consumer) do |tags|
|
|
@@ -55,7 +55,24 @@ module Karafka
|
|
|
55
55
|
consumer = job.executor.topic.consumer
|
|
56
56
|
topic = job.executor.topic.name
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
action = case job_type
|
|
59
|
+
when 'Periodic'
|
|
60
|
+
'tick'
|
|
61
|
+
when 'PeriodicNonBlocking'
|
|
62
|
+
'tick'
|
|
63
|
+
when 'Shutdown'
|
|
64
|
+
'shutdown'
|
|
65
|
+
when 'Revoked'
|
|
66
|
+
'revoked'
|
|
67
|
+
when 'RevokedNonBlocking'
|
|
68
|
+
'revoked'
|
|
69
|
+
when 'Idle'
|
|
70
|
+
'idle'
|
|
71
|
+
else
|
|
72
|
+
'consume'
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
current_span.resource = "#{consumer}##{action}"
|
|
59
76
|
info "[#{job.id}] #{job_type} job for #{consumer} on #{topic} started"
|
|
60
77
|
|
|
61
78
|
pop_tags
|
|
@@ -94,14 +111,16 @@ module Karafka
|
|
|
94
111
|
error "Consumer consuming error: #{error}"
|
|
95
112
|
when 'consumer.revoked.error'
|
|
96
113
|
error "Consumer on revoked failed due to an error: #{error}"
|
|
97
|
-
when 'consumer.
|
|
98
|
-
error "Consumer before
|
|
114
|
+
when 'consumer.before_schedule.error'
|
|
115
|
+
error "Consumer before schedule failed due to an error: #{error}"
|
|
99
116
|
when 'consumer.before_consume.error'
|
|
100
117
|
error "Consumer before consume failed due to an error: #{error}"
|
|
101
118
|
when 'consumer.after_consume.error'
|
|
102
119
|
error "Consumer after consume failed due to an error: #{error}"
|
|
103
120
|
when 'consumer.shutdown.error'
|
|
104
121
|
error "Consumer on shutdown failed due to an error: #{error}"
|
|
122
|
+
when 'consumer.tick.error'
|
|
123
|
+
error "Consumer tick failed due to an error: #{error}"
|
|
105
124
|
when 'worker.process.error'
|
|
106
125
|
fatal "Worker processing failed due to an error: #{error}"
|
|
107
126
|
when 'connection.listener.fetch_loop.error'
|
|
@@ -128,18 +128,21 @@ module Karafka
|
|
|
128
128
|
histogram('consumer.consumption_lag', metadata.consumption_lag, tags: tags)
|
|
129
129
|
end
|
|
130
130
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
131
|
+
{
|
|
132
|
+
revoked: :revoked,
|
|
133
|
+
shutdown: :shutdown,
|
|
134
|
+
ticked: :tick
|
|
135
|
+
}.each do |after, name|
|
|
136
|
+
class_eval <<~RUBY, __FILE__, __LINE__ + 1
|
|
137
|
+
# Keeps track of user code execution
|
|
138
|
+
#
|
|
139
|
+
# @param event [Karafka::Core::Monitoring::Event]
|
|
140
|
+
def on_consumer_#{after}(event)
|
|
141
|
+
tags = default_tags + consumer_tags(event.payload[:caller])
|
|
142
|
+
|
|
143
|
+
count('consumer.#{name}', 1, tags: tags)
|
|
144
|
+
end
|
|
145
|
+
RUBY
|
|
143
146
|
end
|
|
144
147
|
|
|
145
148
|
# Worker related metrics
|
|
@@ -15,6 +15,14 @@ module Karafka
|
|
|
15
15
|
# data would be processed, but process itself would still be active. This listener allows
|
|
16
16
|
# for defining of a ttl that gets bumped on each poll loop and before and after processing
|
|
17
17
|
# of a given messages batch.
|
|
18
|
+
#
|
|
19
|
+
# @note This listener will bind itself only when Karafka will actually attempt to start
|
|
20
|
+
# and moves from initializing to running. Before that, the TCP server will NOT be active.
|
|
21
|
+
# This is done on purpose to mitigate a case where users would subscribe this listener
|
|
22
|
+
# in `karafka.rb` without checking the recommendations of conditional assignment.
|
|
23
|
+
#
|
|
24
|
+
# @note In case of usage within an embedding with Puma, you need to select different port
|
|
25
|
+
# then the one used by Puma itself.
|
|
18
26
|
class LivenessListener
|
|
19
27
|
include ::Karafka::Core::Helpers::Time
|
|
20
28
|
|
|
@@ -40,12 +48,18 @@ module Karafka
|
|
|
40
48
|
consuming_ttl: 5 * 60 * 1_000,
|
|
41
49
|
polling_ttl: 5 * 60 * 1_000
|
|
42
50
|
)
|
|
43
|
-
@
|
|
51
|
+
@hostname = hostname
|
|
52
|
+
@port = port
|
|
44
53
|
@polling_ttl = polling_ttl
|
|
45
54
|
@consuming_ttl = consuming_ttl
|
|
46
55
|
@mutex = Mutex.new
|
|
47
56
|
@pollings = {}
|
|
48
57
|
@consumptions = {}
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# @param _event [Karafka::Core::Monitoring::Event]
|
|
61
|
+
def on_app_running(_event)
|
|
62
|
+
@server = TCPServer.new(*[@hostname, @port].compact)
|
|
49
63
|
|
|
50
64
|
Thread.new do
|
|
51
65
|
loop do
|
|
@@ -54,42 +68,37 @@ module Karafka
|
|
|
54
68
|
end
|
|
55
69
|
end
|
|
56
70
|
|
|
57
|
-
#
|
|
58
|
-
# @param _event [Karafka::Core::Monitoring::Event]
|
|
59
|
-
def on_connection_listener_fetch_loop(_event)
|
|
60
|
-
mark_polling_tick
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
# Tick on starting work
|
|
64
|
-
# @param _event [Karafka::Core::Monitoring::Event]
|
|
65
|
-
def on_consumer_consume(_event)
|
|
66
|
-
mark_consumption_tick
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
# Tick on finished work
|
|
70
|
-
# @param _event [Karafka::Core::Monitoring::Event]
|
|
71
|
-
def on_consumer_consumed(_event)
|
|
72
|
-
clear_consumption_tick
|
|
73
|
-
end
|
|
74
|
-
|
|
71
|
+
# Stop the http server when we stop the process
|
|
75
72
|
# @param _event [Karafka::Core::Monitoring::Event]
|
|
76
|
-
def
|
|
77
|
-
|
|
73
|
+
def on_app_stopped(_event)
|
|
74
|
+
@server.close
|
|
78
75
|
end
|
|
79
76
|
|
|
77
|
+
# Tick on each fetch
|
|
80
78
|
# @param _event [Karafka::Core::Monitoring::Event]
|
|
81
|
-
def
|
|
82
|
-
|
|
79
|
+
def on_connection_listener_fetch_loop(_event)
|
|
80
|
+
mark_polling_tick
|
|
83
81
|
end
|
|
84
82
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
83
|
+
{
|
|
84
|
+
consume: :consumed,
|
|
85
|
+
revoke: :revoked,
|
|
86
|
+
shutting_down: :shutdown,
|
|
87
|
+
tick: :ticked
|
|
88
|
+
}.each do |before, after|
|
|
89
|
+
class_eval <<~RUBY, __FILE__, __LINE__ + 1
|
|
90
|
+
# Tick on starting work
|
|
91
|
+
# @param _event [Karafka::Core::Monitoring::Event]
|
|
92
|
+
def on_consumer_#{before}(_event)
|
|
93
|
+
mark_consumption_tick
|
|
94
|
+
end
|
|
89
95
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
96
|
+
# Tick on finished work
|
|
97
|
+
# @param _event [Karafka::Core::Monitoring::Event]
|
|
98
|
+
def on_consumer_#{after}(_event)
|
|
99
|
+
clear_consumption_tick
|
|
100
|
+
end
|
|
101
|
+
RUBY
|
|
93
102
|
end
|
|
94
103
|
|
|
95
104
|
# @param _event [Karafka::Core::Monitoring::Event]
|
|
@@ -98,12 +107,6 @@ module Karafka
|
|
|
98
107
|
clear_polling_tick
|
|
99
108
|
end
|
|
100
109
|
|
|
101
|
-
# Stop the http server when we stop the process
|
|
102
|
-
# @param _event [Karafka::Core::Monitoring::Event]
|
|
103
|
-
def on_app_stopped(_event)
|
|
104
|
-
@server.close
|
|
105
|
-
end
|
|
106
|
-
|
|
107
110
|
private
|
|
108
111
|
|
|
109
112
|
# Wraps the logic with a mutex
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# This Karafka component is a Pro component under a commercial license.
|
|
4
|
+
# This Karafka component is NOT licensed under LGPL.
|
|
5
|
+
#
|
|
6
|
+
# All of the commercial components are present in the lib/karafka/pro directory of this
|
|
7
|
+
# repository and their usage requires commercial license agreement.
|
|
8
|
+
#
|
|
9
|
+
# Karafka has also commercial-friendly license, commercial support and commercial components.
|
|
10
|
+
#
|
|
11
|
+
# By sending a pull request to the pro components, you are agreeing to transfer the copyright of
|
|
12
|
+
# your code to Maciej Mensfeld.
|
|
13
|
+
|
|
14
|
+
module Karafka
|
|
15
|
+
module Pro
|
|
16
|
+
# Extra methods always used in the base consumer in the pro mode
|
|
17
|
+
#
|
|
18
|
+
# We do not define those methods as part of the strategies flows, because they are injected
|
|
19
|
+
# (strategies) on singletons and often used only in one of the strategy variants
|
|
20
|
+
#
|
|
21
|
+
# Methods here are suppose to be always available or are expected to be redefined
|
|
22
|
+
module BaseConsumer
|
|
23
|
+
# Runs the on-schedule tick periodic operations
|
|
24
|
+
# This method is an alias but is part of the naming convention used for other flows, this
|
|
25
|
+
# is why we do not reference the `handle_before_schedule_tick` directly
|
|
26
|
+
def on_before_schedule_tick
|
|
27
|
+
handle_before_schedule_tick
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Used by the executor to trigger consumer tick
|
|
31
|
+
# @private
|
|
32
|
+
def on_tick
|
|
33
|
+
handle_tick
|
|
34
|
+
rescue StandardError => e
|
|
35
|
+
Karafka.monitor.instrument(
|
|
36
|
+
'error.occurred',
|
|
37
|
+
error: e,
|
|
38
|
+
caller: self,
|
|
39
|
+
type: 'consumer.tick.error'
|
|
40
|
+
)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# By default we do nothing when ticking
|
|
44
|
+
def tick; end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|