karafka 2.2.13 → 2.3.0.alpha1
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 +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
@@ -14,12 +14,19 @@ module Karafka
|
|
14
14
|
# @param max_retries [Integer] after how many retries should we move data to dlq
|
15
15
|
# @param topic [String, false] where the messages should be moved if failing or false
|
16
16
|
# if we do not want to move it anywhere and just skip
|
17
|
+
# @param independent [Boolean] needs to be true in order for each marking as consumed
|
18
|
+
# in a retry flow to reset the errors counter
|
17
19
|
# @return [Config] defined config
|
18
|
-
def dead_letter_queue(
|
20
|
+
def dead_letter_queue(
|
21
|
+
max_retries: DEFAULT_MAX_RETRIES,
|
22
|
+
topic: nil,
|
23
|
+
independent: false
|
24
|
+
)
|
19
25
|
@dead_letter_queue ||= Config.new(
|
20
26
|
active: !topic.nil?,
|
21
27
|
max_retries: max_retries,
|
22
|
-
topic: topic
|
28
|
+
topic: topic,
|
29
|
+
independent: independent
|
23
30
|
)
|
24
31
|
end
|
25
32
|
|
@@ -10,11 +10,12 @@ module Karafka
|
|
10
10
|
# @param target [Object] target object to which we proxy any DSL call
|
11
11
|
# @param defaults [Proc] defaults for target that should be applicable after the proper
|
12
12
|
# proxy context (if needed)
|
13
|
-
# @param block [Proc] block that we want to evaluate in the proxy context
|
13
|
+
# @param block [Proc, nil] block that we want to evaluate in the proxy context or nil if no
|
14
|
+
# proxy block context for example because whole context is taken from defaults
|
14
15
|
def initialize(target, defaults = ->(_) {}, &block)
|
15
16
|
@target = target
|
16
|
-
instance_eval(&block)
|
17
|
-
instance_eval(&defaults)
|
17
|
+
instance_eval(&block) if block
|
18
|
+
instance_eval(&defaults) if defaults
|
18
19
|
end
|
19
20
|
|
20
21
|
# Ruby 2.7.0 to 2.7.2 do not have arg forwarding, so we fallback to the old way
|
@@ -37,7 +37,8 @@ module Karafka
|
|
37
37
|
# @param topics [Karafka::Routing::Topics] all the topics that share the same key settings
|
38
38
|
# @return [SubscriptionGroup] built subscription group
|
39
39
|
def initialize(position, topics)
|
40
|
-
@
|
40
|
+
@details = topics.first.subscription_group_details
|
41
|
+
@name = @details.fetch(:name)
|
41
42
|
@consumer_group = topics.first.consumer_group
|
42
43
|
# We include the consumer group id here because we want to have unique ids of subscription
|
43
44
|
# groups across the system. Otherwise user could set the same name for multiple
|
@@ -47,7 +48,6 @@ module Karafka
|
|
47
48
|
@position = position
|
48
49
|
@topics = topics
|
49
50
|
@kafka = build_kafka
|
50
|
-
freeze
|
51
51
|
end
|
52
52
|
|
53
53
|
# @return [String] consumer group id
|
@@ -19,7 +19,7 @@ module Karafka
|
|
19
19
|
max_messages
|
20
20
|
max_wait_time
|
21
21
|
initial_offset
|
22
|
-
|
22
|
+
subscription_group_details
|
23
23
|
].freeze
|
24
24
|
|
25
25
|
private_constant :DISTRIBUTION_KEYS
|
@@ -37,7 +37,7 @@ module Karafka
|
|
37
37
|
.group_by(&:first)
|
38
38
|
.values
|
39
39
|
.map { |value| value.map(&:last) }
|
40
|
-
.
|
40
|
+
.flat_map { |value| expand(value) }
|
41
41
|
.map { |grouped_topics| SubscriptionGroup.new(@position += 1, grouped_topics) }
|
42
42
|
.tap do |subscription_groups|
|
43
43
|
subscription_groups.each do |subscription_group|
|
@@ -60,6 +60,15 @@ module Karafka
|
|
60
60
|
|
61
61
|
accu.hash
|
62
62
|
end
|
63
|
+
|
64
|
+
# Hook for optional expansion of groups based on subscription group features
|
65
|
+
#
|
66
|
+
# @param topics_array [Array<Routing::Topic>] group of topics that have the same settings
|
67
|
+
# and can use the same connection
|
68
|
+
# @return [Array<Array<Routing::Topics>>] expanded groups
|
69
|
+
def expand(topics_array)
|
70
|
+
[Routing::Topics.new(topics_array)]
|
71
|
+
end
|
63
72
|
end
|
64
73
|
end
|
65
74
|
end
|
@@ -9,7 +9,7 @@ module Karafka
|
|
9
9
|
attr_reader :id, :name, :consumer_group
|
10
10
|
attr_writer :consumer
|
11
11
|
|
12
|
-
attr_accessor :
|
12
|
+
attr_accessor :subscription_group_details
|
13
13
|
|
14
14
|
# Full subscription group reference can be built only when we have knowledge about the
|
15
15
|
# whole routing tree, this is why it is going to be set later on
|
@@ -46,15 +46,13 @@ module Karafka
|
|
46
46
|
INHERITABLE_ATTRIBUTES.each do |attribute|
|
47
47
|
attr_writer attribute
|
48
48
|
|
49
|
-
|
50
|
-
|
49
|
+
class_eval <<~RUBY, __FILE__, __LINE__ + 1
|
50
|
+
def #{attribute}
|
51
|
+
return @#{attribute} unless @#{attribute}.nil?
|
51
52
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
instance_variable_set(:"@#{attribute}", value)
|
57
|
-
end
|
53
|
+
@#{attribute} = Karafka::App.config.send(:#{attribute})
|
54
|
+
end
|
55
|
+
RUBY
|
58
56
|
end
|
59
57
|
|
60
58
|
# @return [String] name of subscription that will go to librdkafka
|
@@ -117,7 +115,7 @@ module Karafka
|
|
117
115
|
active: active?,
|
118
116
|
consumer: consumer,
|
119
117
|
consumer_group_id: consumer_group.id,
|
120
|
-
|
118
|
+
subscription_group_details: subscription_group_details
|
121
119
|
).freeze
|
122
120
|
end
|
123
121
|
end
|
@@ -9,7 +9,7 @@ module Karafka
|
|
9
9
|
include Enumerable
|
10
10
|
extend Forwardable
|
11
11
|
|
12
|
-
def_delegators :@accumulator, :[], :size, :empty?, :last,
|
12
|
+
def_delegators :@accumulator, :[], :size, :empty?, :last, :<<, :map!, :sort_by!, :reverse!
|
13
13
|
|
14
14
|
# @param topics_array [Array<Karafka::Routing::Topic>] array with topics
|
15
15
|
def initialize(topics_array)
|
data/lib/karafka/runner.rb
CHANGED
@@ -3,6 +3,11 @@
|
|
3
3
|
module Karafka
|
4
4
|
# Class used to run the Karafka listeners in separate threads
|
5
5
|
class Runner
|
6
|
+
def initialize
|
7
|
+
@manager = App.config.internal.connection.manager
|
8
|
+
@conductor = App.config.internal.connection.conductor
|
9
|
+
end
|
10
|
+
|
6
11
|
# Starts listening on all the listeners asynchronously and handles the jobs queue closing
|
7
12
|
# after listeners are done with their work.
|
8
13
|
def call
|
@@ -13,16 +18,21 @@ module Karafka
|
|
13
18
|
workers = Processing::WorkersBatch.new(jobs_queue)
|
14
19
|
listeners = Connection::ListenersBatch.new(jobs_queue)
|
15
20
|
|
21
|
+
# Register all the listeners so they can be started and managed
|
22
|
+
@manager.register(listeners)
|
23
|
+
|
16
24
|
workers.each(&:async_call)
|
17
|
-
listeners.each(&:async_call)
|
18
25
|
|
19
26
|
# We aggregate threads here for a supervised shutdown process
|
20
27
|
Karafka::Server.workers = workers
|
21
28
|
Karafka::Server.listeners = listeners
|
22
29
|
Karafka::Server.jobs_queue = jobs_queue
|
23
30
|
|
24
|
-
|
25
|
-
|
31
|
+
until @manager.done?
|
32
|
+
@conductor.wait
|
33
|
+
|
34
|
+
@manager.control
|
35
|
+
end
|
26
36
|
|
27
37
|
# We close the jobs queue only when no listener threads are working.
|
28
38
|
# This ensures, that everything was closed prior to us not accepting anymore jobs and that
|
data/lib/karafka/server.rb
CHANGED
@@ -88,7 +88,10 @@ module Karafka
|
|
88
88
|
# their work and if so, we can just return and normal shutdown process will take place
|
89
89
|
# We divide it by 1000 because we use time in ms.
|
90
90
|
((timeout / 1_000) * SUPERVISION_CHECK_FACTOR).to_i.times do
|
91
|
-
|
91
|
+
all_listeners_stopped = listeners.all?(&:stopped?)
|
92
|
+
all_workers_stopped = workers.none?(&:alive?)
|
93
|
+
|
94
|
+
return if all_listeners_stopped && all_workers_stopped
|
92
95
|
|
93
96
|
sleep SUPERVISION_SLEEP
|
94
97
|
end
|
@@ -104,7 +107,7 @@ module Karafka
|
|
104
107
|
|
105
108
|
# We're done waiting, lets kill them!
|
106
109
|
workers.each(&:terminate)
|
107
|
-
listeners.each(&:terminate)
|
110
|
+
listeners.active.each(&:terminate)
|
108
111
|
# We always need to shutdown clients to make sure we do not force the GC to close consumer.
|
109
112
|
# This can cause memory leaks and crashes.
|
110
113
|
listeners.each(&:shutdown)
|
@@ -137,13 +140,6 @@ module Karafka
|
|
137
140
|
# We don't have to safe-guard it with check states as the state transitions work only
|
138
141
|
# in one direction
|
139
142
|
Karafka::App.quiet!
|
140
|
-
|
141
|
-
# We need one more thread to monitor the process and move to quieted once everything
|
142
|
-
# is quiet and no processing is happening anymore
|
143
|
-
Thread.new do
|
144
|
-
sleep(0.1) until listeners.coordinators.all?(&:finished?)
|
145
|
-
Karafka::App.quieted!
|
146
|
-
end
|
147
143
|
end
|
148
144
|
|
149
145
|
private
|
data/lib/karafka/setup/config.rb
CHANGED
@@ -184,8 +184,23 @@ module Karafka
|
|
184
184
|
|
185
185
|
# Namespace for internal connection related settings
|
186
186
|
setting :connection do
|
187
|
+
# Manages starting up and stopping Kafka connections
|
188
|
+
setting :manager, default: Connection::Manager.new
|
189
|
+
# Controls frequency of connections management checks
|
190
|
+
setting :conductor, default: Connection::Conductor.new
|
191
|
+
|
187
192
|
# Settings that are altered by our client proxy layer
|
188
193
|
setting :proxy do
|
194
|
+
# Committed offsets for given CG query
|
195
|
+
setting :committed do
|
196
|
+
# timeout for this request. For busy or remote clusters, this should be high enough
|
197
|
+
setting :timeout, default: 5_000
|
198
|
+
# How many times should we try to run this call before raising an error
|
199
|
+
setting :max_attempts, default: 3
|
200
|
+
# How long should we wait before next attempt in case of a failure
|
201
|
+
setting :wait_time, default: 1_000
|
202
|
+
end
|
203
|
+
|
189
204
|
# Watermark offsets request settings
|
190
205
|
setting :query_watermark_offsets do
|
191
206
|
# timeout for this request. For busy or remote clusters, this should be high enough
|
@@ -211,7 +226,7 @@ module Karafka
|
|
211
226
|
setting :processing do
|
212
227
|
setting :jobs_queue_class, default: Processing::JobsQueue
|
213
228
|
# option scheduler [Object] scheduler we will be using
|
214
|
-
setting :scheduler_class, default: Processing::
|
229
|
+
setting :scheduler_class, default: Processing::Schedulers::Default
|
215
230
|
# option jobs_builder [Object] jobs builder we want to use
|
216
231
|
setting :jobs_builder, default: Processing::JobsBuilder.new
|
217
232
|
# option coordinator [Class] work coordinator we want to user for processing coordination
|
@@ -222,6 +237,8 @@ module Karafka
|
|
222
237
|
setting :strategy_selector, default: Processing::StrategySelector.new
|
223
238
|
# option expansions_selector [Object] processing expansions selector to be used
|
224
239
|
setting :expansions_selector, default: Processing::ExpansionsSelector.new
|
240
|
+
# option [Class] executor class
|
241
|
+
setting :executor_class, default: Processing::Executor
|
225
242
|
end
|
226
243
|
|
227
244
|
# Things related to operating on messages
|
@@ -278,6 +295,9 @@ module Karafka
|
|
278
295
|
# are also configured
|
279
296
|
Pro::Loader.post_setup_all(config) if Karafka.pro?
|
280
297
|
|
298
|
+
# Subscribe the assignments tracker so we can always query all current assignments
|
299
|
+
config.monitor.subscribe(Instrumentation::AssignmentsTracker.instance)
|
300
|
+
|
281
301
|
Karafka::App.initialized!
|
282
302
|
end
|
283
303
|
|
data/lib/karafka/status.rb
CHANGED
@@ -42,25 +42,34 @@ module Karafka
|
|
42
42
|
end
|
43
43
|
|
44
44
|
STATES.each do |state, transition|
|
45
|
-
|
46
|
-
|
47
|
-
|
45
|
+
class_eval <<~RUBY, __FILE__, __LINE__ + 1
|
46
|
+
def #{state}?
|
47
|
+
@status == :#{state}
|
48
|
+
end
|
49
|
+
|
50
|
+
def #{transition}
|
51
|
+
MUTEX.synchronize do
|
52
|
+
# Do not allow reverse state transitions (we always go one way) or transition to the same
|
53
|
+
# state as currently
|
54
|
+
return if @status && STATES.keys.index(:#{state}) <= STATES.keys.index(@status)
|
48
55
|
|
49
|
-
|
50
|
-
MUTEX.synchronize do
|
51
|
-
# Do not allow reverse state transitions (we always go one way) or transition to the same
|
52
|
-
# state as currently
|
53
|
-
return if @status && STATES.keys.index(state) <= STATES.keys.index(@status)
|
56
|
+
@status = :#{state}
|
54
57
|
|
55
|
-
|
58
|
+
# Skip on creation (initializing)
|
59
|
+
# We skip as during this state we do not have yet a monitor
|
60
|
+
return if initializing?
|
56
61
|
|
57
|
-
|
58
|
-
|
59
|
-
|
62
|
+
# We do not set conductor in the initializer because this status object is created
|
63
|
+
# before the configuration kicks in
|
64
|
+
# We need to signal conductor on each state change as those may be relevant to
|
65
|
+
# listeners operations
|
66
|
+
@conductor ||= Karafka::App.config.internal.connection.conductor
|
67
|
+
@conductor.signal
|
60
68
|
|
61
|
-
|
69
|
+
Karafka.monitor.instrument("app.#{state}")
|
70
|
+
end
|
62
71
|
end
|
63
|
-
|
72
|
+
RUBY
|
64
73
|
end
|
65
74
|
|
66
75
|
# @return [Boolean] true if we are in any of the status that would indicate we should no longer
|
@@ -68,3 +68,10 @@ class KarafkaApp < Karafka::App
|
|
68
68
|
end
|
69
69
|
end
|
70
70
|
end
|
71
|
+
|
72
|
+
# Karafka now features a Web UI!
|
73
|
+
# Visit the setup documentation to get started and enhance your experience.
|
74
|
+
#
|
75
|
+
# https://karafka.io/docs/Web-UI-Getting-Started
|
76
|
+
#
|
77
|
+
# Karafka::Web.enable!
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Karafka
|
4
|
+
module TimeTrackers
|
5
|
+
# Tracker used to keep time reference when we last time dispatched any job related to a given
|
6
|
+
# topic partition.
|
7
|
+
#
|
8
|
+
# We can use it to know when last time a job was scheduled
|
9
|
+
#
|
10
|
+
# @note We do not track revocation as on revocation we clear given topic partition reference
|
11
|
+
# not to have a potential memory leak
|
12
|
+
#
|
13
|
+
# @note We do not track shutdown jobs as shutdown is finishing the process, so no time
|
14
|
+
# sensitive operations remain that would use this
|
15
|
+
#
|
16
|
+
# @note We consider partition as active if we scheduled any job related to it within the tick
|
17
|
+
# interval. This has nothing to do whether a partition is assigned.
|
18
|
+
class PartitionUsage < Base
|
19
|
+
# Creates new partition usage time tracker
|
20
|
+
def initialize
|
21
|
+
super
|
22
|
+
|
23
|
+
@last_usage = Hash.new do |topics_hash, topic_name|
|
24
|
+
topics_hash[topic_name] = Hash.new do |partitions_hash, partition_id|
|
25
|
+
partitions_hash[partition_id] = 0
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# @param topic [String]
|
31
|
+
# @param partition [Integer]
|
32
|
+
# @param interval [Integer] minimum interval
|
33
|
+
# @return [Boolean] was this topic partition active
|
34
|
+
def active?(topic, partition, interval)
|
35
|
+
monotonic_now - @last_usage[topic][partition] < interval
|
36
|
+
end
|
37
|
+
|
38
|
+
# Marks usage of given partition
|
39
|
+
#
|
40
|
+
# @param topic [String]
|
41
|
+
# @param partition [Integer]
|
42
|
+
def track(topic, partition)
|
43
|
+
@last_usage[topic][partition] = monotonic_now
|
44
|
+
end
|
45
|
+
|
46
|
+
# Clears references about given partition. Useful on revocation so we do not store old
|
47
|
+
# unassigned partitions data
|
48
|
+
#
|
49
|
+
# @param topic [String]
|
50
|
+
# @param partition [Integer]
|
51
|
+
def revoke(topic, partition)
|
52
|
+
@last_usage[topic].delete(partition)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
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
|
+
version: 2.3.0.alpha1
|
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:
|
38
|
+
date: 2024-01-15 00:00:00.000000000 Z
|
39
39
|
dependencies:
|
40
40
|
- !ruby/object:Gem::Dependency
|
41
41
|
name: karafka-core
|
@@ -43,27 +43,27 @@ dependencies:
|
|
43
43
|
requirements:
|
44
44
|
- - ">="
|
45
45
|
- !ruby/object:Gem::Version
|
46
|
-
version: 2.
|
46
|
+
version: 2.3.0.alpha1
|
47
47
|
- - "<"
|
48
48
|
- !ruby/object:Gem::Version
|
49
|
-
version: 2.
|
49
|
+
version: 2.4.0
|
50
50
|
type: :runtime
|
51
51
|
prerelease: false
|
52
52
|
version_requirements: !ruby/object:Gem::Requirement
|
53
53
|
requirements:
|
54
54
|
- - ">="
|
55
55
|
- !ruby/object:Gem::Version
|
56
|
-
version: 2.
|
56
|
+
version: 2.3.0.alpha1
|
57
57
|
- - "<"
|
58
58
|
- !ruby/object:Gem::Version
|
59
|
-
version: 2.
|
59
|
+
version: 2.4.0
|
60
60
|
- !ruby/object:Gem::Dependency
|
61
61
|
name: waterdrop
|
62
62
|
requirement: !ruby/object:Gem::Requirement
|
63
63
|
requirements:
|
64
64
|
- - ">="
|
65
65
|
- !ruby/object:Gem::Version
|
66
|
-
version: 2.6.
|
66
|
+
version: 2.6.12
|
67
67
|
- - "<"
|
68
68
|
- !ruby/object:Gem::Version
|
69
69
|
version: 3.0.0
|
@@ -73,7 +73,7 @@ dependencies:
|
|
73
73
|
requirements:
|
74
74
|
- - ">="
|
75
75
|
- !ruby/object:Gem::Version
|
76
|
-
version: 2.6.
|
76
|
+
version: 2.6.12
|
77
77
|
- - "<"
|
78
78
|
- !ruby/object:Gem::Version
|
79
79
|
version: 3.0.0
|
@@ -123,6 +123,7 @@ files:
|
|
123
123
|
- LICENSE-COMM
|
124
124
|
- LICENSE-LGPL
|
125
125
|
- README.md
|
126
|
+
- SECURITY.md
|
126
127
|
- bin/benchmarks
|
127
128
|
- bin/create_token
|
128
129
|
- bin/integrations
|
@@ -151,6 +152,7 @@ files:
|
|
151
152
|
- lib/karafka/active_job/job_extensions.rb
|
152
153
|
- lib/karafka/active_job/job_options_contract.rb
|
153
154
|
- lib/karafka/admin.rb
|
155
|
+
- lib/karafka/admin/acl.rb
|
154
156
|
- lib/karafka/app.rb
|
155
157
|
- lib/karafka/base_consumer.rb
|
156
158
|
- lib/karafka/cli.rb
|
@@ -162,14 +164,16 @@ files:
|
|
162
164
|
- lib/karafka/cli/server.rb
|
163
165
|
- lib/karafka/cli/topics.rb
|
164
166
|
- lib/karafka/connection/client.rb
|
165
|
-
- lib/karafka/connection/
|
167
|
+
- lib/karafka/connection/conductor.rb
|
166
168
|
- lib/karafka/connection/listener.rb
|
167
169
|
- lib/karafka/connection/listeners_batch.rb
|
170
|
+
- lib/karafka/connection/manager.rb
|
168
171
|
- lib/karafka/connection/messages_buffer.rb
|
169
172
|
- lib/karafka/connection/pauses_manager.rb
|
170
173
|
- lib/karafka/connection/proxy.rb
|
171
174
|
- lib/karafka/connection/raw_messages_buffer.rb
|
172
175
|
- lib/karafka/connection/rebalance_manager.rb
|
176
|
+
- lib/karafka/connection/status.rb
|
173
177
|
- lib/karafka/contracts.rb
|
174
178
|
- lib/karafka/contracts/base.rb
|
175
179
|
- lib/karafka/contracts/config.rb
|
@@ -183,6 +187,7 @@ files:
|
|
183
187
|
- lib/karafka/helpers/colorize.rb
|
184
188
|
- lib/karafka/helpers/interval_runner.rb
|
185
189
|
- lib/karafka/helpers/multi_delegator.rb
|
190
|
+
- lib/karafka/instrumentation/assignments_tracker.rb
|
186
191
|
- lib/karafka/instrumentation/callbacks/error.rb
|
187
192
|
- lib/karafka/instrumentation/callbacks/rebalance.rb
|
188
193
|
- lib/karafka/instrumentation/callbacks/statistics.rb
|
@@ -216,10 +221,13 @@ files:
|
|
216
221
|
- lib/karafka/pro/active_job/consumer.rb
|
217
222
|
- lib/karafka/pro/active_job/dispatcher.rb
|
218
223
|
- lib/karafka/pro/active_job/job_options_contract.rb
|
224
|
+
- lib/karafka/pro/base_consumer.rb
|
219
225
|
- lib/karafka/pro/cleaner.rb
|
220
226
|
- lib/karafka/pro/cleaner/errors.rb
|
221
227
|
- lib/karafka/pro/cleaner/messages/message.rb
|
222
228
|
- lib/karafka/pro/cleaner/messages/messages.rb
|
229
|
+
- lib/karafka/pro/connection/manager.rb
|
230
|
+
- lib/karafka/pro/connection/multiplexing/listener.rb
|
223
231
|
- lib/karafka/pro/contracts/base.rb
|
224
232
|
- lib/karafka/pro/contracts/server_cli_options.rb
|
225
233
|
- lib/karafka/pro/encryption.rb
|
@@ -229,13 +237,15 @@ files:
|
|
229
237
|
- lib/karafka/pro/encryption/messages/middleware.rb
|
230
238
|
- lib/karafka/pro/encryption/messages/parser.rb
|
231
239
|
- lib/karafka/pro/encryption/setup/config.rb
|
240
|
+
- lib/karafka/pro/instrumentation/performance_tracker.rb
|
232
241
|
- lib/karafka/pro/iterator.rb
|
233
242
|
- lib/karafka/pro/iterator/expander.rb
|
234
243
|
- lib/karafka/pro/iterator/tpl_builder.rb
|
235
244
|
- lib/karafka/pro/loader.rb
|
236
|
-
- lib/karafka/pro/performance_tracker.rb
|
237
245
|
- lib/karafka/pro/processing/collapser.rb
|
238
246
|
- lib/karafka/pro/processing/coordinator.rb
|
247
|
+
- lib/karafka/pro/processing/executor.rb
|
248
|
+
- lib/karafka/pro/processing/expansions_selector.rb
|
239
249
|
- lib/karafka/pro/processing/filters/base.rb
|
240
250
|
- lib/karafka/pro/processing/filters/delayer.rb
|
241
251
|
- lib/karafka/pro/processing/filters/expirer.rb
|
@@ -244,11 +254,17 @@ files:
|
|
244
254
|
- lib/karafka/pro/processing/filters/virtual_limiter.rb
|
245
255
|
- lib/karafka/pro/processing/filters_applier.rb
|
246
256
|
- lib/karafka/pro/processing/jobs/consume_non_blocking.rb
|
257
|
+
- lib/karafka/pro/processing/jobs/periodic.rb
|
258
|
+
- lib/karafka/pro/processing/jobs/periodic_non_blocking.rb
|
247
259
|
- lib/karafka/pro/processing/jobs/revoked_non_blocking.rb
|
248
260
|
- lib/karafka/pro/processing/jobs_builder.rb
|
249
261
|
- lib/karafka/pro/processing/jobs_queue.rb
|
262
|
+
- lib/karafka/pro/processing/offset_metadata/consumer.rb
|
263
|
+
- lib/karafka/pro/processing/offset_metadata/fetcher.rb
|
264
|
+
- lib/karafka/pro/processing/offset_metadata/listener.rb
|
250
265
|
- lib/karafka/pro/processing/partitioner.rb
|
251
|
-
- lib/karafka/pro/processing/
|
266
|
+
- lib/karafka/pro/processing/schedulers/base.rb
|
267
|
+
- lib/karafka/pro/processing/schedulers/default.rb
|
252
268
|
- lib/karafka/pro/processing/strategies.rb
|
253
269
|
- lib/karafka/pro/processing/strategies/aj/dlq_ftr_lrj_mom.rb
|
254
270
|
- lib/karafka/pro/processing/strategies/aj/dlq_ftr_lrj_mom_vp.rb
|
@@ -326,6 +342,19 @@ files:
|
|
326
342
|
- lib/karafka/pro/routing/features/long_running_job/config.rb
|
327
343
|
- lib/karafka/pro/routing/features/long_running_job/contracts/topic.rb
|
328
344
|
- lib/karafka/pro/routing/features/long_running_job/topic.rb
|
345
|
+
- lib/karafka/pro/routing/features/multiplexing.rb
|
346
|
+
- lib/karafka/pro/routing/features/multiplexing/config.rb
|
347
|
+
- lib/karafka/pro/routing/features/multiplexing/contracts/topic.rb
|
348
|
+
- lib/karafka/pro/routing/features/multiplexing/patches/contracts/consumer_group.rb
|
349
|
+
- lib/karafka/pro/routing/features/multiplexing/proxy.rb
|
350
|
+
- lib/karafka/pro/routing/features/multiplexing/subscription_group.rb
|
351
|
+
- lib/karafka/pro/routing/features/multiplexing/subscription_groups_builder.rb
|
352
|
+
- lib/karafka/pro/routing/features/non_blocking_job.rb
|
353
|
+
- lib/karafka/pro/routing/features/non_blocking_job/topic.rb
|
354
|
+
- lib/karafka/pro/routing/features/offset_metadata.rb
|
355
|
+
- lib/karafka/pro/routing/features/offset_metadata/config.rb
|
356
|
+
- lib/karafka/pro/routing/features/offset_metadata/contracts/topic.rb
|
357
|
+
- lib/karafka/pro/routing/features/offset_metadata/topic.rb
|
329
358
|
- lib/karafka/pro/routing/features/patterns.rb
|
330
359
|
- lib/karafka/pro/routing/features/patterns/builder.rb
|
331
360
|
- lib/karafka/pro/routing/features/patterns/config.rb
|
@@ -341,6 +370,10 @@ files:
|
|
341
370
|
- lib/karafka/pro/routing/features/pausing.rb
|
342
371
|
- lib/karafka/pro/routing/features/pausing/contracts/topic.rb
|
343
372
|
- lib/karafka/pro/routing/features/pausing/topic.rb
|
373
|
+
- lib/karafka/pro/routing/features/periodic_job.rb
|
374
|
+
- lib/karafka/pro/routing/features/periodic_job/config.rb
|
375
|
+
- lib/karafka/pro/routing/features/periodic_job/contracts/topic.rb
|
376
|
+
- lib/karafka/pro/routing/features/periodic_job/topic.rb
|
344
377
|
- lib/karafka/pro/routing/features/throttling.rb
|
345
378
|
- lib/karafka/pro/routing/features/throttling/config.rb
|
346
379
|
- lib/karafka/pro/routing/features/throttling/contracts/topic.rb
|
@@ -367,7 +400,7 @@ files:
|
|
367
400
|
- lib/karafka/processing/jobs_queue.rb
|
368
401
|
- lib/karafka/processing/partitioner.rb
|
369
402
|
- lib/karafka/processing/result.rb
|
370
|
-
- lib/karafka/processing/
|
403
|
+
- lib/karafka/processing/schedulers/default.rb
|
371
404
|
- lib/karafka/processing/strategies/aj_dlq_mom.rb
|
372
405
|
- lib/karafka/processing/strategies/aj_mom.rb
|
373
406
|
- lib/karafka/processing/strategies/base.rb
|
@@ -425,6 +458,7 @@ files:
|
|
425
458
|
- lib/karafka/templates/example_consumer.rb.erb
|
426
459
|
- lib/karafka/templates/karafka.rb.erb
|
427
460
|
- lib/karafka/time_trackers/base.rb
|
461
|
+
- lib/karafka/time_trackers/partition_usage.rb
|
428
462
|
- lib/karafka/time_trackers/pause.rb
|
429
463
|
- lib/karafka/time_trackers/poll.rb
|
430
464
|
- lib/karafka/version.rb
|
@@ -457,7 +491,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
457
491
|
- !ruby/object:Gem::Version
|
458
492
|
version: '0'
|
459
493
|
requirements: []
|
460
|
-
rubygems_version: 3.
|
494
|
+
rubygems_version: 3.5.3
|
461
495
|
signing_key:
|
462
496
|
specification_version: 4
|
463
497
|
summary: Karafka is Ruby and Rails efficient Kafka processing framework.
|
metadata.gz.sig
CHANGED
Binary file
|
@@ -1,48 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Karafka
|
4
|
-
module Connection
|
5
|
-
# This object represents a collective status of execution of group of listeners running inside
|
6
|
-
# of one consumer group but in separate subscription groups.
|
7
|
-
#
|
8
|
-
# There are cases when we do not want to close a given client when others from the same
|
9
|
-
# consumer group are running because it can cause instabilities due to early shutdown of some
|
10
|
-
# of the clients out of same consumer group.
|
11
|
-
#
|
12
|
-
# We also want to make sure, we close one consumer at a time while others can continue polling.
|
13
|
-
#
|
14
|
-
# This prevents a scenario, where a rebalance is not acknowledged and we loose assignment
|
15
|
-
# without having a chance to commit changes.
|
16
|
-
class ConsumerGroupCoordinator
|
17
|
-
# @param group_size [Integer] number of separate subscription groups in a consumer group
|
18
|
-
def initialize(group_size)
|
19
|
-
@shutdown_mutex = Mutex.new
|
20
|
-
@group_size = group_size
|
21
|
-
@finished = Set.new
|
22
|
-
end
|
23
|
-
|
24
|
-
# @return [Boolean] true if all the subscription groups from a given consumer group are
|
25
|
-
# finished
|
26
|
-
def finished?
|
27
|
-
@finished.size == @group_size
|
28
|
-
end
|
29
|
-
|
30
|
-
# @return [Boolean] can we start shutdown on a given listener
|
31
|
-
# @note If true, will also obtain a lock so no-one else will be closing the same time we do
|
32
|
-
def shutdown?
|
33
|
-
finished? && @shutdown_mutex.try_lock
|
34
|
-
end
|
35
|
-
|
36
|
-
# Unlocks the shutdown lock
|
37
|
-
def unlock
|
38
|
-
@shutdown_mutex.unlock if @shutdown_mutex.owned?
|
39
|
-
end
|
40
|
-
|
41
|
-
# Marks given listener as finished
|
42
|
-
# @param listener_id [String]
|
43
|
-
def finish_work(listener_id)
|
44
|
-
@finished << listener_id
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|