karafka 2.2.12 → 2.2.14
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/CHANGELOG.md +141 -121
- data/Gemfile.lock +10 -10
- data/config/locales/errors.yml +2 -1
- data/docker-compose.yml +2 -0
- data/lib/karafka/admin.rb +109 -3
- data/lib/karafka/app.rb +7 -0
- data/lib/karafka/base_consumer.rb +23 -30
- data/lib/karafka/connection/client.rb +13 -10
- data/lib/karafka/connection/consumer_group_coordinator.rb +3 -3
- data/lib/karafka/connection/listener.rb +18 -10
- data/lib/karafka/connection/listeners_batch.rb +6 -1
- data/lib/karafka/contracts/config.rb +2 -1
- 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 +0 -9
- data/lib/karafka/instrumentation/notifications.rb +6 -3
- data/lib/karafka/instrumentation/vendors/datadog/logger_listener.rb +2 -2
- data/lib/karafka/pro/instrumentation/performance_tracker.rb +85 -0
- data/lib/karafka/pro/loader.rb +3 -2
- data/lib/karafka/pro/processing/coordinator.rb +12 -6
- data/lib/karafka/pro/processing/jobs_queue.rb +109 -0
- data/lib/karafka/pro/processing/schedulers/base.rb +127 -0
- data/lib/karafka/pro/processing/schedulers/default.rb +109 -0
- data/lib/karafka/pro/processing/strategies/aj/lrj_mom_vp.rb +1 -1
- data/lib/karafka/pro/processing/strategies/default.rb +3 -1
- data/lib/karafka/pro/processing/strategies/lrj/default.rb +10 -1
- data/lib/karafka/pro/processing/strategies/lrj/mom.rb +1 -1
- data/lib/karafka/pro/processing/strategies/vp/default.rb +9 -5
- data/lib/karafka/processing/coordinator.rb +13 -7
- data/lib/karafka/processing/executor.rb +27 -3
- data/lib/karafka/processing/executors_buffer.rb +3 -3
- 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 +45 -17
- data/lib/karafka/processing/schedulers/default.rb +41 -0
- data/lib/karafka/processing/strategies/base.rb +13 -4
- data/lib/karafka/processing/strategies/default.rb +17 -5
- data/lib/karafka/processing/worker.rb +4 -1
- data/lib/karafka/routing/builder.rb +32 -17
- data/lib/karafka/routing/proxy.rb +4 -3
- data/lib/karafka/routing/subscription_group.rb +11 -6
- data/lib/karafka/routing/topics.rb +1 -1
- data/lib/karafka/runner.rb +1 -1
- data/lib/karafka/setup/config.rb +5 -1
- data/lib/karafka/version.rb +1 -1
- data/lib/karafka.rb +0 -1
- data.tar.gz.sig +0 -0
- metadata +8 -5
- metadata.gz.sig +0 -0
- data/lib/karafka/pro/performance_tracker.rb +0 -84
- data/lib/karafka/pro/processing/scheduler.rb +0 -75
- data/lib/karafka/processing/scheduler.rb +0 -22
@@ -11,6 +11,15 @@ module Karafka
|
|
11
11
|
#
|
12
12
|
# @note Executors are not removed after partition is revoked. They are not that big and will
|
13
13
|
# be re-used in case of a re-claim
|
14
|
+
#
|
15
|
+
# @note Since given consumer can run various operations, executor manages that and its
|
16
|
+
# lifecycle. There are following types of operations with appropriate before/after, etc:
|
17
|
+
#
|
18
|
+
# - consume - primary operation related to running user consumption code
|
19
|
+
# - idle - cleanup job that runs on idle runs where no messages would be passed to the end
|
20
|
+
# user. This is used for complex flows with filters, etc
|
21
|
+
# - revoked - runs after the partition was revoked
|
22
|
+
# - shutdown - runs when process is going to shutdown
|
14
23
|
class Executor
|
15
24
|
extend Forwardable
|
16
25
|
|
@@ -39,11 +48,11 @@ module Karafka
|
|
39
48
|
end
|
40
49
|
|
41
50
|
# Allows us to prepare the consumer in the listener thread prior to the job being send to
|
42
|
-
#
|
51
|
+
# be scheduled. It also allows to run some code that is time sensitive and cannot wait in the
|
43
52
|
# queue as it could cause starvation.
|
44
53
|
#
|
45
54
|
# @param messages [Array<Karafka::Messages::Message>]
|
46
|
-
def
|
55
|
+
def before_schedule_consume(messages)
|
47
56
|
# Recreate consumer with each batch if persistence is not enabled
|
48
57
|
# We reload the consumers with each batch instead of relying on some external signals
|
49
58
|
# when needed for consistency. That way devs may have it on or off and not in this
|
@@ -60,7 +69,7 @@ module Karafka
|
|
60
69
|
Time.now
|
61
70
|
)
|
62
71
|
|
63
|
-
consumer.
|
72
|
+
consumer.on_before_schedule_consume
|
64
73
|
end
|
65
74
|
|
66
75
|
# Runs setup and warm-up code in the worker prior to running the consumption
|
@@ -79,6 +88,11 @@ module Karafka
|
|
79
88
|
consumer.on_after_consume
|
80
89
|
end
|
81
90
|
|
91
|
+
# Runs the code needed before idle work is scheduled
|
92
|
+
def before_schedule_idle
|
93
|
+
consumer.on_before_schedule_idle
|
94
|
+
end
|
95
|
+
|
82
96
|
# Runs consumer idle operations
|
83
97
|
# This may include house-keeping or other state management changes that can occur but that
|
84
98
|
# not mean there are any new messages available for the end user to process
|
@@ -96,6 +110,11 @@ module Karafka
|
|
96
110
|
consumer.on_idle
|
97
111
|
end
|
98
112
|
|
113
|
+
# Runs code needed before revoked job is scheduled
|
114
|
+
def before_schedule_revoked
|
115
|
+
consumer.on_before_schedule_revoked if @consumer
|
116
|
+
end
|
117
|
+
|
99
118
|
# Runs the controller `#revoked` method that should be triggered when a given consumer is
|
100
119
|
# no longer needed due to partitions reassignment.
|
101
120
|
#
|
@@ -112,6 +131,11 @@ module Karafka
|
|
112
131
|
consumer.on_revoked if @consumer
|
113
132
|
end
|
114
133
|
|
134
|
+
# Runs code needed before shutdown job is scheduled
|
135
|
+
def before_schedule_shutdown
|
136
|
+
consumer.on_before_schedule_shutdown if @consumer
|
137
|
+
end
|
138
|
+
|
115
139
|
# Runs the controller `#shutdown` method that should be triggered when a given consumer is
|
116
140
|
# no longer needed as we're closing the process.
|
117
141
|
#
|
@@ -54,9 +54,9 @@ module Karafka
|
|
54
54
|
# @yieldparam [Integer] partition number
|
55
55
|
# @yieldparam [Executor] given executor
|
56
56
|
def each
|
57
|
-
@buffer.
|
58
|
-
partitions.
|
59
|
-
executors.
|
57
|
+
@buffer.each_value do |partitions|
|
58
|
+
partitions.each_value do |executors|
|
59
|
+
executors.each_value do |executor|
|
60
60
|
yield(executor)
|
61
61
|
end
|
62
62
|
end
|
@@ -20,11 +20,14 @@ module Karafka
|
|
20
20
|
# All jobs are blocking by default and they can release the lock when blocking operations
|
21
21
|
# are done (if needed)
|
22
22
|
@non_blocking = false
|
23
|
+
@status = :pending
|
23
24
|
end
|
24
25
|
|
25
|
-
# When redefined can run any code prior to the job being
|
26
|
+
# When redefined can run any code prior to the job being scheduled
|
26
27
|
# @note This will run in the listener thread and not in the worker
|
27
|
-
def
|
28
|
+
def before_schedule
|
29
|
+
raise NotImplementedError, 'Please implement in a subclass'
|
30
|
+
end
|
28
31
|
|
29
32
|
# When redefined can run any code that should run before executing the proper code
|
30
33
|
def before_call; end
|
@@ -49,6 +52,20 @@ module Karafka
|
|
49
52
|
def non_blocking?
|
50
53
|
@non_blocking
|
51
54
|
end
|
55
|
+
|
56
|
+
# @return [Boolean] was this job finished.
|
57
|
+
def finished?
|
58
|
+
@status == :finished
|
59
|
+
end
|
60
|
+
|
61
|
+
# Marks the job as finished. Used by the worker to indicate, that this job is done.
|
62
|
+
#
|
63
|
+
# @note Since the scheduler knows exactly when it schedules jobs and when it keeps them
|
64
|
+
# pending, we do not need advanced state tracking and the only information from the
|
65
|
+
# "outside" is whether it was finished or not after it was scheduled for execution.
|
66
|
+
def finish!
|
67
|
+
@status = :finished
|
68
|
+
end
|
52
69
|
end
|
53
70
|
end
|
54
71
|
end
|
@@ -20,9 +20,9 @@ module Karafka
|
|
20
20
|
end
|
21
21
|
|
22
22
|
# Runs all the preparation code on the executor that needs to happen before the job is
|
23
|
-
#
|
24
|
-
def
|
25
|
-
executor.
|
23
|
+
# scheduled.
|
24
|
+
def before_schedule
|
25
|
+
executor.before_schedule_consume(@messages)
|
26
26
|
end
|
27
27
|
|
28
28
|
# Runs the before consumption preparations on the executor
|
@@ -9,6 +9,9 @@ module Karafka
|
|
9
9
|
# on this queue, that's why internally we keep track of processing per group.
|
10
10
|
#
|
11
11
|
# We work with the assumption, that partitions data is evenly distributed.
|
12
|
+
#
|
13
|
+
# @note This job queue also keeps track / understands number of busy workers. This is because
|
14
|
+
# we use a single workers poll that can have granular scheduling.
|
12
15
|
class JobsQueue
|
13
16
|
# @return [Karafka::Processing::JobsQueue]
|
14
17
|
def initialize
|
@@ -20,23 +23,29 @@ module Karafka
|
|
20
23
|
# scheduled by Ruby hundreds of thousands of times per group.
|
21
24
|
# We cannot use a single semaphore as it could potentially block in listeners that should
|
22
25
|
# process with their data and also could unlock when a given group needs to remain locked
|
23
|
-
@semaphores =
|
24
|
-
|
25
|
-
# versions we use our custom queue wrapper
|
26
|
-
h.compute_if_absent(k) { RUBY_VERSION < '3.2' ? TimedQueue.new : Queue.new }
|
27
|
-
end
|
28
|
-
|
26
|
+
@semaphores = {}
|
27
|
+
@concurrency = Karafka::App.config.concurrency
|
29
28
|
@tick_interval = ::Karafka::App.config.internal.tick_interval
|
30
29
|
@in_processing = Hash.new { |h, k| h[k] = [] }
|
30
|
+
@statistics = { busy: 0, enqueued: 0 }
|
31
31
|
|
32
32
|
@mutex = Mutex.new
|
33
33
|
end
|
34
34
|
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
38
|
-
|
39
|
-
|
35
|
+
# Registers given subscription group id in the queue. It is needed so we do not dynamically
|
36
|
+
# create semaphore, hence avoiding potential race conditions
|
37
|
+
#
|
38
|
+
# @param group_id [String]
|
39
|
+
def register(group_id)
|
40
|
+
# Ruby prior to 3.2 did not have queue with a timeout on `#pop`, that is why for those
|
41
|
+
@mutex.synchronize do
|
42
|
+
# versions we use our custom queue wrapper
|
43
|
+
#
|
44
|
+
# Initializes this semaphore from the mutex, so it is never auto-created
|
45
|
+
# Since we always schedule a job before waiting using semaphores, there won't be any
|
46
|
+
# concurrency problems
|
47
|
+
@semaphores[group_id] = RUBY_VERSION < '3.2' ? TimedQueue.new : Queue.new
|
48
|
+
end
|
40
49
|
end
|
41
50
|
|
42
51
|
# Adds the job to the internal main queue, scheduling it for execution in a worker and marks
|
@@ -55,6 +64,16 @@ module Karafka
|
|
55
64
|
|
56
65
|
group << job
|
57
66
|
|
67
|
+
# Assume that moving to queue means being picked up immediately not to create stats
|
68
|
+
# race conditions because of pop overhead. If there are workers available, we assume
|
69
|
+
# work is going to be handled as we never reject enqueued jobs
|
70
|
+
if @statistics[:busy] < @concurrency
|
71
|
+
@statistics[:busy] += 1
|
72
|
+
else
|
73
|
+
# If system is fully loaded, it means this job is indeed enqueued
|
74
|
+
@statistics[:enqueued] += 1
|
75
|
+
end
|
76
|
+
|
58
77
|
@queue << job
|
59
78
|
end
|
60
79
|
end
|
@@ -71,7 +90,7 @@ module Karafka
|
|
71
90
|
# @param group_id [String] id of the group we want to unlock for one tick
|
72
91
|
# @note This does not release the wait lock. It just causes a conditions recheck
|
73
92
|
def tick(group_id)
|
74
|
-
@semaphores
|
93
|
+
@semaphores.fetch(group_id) << true
|
75
94
|
end
|
76
95
|
|
77
96
|
# Marks a given job from a given group as completed. When there are no more jobs from a given
|
@@ -80,7 +99,16 @@ module Karafka
|
|
80
99
|
# @param [Jobs::Base] job that was completed
|
81
100
|
def complete(job)
|
82
101
|
@mutex.synchronize do
|
102
|
+
# We finish one job and if there is another, we pick it up
|
103
|
+
if @statistics[:enqueued].positive?
|
104
|
+
@statistics[:enqueued] -= 1
|
105
|
+
# If no more enqueued jobs, we will be just less busy
|
106
|
+
else
|
107
|
+
@statistics[:busy] -= 1
|
108
|
+
end
|
109
|
+
|
83
110
|
@in_processing[job.group_id].delete(job)
|
111
|
+
|
84
112
|
tick(job.group_id)
|
85
113
|
end
|
86
114
|
end
|
@@ -132,7 +160,7 @@ module Karafka
|
|
132
160
|
while wait?(group_id)
|
133
161
|
yield if block_given?
|
134
162
|
|
135
|
-
@semaphores
|
163
|
+
@semaphores.fetch(group_id).pop(timeout: @tick_interval / 1_000.0)
|
136
164
|
end
|
137
165
|
end
|
138
166
|
|
@@ -141,10 +169,10 @@ module Karafka
|
|
141
169
|
#
|
142
170
|
# @return [Hash] hash with basic usage statistics of this queue.
|
143
171
|
def statistics
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
172
|
+
# Ensures there are no race conditions when returning this data
|
173
|
+
@mutex.synchronize do
|
174
|
+
@statistics.dup.freeze
|
175
|
+
end
|
148
176
|
end
|
149
177
|
|
150
178
|
private
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Karafka
|
4
|
+
module Processing
|
5
|
+
# Namespace for Karafka OSS schedulers
|
6
|
+
module Schedulers
|
7
|
+
# FIFO scheduler for messages coming from various topics and partitions
|
8
|
+
class Default
|
9
|
+
# @param queue [Karafka::Processing::JobsQueue] queue where we want to put the jobs
|
10
|
+
def initialize(queue)
|
11
|
+
@queue = queue
|
12
|
+
end
|
13
|
+
|
14
|
+
# Schedules jobs in the fifo order
|
15
|
+
#
|
16
|
+
# @param jobs_array [Array<Karafka::Processing::Jobs::Base>] jobs we want to schedule
|
17
|
+
def on_schedule_consumption(jobs_array)
|
18
|
+
jobs_array.each do |job|
|
19
|
+
@queue << job
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Both revocation and shutdown jobs can also run in fifo by default
|
24
|
+
alias on_schedule_revocation on_schedule_consumption
|
25
|
+
alias on_schedule_shutdown on_schedule_consumption
|
26
|
+
|
27
|
+
# This scheduler does not have anything to manage as it is a pass through and has no state
|
28
|
+
def on_manage
|
29
|
+
nil
|
30
|
+
end
|
31
|
+
|
32
|
+
# This scheduler does not need to be cleared because it is stateless
|
33
|
+
#
|
34
|
+
# @param _group_id [String] Subscription group id
|
35
|
+
def on_clear(_group_id)
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -11,10 +11,19 @@ module Karafka
|
|
11
11
|
module Strategies
|
12
12
|
# Base strategy that should be included in each strategy, just to ensure the API
|
13
13
|
module Base
|
14
|
-
#
|
15
|
-
|
16
|
-
|
17
|
-
|
14
|
+
# Defines all the before schedule handlers for appropriate actions
|
15
|
+
%i[
|
16
|
+
consume
|
17
|
+
idle
|
18
|
+
revoked
|
19
|
+
shutdown
|
20
|
+
].each do |action|
|
21
|
+
class_eval <<~RUBY, __FILE__, __LINE__ + 1
|
22
|
+
def handle_before_schedule_#{action}
|
23
|
+
# What should happen before scheduling this work
|
24
|
+
raise NotImplementedError, 'Implement in a subclass'
|
25
|
+
end
|
26
|
+
RUBY
|
18
27
|
end
|
19
28
|
|
20
29
|
# What should happen before we kick in the processing
|
@@ -13,6 +13,23 @@ module Karafka
|
|
13
13
|
# Apply strategy for a non-feature based flow
|
14
14
|
FEATURES = %i[].freeze
|
15
15
|
|
16
|
+
# By default on all "before schedule" we just run instrumentation, nothing more
|
17
|
+
%i[
|
18
|
+
consume
|
19
|
+
idle
|
20
|
+
revoked
|
21
|
+
shutdown
|
22
|
+
].each do |action|
|
23
|
+
class_eval <<~RUBY, __FILE__, __LINE__ + 1
|
24
|
+
# No actions needed for the standard flow here
|
25
|
+
def handle_before_schedule_#{action}
|
26
|
+
Karafka.monitor.instrument('consumer.before_schedule_#{action}', caller: self)
|
27
|
+
|
28
|
+
nil
|
29
|
+
end
|
30
|
+
RUBY
|
31
|
+
end
|
32
|
+
|
16
33
|
# Marks message as consumed in an async way.
|
17
34
|
#
|
18
35
|
# @param message [Messages::Message] last successfully processed message.
|
@@ -76,11 +93,6 @@ module Karafka
|
|
76
93
|
commit_offsets(async: false)
|
77
94
|
end
|
78
95
|
|
79
|
-
# No actions needed for the standard flow here
|
80
|
-
def handle_before_enqueue
|
81
|
-
nil
|
82
|
-
end
|
83
|
-
|
84
96
|
# Increment number of attempts
|
85
97
|
def handle_before_consume
|
86
98
|
coordinator.pause_tracker.increment
|
@@ -83,7 +83,10 @@ module Karafka
|
|
83
83
|
)
|
84
84
|
ensure
|
85
85
|
# job can be nil when the queue is being closed
|
86
|
-
|
86
|
+
if job
|
87
|
+
@jobs_queue.complete(job)
|
88
|
+
job.finish!
|
89
|
+
end
|
87
90
|
|
88
91
|
# Always publish info, that we completed all the work despite its result
|
89
92
|
Karafka.monitor.instrument('worker.completed', instrument_details)
|
@@ -3,20 +3,25 @@
|
|
3
3
|
module Karafka
|
4
4
|
module Routing
|
5
5
|
# Builder used as a DSL layer for building consumers and telling them which topics to consume
|
6
|
+
#
|
7
|
+
# @note We lock the access just in case this is used in patterns. The locks here do not have
|
8
|
+
# any impact on routing usage unless being expanded, so no race conditions risks.
|
9
|
+
#
|
6
10
|
# @example Build a simple (most common) route
|
7
11
|
# consumers do
|
8
12
|
# topic :new_videos do
|
9
13
|
# consumer NewVideosConsumer
|
10
14
|
# end
|
11
15
|
# end
|
12
|
-
class Builder <
|
16
|
+
class Builder < Array
|
13
17
|
# Empty default per-topic config
|
14
18
|
EMPTY_DEFAULTS = ->(_) {}.freeze
|
15
19
|
|
16
20
|
private_constant :EMPTY_DEFAULTS
|
17
21
|
|
18
22
|
def initialize
|
19
|
-
@
|
23
|
+
@mutex = Mutex.new
|
24
|
+
@draws = []
|
20
25
|
@defaults = EMPTY_DEFAULTS
|
21
26
|
super
|
22
27
|
end
|
@@ -34,21 +39,23 @@ module Karafka
|
|
34
39
|
# end
|
35
40
|
# end
|
36
41
|
def draw(&block)
|
37
|
-
@
|
42
|
+
@mutex.synchronize do
|
43
|
+
@draws << block
|
38
44
|
|
39
|
-
|
45
|
+
instance_eval(&block)
|
40
46
|
|
41
|
-
|
42
|
-
|
43
|
-
|
47
|
+
each do |consumer_group|
|
48
|
+
# Validate consumer group settings
|
49
|
+
Contracts::ConsumerGroup.new.validate!(consumer_group.to_h)
|
44
50
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
51
|
+
# and then its topics settings
|
52
|
+
consumer_group.topics.each do |topic|
|
53
|
+
Contracts::Topic.new.validate!(topic.to_h)
|
54
|
+
end
|
49
55
|
|
50
|
-
|
51
|
-
|
56
|
+
# Initialize subscription groups after all the routing is done
|
57
|
+
consumer_group.subscription_groups
|
58
|
+
end
|
52
59
|
end
|
53
60
|
end
|
54
61
|
|
@@ -61,9 +68,11 @@ module Karafka
|
|
61
68
|
|
62
69
|
# Clears the builder and the draws memory
|
63
70
|
def clear
|
64
|
-
@
|
65
|
-
|
66
|
-
|
71
|
+
@mutex.synchronize do
|
72
|
+
@defaults = EMPTY_DEFAULTS
|
73
|
+
@draws.clear
|
74
|
+
super
|
75
|
+
end
|
67
76
|
end
|
68
77
|
|
69
78
|
# @param block [Proc] block with per-topic evaluated defaults
|
@@ -71,7 +80,13 @@ module Karafka
|
|
71
80
|
def defaults(&block)
|
72
81
|
return @defaults unless block
|
73
82
|
|
74
|
-
@
|
83
|
+
if @mutex.owned?
|
84
|
+
@defaults = block
|
85
|
+
else
|
86
|
+
@mutex.synchronize do
|
87
|
+
@defaults = block
|
88
|
+
end
|
89
|
+
end
|
75
90
|
end
|
76
91
|
|
77
92
|
private
|
@@ -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
|
@@ -10,19 +10,24 @@ module Karafka
|
|
10
10
|
class SubscriptionGroup
|
11
11
|
attr_reader :id, :name, :topics, :kafka, :consumer_group
|
12
12
|
|
13
|
-
#
|
14
|
-
|
13
|
+
# Lock for generating new ids safely
|
14
|
+
ID_MUTEX = Mutex.new
|
15
15
|
|
16
|
-
private_constant :
|
16
|
+
private_constant :ID_MUTEX
|
17
17
|
|
18
18
|
class << self
|
19
19
|
# Generates new subscription group id that will be used in case of anonymous subscription
|
20
20
|
# groups
|
21
21
|
# @return [String] hex(6) compatible reproducible id
|
22
22
|
def id
|
23
|
-
|
24
|
-
|
25
|
-
|
23
|
+
ID_MUTEX.synchronize do
|
24
|
+
@group_counter ||= 0
|
25
|
+
@group_counter += 1
|
26
|
+
|
27
|
+
::Digest::MD5.hexdigest(
|
28
|
+
@group_counter.to_s
|
29
|
+
)[0..11]
|
30
|
+
end
|
26
31
|
end
|
27
32
|
end
|
28
33
|
|
@@ -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
@@ -8,7 +8,7 @@ module Karafka
|
|
8
8
|
def call
|
9
9
|
# Despite possibility of having several independent listeners, we aim to have one queue for
|
10
10
|
# jobs across and one workers poll for that
|
11
|
-
jobs_queue =
|
11
|
+
jobs_queue = App.config.internal.processing.jobs_queue_class.new
|
12
12
|
|
13
13
|
workers = Processing::WorkersBatch.new(jobs_queue)
|
14
14
|
listeners = Connection::ListenersBatch.new(jobs_queue)
|
data/lib/karafka/setup/config.rb
CHANGED
@@ -209,8 +209,9 @@ module Karafka
|
|
209
209
|
end
|
210
210
|
|
211
211
|
setting :processing do
|
212
|
+
setting :jobs_queue_class, default: Processing::JobsQueue
|
212
213
|
# option scheduler [Object] scheduler we will be using
|
213
|
-
setting :
|
214
|
+
setting :scheduler_class, default: Processing::Schedulers::Default
|
214
215
|
# option jobs_builder [Object] jobs builder we want to use
|
215
216
|
setting :jobs_builder, default: Processing::JobsBuilder.new
|
216
217
|
# option coordinator [Class] work coordinator we want to user for processing coordination
|
@@ -277,6 +278,9 @@ module Karafka
|
|
277
278
|
# are also configured
|
278
279
|
Pro::Loader.post_setup_all(config) if Karafka.pro?
|
279
280
|
|
281
|
+
# Subscribe the assignments tracker so we can always query all current assignments
|
282
|
+
config.monitor.subscribe(Instrumentation::AssignmentsTracker.instance)
|
283
|
+
|
280
284
|
Karafka::App.initialized!
|
281
285
|
end
|
282
286
|
|
data/lib/karafka/version.rb
CHANGED
data/lib/karafka.rb
CHANGED
data.tar.gz.sig
CHANGED
Binary file
|