karafka 2.2.12 → 2.2.14
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/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
|