karafka 2.0.21 → 2.0.23
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 +6 -0
- data/.ruby-version +1 -1
- data/CHANGELOG.md +21 -0
- data/Gemfile.lock +7 -8
- data/README.md +1 -1
- data/bin/integrations +2 -2
- data/bin/rspecs +2 -0
- data/config/errors.yml +5 -2
- data/karafka.gemspec +2 -3
- data/lib/karafka/admin.rb +84 -4
- data/lib/karafka/app.rb +12 -2
- data/lib/karafka/base_consumer.rb +8 -11
- data/lib/karafka/cli/info.rb +2 -1
- data/lib/karafka/cli/server.rb +7 -6
- data/lib/karafka/connection/client.rb +4 -4
- data/lib/karafka/contracts/server_cli_options.rb +60 -3
- data/lib/karafka/contracts/topic.rb +1 -1
- data/lib/karafka/licenser.rb +53 -50
- data/lib/karafka/pro/loader.rb +1 -3
- data/lib/karafka/pro/processing/strategies/aj_dlq_mom.rb +2 -2
- data/lib/karafka/pro/processing/strategies/aj_lrj_mom_vp.rb +2 -2
- data/lib/karafka/pro/processing/strategies/aj_mom_vp.rb +1 -1
- data/lib/karafka/pro/processing/strategies/default.rb +31 -1
- data/lib/karafka/pro/processing/strategies/dlq.rb +4 -2
- data/lib/karafka/pro/processing/strategies/dlq_lrj.rb +3 -1
- data/lib/karafka/pro/processing/strategies/dlq_lrj_mom.rb +1 -1
- data/lib/karafka/pro/processing/strategies/dlq_mom.rb +2 -2
- data/lib/karafka/pro/processing/strategies/lrj.rb +4 -2
- data/lib/karafka/pro/processing/strategies/lrj_mom.rb +2 -2
- data/lib/karafka/pro/processing/strategies/mom.rb +1 -1
- data/lib/karafka/processing/coordinator.rb +15 -0
- data/lib/karafka/processing/jobs_queue.rb +1 -1
- data/lib/karafka/processing/strategies/aj_dlq_mom.rb +2 -2
- data/lib/karafka/processing/strategies/base.rb +5 -0
- data/lib/karafka/processing/strategies/default.rb +26 -1
- data/lib/karafka/processing/strategies/dlq.rb +4 -2
- data/lib/karafka/processing/strategies/dlq_mom.rb +2 -2
- data/lib/karafka/processing/strategies/mom.rb +1 -1
- data/lib/karafka/railtie.rb +3 -0
- data/lib/karafka/routing/builder.rb +1 -1
- data/lib/karafka/routing/consumer_group.rb +6 -3
- data/lib/karafka/routing/subscription_group.rb +11 -2
- data/lib/karafka/routing/topic.rb +8 -0
- data/lib/karafka/routing/topics.rb +8 -0
- data/lib/karafka/server.rb +11 -10
- data/lib/karafka/setup/config.rb +15 -11
- data/lib/karafka/version.rb +1 -1
- data/lib/karafka.rb +9 -0
- data.tar.gz.sig +0 -0
- metadata +7 -22
- metadata.gz.sig +0 -0
- data/lib/karafka/instrumentation.rb +0 -21
@@ -42,7 +42,7 @@ module Karafka
|
|
42
42
|
# Do NOT commit offsets, they are comitted after each job in the AJ consumer.
|
43
43
|
coordinator.pause_tracker.reset
|
44
44
|
elsif coordinator.pause_tracker.attempt <= topic.dead_letter_queue.max_retries
|
45
|
-
pause(coordinator.seek_offset)
|
45
|
+
pause(coordinator.seek_offset, nil, false)
|
46
46
|
else
|
47
47
|
coordinator.pause_tracker.reset
|
48
48
|
skippable_message = find_skippable_message
|
@@ -51,7 +51,7 @@ module Karafka
|
|
51
51
|
# since AJ consumer commits the offset after each job, we also know that the
|
52
52
|
# previous job was successful
|
53
53
|
mark_as_consumed(skippable_message)
|
54
|
-
pause(coordinator.seek_offset)
|
54
|
+
pause(coordinator.seek_offset, nil, false)
|
55
55
|
end
|
56
56
|
end
|
57
57
|
end
|
@@ -33,7 +33,7 @@ module Karafka
|
|
33
33
|
# No actions needed for the standard flow here
|
34
34
|
def handle_before_enqueue
|
35
35
|
coordinator.on_enqueued do
|
36
|
-
pause(coordinator.seek_offset, Lrj::MAX_PAUSE_TIME)
|
36
|
+
pause(coordinator.seek_offset, Lrj::MAX_PAUSE_TIME, false)
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
@@ -51,7 +51,7 @@ module Karafka
|
|
51
51
|
# If processing failed, we need to pause
|
52
52
|
# For long running job this will overwrite the default never-ending pause and will
|
53
53
|
# cause the processing to keep going after the error backoff
|
54
|
-
pause(coordinator.seek_offset)
|
54
|
+
pause(coordinator.seek_offset, nil, false)
|
55
55
|
end
|
56
56
|
end
|
57
57
|
end
|
@@ -22,6 +22,7 @@ module Karafka
|
|
22
22
|
# Nothing. Just standard, automatic flow
|
23
23
|
module Default
|
24
24
|
include Base
|
25
|
+
include ::Karafka::Processing::Strategies::Default
|
25
26
|
|
26
27
|
# Apply strategy for a non-feature based flow
|
27
28
|
FEATURES = %i[].freeze
|
@@ -39,6 +40,31 @@ module Karafka
|
|
39
40
|
end
|
40
41
|
end
|
41
42
|
|
43
|
+
# Run the user consumption code
|
44
|
+
def handle_consume
|
45
|
+
# We should not run the work at all on a partition that was revoked
|
46
|
+
# This can happen primarily when an LRJ job gets to the internal worker queue and
|
47
|
+
# this partition is revoked prior processing.
|
48
|
+
unless revoked?
|
49
|
+
Karafka.monitor.instrument('consumer.consumed', caller: self) do
|
50
|
+
consume
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Mark job as successful
|
55
|
+
coordinator.consumption(self).success!
|
56
|
+
rescue StandardError => e
|
57
|
+
# If failed, mark as failed
|
58
|
+
coordinator.consumption(self).failure!(e)
|
59
|
+
|
60
|
+
# Re-raise so reported in the consumer
|
61
|
+
raise e
|
62
|
+
ensure
|
63
|
+
# We need to decrease number of jobs that this coordinator coordinates as it has
|
64
|
+
# finished
|
65
|
+
coordinator.decrement
|
66
|
+
end
|
67
|
+
|
42
68
|
# Standard flow without any features
|
43
69
|
def handle_after_consume
|
44
70
|
coordinator.on_finished do |last_group_message|
|
@@ -47,9 +73,13 @@ module Karafka
|
|
47
73
|
if coordinator.success?
|
48
74
|
coordinator.pause_tracker.reset
|
49
75
|
|
76
|
+
# Do not mark last message if pause happened. This prevents a scenario where pause
|
77
|
+
# is overridden upon rebalance by marking
|
78
|
+
return if coordinator.manual_pause?
|
79
|
+
|
50
80
|
mark_as_consumed(last_group_message)
|
51
81
|
else
|
52
|
-
pause(coordinator.seek_offset)
|
82
|
+
pause(coordinator.seek_offset, nil, false)
|
53
83
|
end
|
54
84
|
end
|
55
85
|
end
|
@@ -32,9 +32,11 @@ module Karafka
|
|
32
32
|
if coordinator.success?
|
33
33
|
coordinator.pause_tracker.reset
|
34
34
|
|
35
|
+
return if coordinator.manual_pause?
|
36
|
+
|
35
37
|
mark_as_consumed(messages.last)
|
36
38
|
elsif coordinator.pause_tracker.attempt <= topic.dead_letter_queue.max_retries
|
37
|
-
pause(coordinator.seek_offset)
|
39
|
+
pause(coordinator.seek_offset, nil, false)
|
38
40
|
# If we've reached number of retries that we could, we need to skip the first message
|
39
41
|
# that was not marked as consumed, pause and continue, while also moving this message
|
40
42
|
# to the dead topic
|
@@ -44,7 +46,7 @@ module Karafka
|
|
44
46
|
skippable_message = find_skippable_message
|
45
47
|
dispatch_to_dlq(skippable_message) if dispatch_to_dlq?
|
46
48
|
mark_as_consumed(skippable_message)
|
47
|
-
pause(coordinator.seek_offset)
|
49
|
+
pause(coordinator.seek_offset, nil, false)
|
48
50
|
end
|
49
51
|
end
|
50
52
|
end
|
@@ -34,12 +34,14 @@ module Karafka
|
|
34
34
|
if coordinator.success?
|
35
35
|
coordinator.pause_tracker.reset
|
36
36
|
|
37
|
+
return if coordinator.manual_pause?
|
38
|
+
|
37
39
|
mark_as_consumed(last_group_message) unless revoked?
|
38
40
|
seek(coordinator.seek_offset) unless revoked?
|
39
41
|
|
40
42
|
resume
|
41
43
|
elsif coordinator.pause_tracker.attempt <= topic.dead_letter_queue.max_retries
|
42
|
-
pause(coordinator.seek_offset)
|
44
|
+
pause(coordinator.seek_offset, nil, false)
|
43
45
|
else
|
44
46
|
coordinator.pause_tracker.reset
|
45
47
|
|
@@ -35,7 +35,7 @@ module Karafka
|
|
35
35
|
if coordinator.success?
|
36
36
|
coordinator.pause_tracker.reset
|
37
37
|
elsif coordinator.pause_tracker.attempt <= topic.dead_letter_queue.max_retries
|
38
|
-
pause(coordinator.seek_offset)
|
38
|
+
pause(coordinator.seek_offset, nil, false)
|
39
39
|
# If we've reached number of retries that we could, we need to skip the first message
|
40
40
|
# that was not marked as consumed, pause and continue, while also moving this message
|
41
41
|
# to the dead topic.
|
@@ -51,7 +51,7 @@ module Karafka
|
|
51
51
|
dispatch_to_dlq(skippable_message)
|
52
52
|
end
|
53
53
|
|
54
|
-
pause(coordinator.seek_offset)
|
54
|
+
pause(coordinator.seek_offset, nil, false)
|
55
55
|
end
|
56
56
|
end
|
57
57
|
end
|
@@ -37,7 +37,7 @@ module Karafka
|
|
37
37
|
#
|
38
38
|
# For VP it applies the same way and since VP cannot be used with MOM we should not
|
39
39
|
# have any edge cases here.
|
40
|
-
pause(coordinator.seek_offset, MAX_PAUSE_TIME)
|
40
|
+
pause(coordinator.seek_offset, MAX_PAUSE_TIME, false)
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
@@ -47,6 +47,8 @@ module Karafka
|
|
47
47
|
if coordinator.success?
|
48
48
|
coordinator.pause_tracker.reset
|
49
49
|
|
50
|
+
return if coordinator.manual_pause?
|
51
|
+
|
50
52
|
mark_as_consumed(last_group_message) unless revoked?
|
51
53
|
seek(coordinator.seek_offset) unless revoked?
|
52
54
|
|
@@ -55,7 +57,7 @@ module Karafka
|
|
55
57
|
# If processing failed, we need to pause
|
56
58
|
# For long running job this will overwrite the default never-ending pause and will
|
57
59
|
# cause the processing to keep going after the error backoff
|
58
|
-
pause(coordinator.seek_offset)
|
60
|
+
pause(coordinator.seek_offset, nil, false)
|
59
61
|
end
|
60
62
|
end
|
61
63
|
end
|
@@ -36,7 +36,7 @@ module Karafka
|
|
36
36
|
#
|
37
37
|
# For VP it applies the same way and since VP cannot be used with MOM we should not
|
38
38
|
# have any edge cases here.
|
39
|
-
pause(coordinator.seek_offset, Lrj::MAX_PAUSE_TIME)
|
39
|
+
pause(coordinator.seek_offset, Lrj::MAX_PAUSE_TIME, false)
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
@@ -50,7 +50,7 @@ module Karafka
|
|
50
50
|
|
51
51
|
resume
|
52
52
|
else
|
53
|
-
pause(coordinator.seek_offset)
|
53
|
+
pause(coordinator.seek_offset, false)
|
54
54
|
end
|
55
55
|
end
|
56
56
|
end
|
@@ -21,6 +21,7 @@ module Karafka
|
|
21
21
|
@revoked = false
|
22
22
|
@consumptions = {}
|
23
23
|
@running_jobs = 0
|
24
|
+
@manual_pause = false
|
24
25
|
@mutex = Mutex.new
|
25
26
|
end
|
26
27
|
|
@@ -34,6 +35,9 @@ module Karafka
|
|
34
35
|
# consumption results of consumer instances we no longer control
|
35
36
|
@consumptions.clear
|
36
37
|
|
38
|
+
# When starting to run, no pause is expected and no manual pause as well
|
39
|
+
@manual_pause = false
|
40
|
+
|
37
41
|
# We set it on the first encounter and never again, because then the offset setting
|
38
42
|
# should be up to the consumers logic (our or the end user)
|
39
43
|
# Seek offset needs to be always initialized as for case where manual offset management
|
@@ -98,6 +102,17 @@ module Karafka
|
|
98
102
|
def revoked?
|
99
103
|
@revoked
|
100
104
|
end
|
105
|
+
|
106
|
+
# Store in the coordinator info, that this pause was done manually by the end user and not
|
107
|
+
# by the system itself
|
108
|
+
def manual_pause
|
109
|
+
@mutex.synchronize { @manual_pause = true }
|
110
|
+
end
|
111
|
+
|
112
|
+
# @return [Boolean] are we in a pause that was initiated by the user
|
113
|
+
def manual_pause?
|
114
|
+
@pause_tracker.paused? && @manual_pause
|
115
|
+
end
|
101
116
|
end
|
102
117
|
end
|
103
118
|
end
|
@@ -26,7 +26,7 @@ module Karafka
|
|
26
26
|
# Do NOT commit offsets, they are comitted after each job in the AJ consumer.
|
27
27
|
coordinator.pause_tracker.reset
|
28
28
|
elsif coordinator.pause_tracker.attempt <= topic.dead_letter_queue.max_retries
|
29
|
-
pause(coordinator.seek_offset)
|
29
|
+
pause(coordinator.seek_offset, nil, false)
|
30
30
|
else
|
31
31
|
coordinator.pause_tracker.reset
|
32
32
|
skippable_message = find_skippable_message
|
@@ -35,7 +35,7 @@ module Karafka
|
|
35
35
|
# since AJ consumer commits the offset after each job, we also know that the
|
36
36
|
# previous job was successful
|
37
37
|
mark_as_consumed(skippable_message)
|
38
|
-
pause(coordinator.seek_offset)
|
38
|
+
pause(coordinator.seek_offset, nil, false)
|
39
39
|
end
|
40
40
|
end
|
41
41
|
end
|
@@ -22,6 +22,11 @@ module Karafka
|
|
22
22
|
raise NotImplementedError, 'Implement in a subclass'
|
23
23
|
end
|
24
24
|
|
25
|
+
# What should happen in the processing
|
26
|
+
def handle_consume
|
27
|
+
raise NotImplementedError, 'Implement in a subclass'
|
28
|
+
end
|
29
|
+
|
25
30
|
# Post-consumption handling
|
26
31
|
def handle_after_consume
|
27
32
|
raise NotImplementedError, 'Implement in a subclass'
|
@@ -23,6 +23,25 @@ module Karafka
|
|
23
23
|
coordinator.pause_tracker.increment
|
24
24
|
end
|
25
25
|
|
26
|
+
# Run the user consumption code
|
27
|
+
def handle_consume
|
28
|
+
Karafka.monitor.instrument('consumer.consumed', caller: self) do
|
29
|
+
consume
|
30
|
+
end
|
31
|
+
|
32
|
+
# Mark job as successful
|
33
|
+
coordinator.consumption(self).success!
|
34
|
+
rescue StandardError => e
|
35
|
+
# If failed, mark as failed
|
36
|
+
coordinator.consumption(self).failure!(e)
|
37
|
+
|
38
|
+
# Re-raise so reported in the consumer
|
39
|
+
raise e
|
40
|
+
ensure
|
41
|
+
# We need to decrease number of jobs that this coordinator coordinates as it has finished
|
42
|
+
coordinator.decrement
|
43
|
+
end
|
44
|
+
|
26
45
|
# Standard flow marks work as consumed and moves on if everything went ok.
|
27
46
|
# If there was a processing error, we will pause and continue from the next message
|
28
47
|
# (next that is +1 from the last one that was successfully marked as consumed)
|
@@ -32,9 +51,15 @@ module Karafka
|
|
32
51
|
if coordinator.success?
|
33
52
|
coordinator.pause_tracker.reset
|
34
53
|
|
54
|
+
# We should not move the offset automatically when the partition was paused
|
55
|
+
# If we would not do this upon a revocation during the pause time, a different process
|
56
|
+
# would pick not from the place where we paused but from the offset that would be
|
57
|
+
# automatically committed here
|
58
|
+
return if coordinator.manual_pause?
|
59
|
+
|
35
60
|
mark_as_consumed(messages.last)
|
36
61
|
else
|
37
|
-
pause(coordinator.seek_offset)
|
62
|
+
pause(coordinator.seek_offset, nil, false)
|
38
63
|
end
|
39
64
|
end
|
40
65
|
|
@@ -22,9 +22,11 @@ module Karafka
|
|
22
22
|
if coordinator.success?
|
23
23
|
coordinator.pause_tracker.reset
|
24
24
|
|
25
|
+
return if coordinator.manual_pause?
|
26
|
+
|
25
27
|
mark_as_consumed(messages.last)
|
26
28
|
elsif coordinator.pause_tracker.attempt <= topic.dead_letter_queue.max_retries
|
27
|
-
pause(coordinator.seek_offset)
|
29
|
+
pause(coordinator.seek_offset, nil, false)
|
28
30
|
# If we've reached number of retries that we could, we need to skip the first message
|
29
31
|
# that was not marked as consumed, pause and continue, while also moving this message
|
30
32
|
# to the dead topic
|
@@ -43,7 +45,7 @@ module Karafka
|
|
43
45
|
return if revoked?
|
44
46
|
|
45
47
|
# We pause to backoff once just in case.
|
46
|
-
pause(coordinator.seek_offset)
|
48
|
+
pause(coordinator.seek_offset, nil, false)
|
47
49
|
end
|
48
50
|
end
|
49
51
|
|
@@ -21,7 +21,7 @@ module Karafka
|
|
21
21
|
if coordinator.success?
|
22
22
|
coordinator.pause_tracker.reset
|
23
23
|
elsif coordinator.pause_tracker.attempt <= topic.dead_letter_queue.max_retries
|
24
|
-
pause(coordinator.seek_offset)
|
24
|
+
pause(coordinator.seek_offset, nil, false)
|
25
25
|
# If we've reached number of retries that we could, we need to skip the first message
|
26
26
|
# that was not marked as consumed, pause and continue, while also moving this message
|
27
27
|
# to the dead topic
|
@@ -33,7 +33,7 @@ module Karafka
|
|
33
33
|
dispatch_to_dlq(skippable_message)
|
34
34
|
|
35
35
|
# We pause to backoff once just in case.
|
36
|
-
pause(coordinator.seek_offset)
|
36
|
+
pause(coordinator.seek_offset, nil, false)
|
37
37
|
end
|
38
38
|
end
|
39
39
|
end
|
data/lib/karafka/railtie.rb
CHANGED
@@ -45,6 +45,9 @@ if rails
|
|
45
45
|
|
46
46
|
next unless Rails.env.development?
|
47
47
|
next unless ENV.key?('KARAFKA_CLI')
|
48
|
+
# If we are already publishing to STDOUT, no need to add it again.
|
49
|
+
# If added again, would print stuff twice
|
50
|
+
next if ActiveSupport::Logger.logger_outputs_to?(Rails.logger, $stdout)
|
48
51
|
|
49
52
|
logger = ActiveSupport::Logger.new($stdout)
|
50
53
|
# Inherit the logger level from Rails, otherwise would always run with the debug level
|
@@ -82,7 +82,7 @@ module Karafka
|
|
82
82
|
# @param block [Proc] further topics definitions
|
83
83
|
def subscription_group(subscription_group_name = SecureRandom.uuid, &block)
|
84
84
|
consumer_group('app') do
|
85
|
-
target.public_send(:subscription_group=, subscription_group_name, &block)
|
85
|
+
target.public_send(:subscription_group=, subscription_group_name.to_s, &block)
|
86
86
|
end
|
87
87
|
end
|
88
88
|
|
@@ -31,7 +31,10 @@ module Karafka
|
|
31
31
|
|
32
32
|
# @return [Boolean] true if this consumer group should be active in our current process
|
33
33
|
def active?
|
34
|
-
Karafka::
|
34
|
+
cgs = Karafka::App.config.internal.routing.active.consumer_groups
|
35
|
+
|
36
|
+
# When empty it means no groups were specified, hence all should be used
|
37
|
+
cgs.empty? || cgs.include?(name)
|
35
38
|
end
|
36
39
|
|
37
40
|
# Builds a topic representation inside of a current consumer group route
|
@@ -50,9 +53,9 @@ module Karafka
|
|
50
53
|
|
51
54
|
# Assigns the current subscription group id based on the defined one and allows for further
|
52
55
|
# topic definition
|
53
|
-
# @param name [String, Symbol]
|
56
|
+
# @param name [String, Symbol] name of the current subscription group
|
54
57
|
# @param block [Proc] block that may include topics definitions
|
55
|
-
def subscription_group=(name, &block)
|
58
|
+
def subscription_group=(name = SecureRandom.uuid, &block)
|
56
59
|
# We cast it here, so the routing supports symbol based but that's anyhow later on
|
57
60
|
# validated as a string
|
58
61
|
@current_subscription_group_id = name
|
@@ -8,7 +8,7 @@ module Karafka
|
|
8
8
|
# @note One subscription group will always belong to one consumer group, but one consumer
|
9
9
|
# group can have multiple subscription groups.
|
10
10
|
class SubscriptionGroup
|
11
|
-
attr_reader :id, :topics, :kafka
|
11
|
+
attr_reader :id, :name, :topics, :kafka
|
12
12
|
|
13
13
|
# @param position [Integer] position of this subscription group in all the subscriptions
|
14
14
|
# groups array. We need to have this value for sake of static group memberships, where
|
@@ -16,7 +16,8 @@ module Karafka
|
|
16
16
|
# @param topics [Karafka::Routing::Topics] all the topics that share the same key settings
|
17
17
|
# @return [SubscriptionGroup] built subscription group
|
18
18
|
def initialize(position, topics)
|
19
|
-
@
|
19
|
+
@name = topics.first.subscription_group
|
20
|
+
@id = "#{@name}_#{position}"
|
20
21
|
@position = position
|
21
22
|
@topics = topics
|
22
23
|
@kafka = build_kafka
|
@@ -38,6 +39,14 @@ module Karafka
|
|
38
39
|
@topics.first.max_wait_time
|
39
40
|
end
|
40
41
|
|
42
|
+
# @return [Boolean] is this subscription group one of active once
|
43
|
+
def active?
|
44
|
+
sgs = Karafka::App.config.internal.routing.active.subscription_groups
|
45
|
+
|
46
|
+
# When empty it means no groups were specified, hence all should be used
|
47
|
+
sgs.empty? || sgs.include?(name)
|
48
|
+
end
|
49
|
+
|
41
50
|
private
|
42
51
|
|
43
52
|
# @return [Hash] kafka settings are a bit special. They are exactly the same for all of the
|
@@ -75,6 +75,14 @@ module Karafka
|
|
75
75
|
consumer
|
76
76
|
end
|
77
77
|
|
78
|
+
# @return [Boolean] should this topic be in use
|
79
|
+
def active?
|
80
|
+
topics = Karafka::App.config.internal.routing.active.topics
|
81
|
+
|
82
|
+
# When empty it means no topics were specified, hence all should be used
|
83
|
+
topics.empty? || topics.include?(name)
|
84
|
+
end
|
85
|
+
|
78
86
|
# @return [Hash] hash with all the topic attributes
|
79
87
|
# @note This is being used when we validate the consumer_group and its topics
|
80
88
|
def to_h
|
@@ -23,6 +23,14 @@ module Karafka
|
|
23
23
|
@accumulator.each(&block)
|
24
24
|
end
|
25
25
|
|
26
|
+
# Allows us to remove elements from the topics
|
27
|
+
#
|
28
|
+
# Block to decide what to delete
|
29
|
+
# @param block [Proc]
|
30
|
+
def delete_if(&block)
|
31
|
+
@accumulator.delete_if(&block)
|
32
|
+
end
|
33
|
+
|
26
34
|
# Finds topic by its name
|
27
35
|
#
|
28
36
|
# @param topic_name [String] topic name
|
data/lib/karafka/server.rb
CHANGED
@@ -20,11 +20,19 @@ module Karafka
|
|
20
20
|
# Set of workers
|
21
21
|
attr_accessor :workers
|
22
22
|
|
23
|
-
# Writer for list of consumer groups that we want to consume in our current process context
|
24
|
-
attr_writer :consumer_groups
|
25
|
-
|
26
23
|
# Method which runs app
|
27
24
|
def run
|
25
|
+
self.listeners = []
|
26
|
+
self.workers = []
|
27
|
+
|
28
|
+
# We need to validate this prior to running because it may be executed also from the
|
29
|
+
# embedded
|
30
|
+
# We cannot validate this during the start because config needs to be populated and routes
|
31
|
+
# need to be defined.
|
32
|
+
Contracts::ServerCliOptions.new.validate!(
|
33
|
+
Karafka::App.config.internal.routing.active.to_h
|
34
|
+
)
|
35
|
+
|
28
36
|
process.on_sigint { stop }
|
29
37
|
process.on_sigquit { stop }
|
30
38
|
process.on_sigterm { stop }
|
@@ -49,13 +57,6 @@ module Karafka
|
|
49
57
|
raise e
|
50
58
|
end
|
51
59
|
|
52
|
-
# @return [Array<String>] array with names of consumer groups that should be consumed in a
|
53
|
-
# current server context
|
54
|
-
def consumer_groups
|
55
|
-
# If not specified, a server will listen on all the topics
|
56
|
-
@consumer_groups ||= Karafka::App.consumer_groups.map(&:name).freeze
|
57
|
-
end
|
58
|
-
|
59
60
|
# Starts Karafka with a supervision
|
60
61
|
# @note We don't need to sleep because Karafka::Fetcher is locking and waiting to
|
61
62
|
# finish loop (and it won't happen until we explicitly want to stop)
|
data/lib/karafka/setup/config.rb
CHANGED
@@ -107,6 +107,14 @@ module Karafka
|
|
107
107
|
# option subscription_groups_builder [Routing::SubscriptionGroupsBuilder] subscription
|
108
108
|
# group builder
|
109
109
|
setting :subscription_groups_builder, default: Routing::SubscriptionGroupsBuilder.new
|
110
|
+
|
111
|
+
# Internally assigned list of limits on routings active for the current process
|
112
|
+
# This should be overwritten by the CLI command
|
113
|
+
setting :active do
|
114
|
+
setting :consumer_groups, default: [].freeze
|
115
|
+
setting :subscription_groups, default: [].freeze
|
116
|
+
setting :topics, default: [].freeze
|
117
|
+
end
|
110
118
|
end
|
111
119
|
|
112
120
|
setting :processing do
|
@@ -142,16 +150,18 @@ module Karafka
|
|
142
150
|
# Configuring method
|
143
151
|
# @param block [Proc] block we want to execute with the config instance
|
144
152
|
def setup(&block)
|
153
|
+
# Will prepare and verify license if present
|
154
|
+
Licenser.prepare_and_verify(config.license)
|
155
|
+
# Will configure all the pro components
|
156
|
+
# This needs to happen before end user configuration as the end user may overwrite some
|
157
|
+
# of the pro defaults with custom components
|
158
|
+
Pro::Loader.setup(config) if Karafka.pro?
|
159
|
+
|
145
160
|
configure(&block)
|
146
161
|
merge_kafka_defaults!(config)
|
147
162
|
|
148
163
|
Contracts::Config.new.validate!(config.to_h)
|
149
164
|
|
150
|
-
licenser = Licenser.new
|
151
|
-
|
152
|
-
# Tries to load our license gem and if present will try to load the correct license
|
153
|
-
licenser.prepare_and_verify(config.license)
|
154
|
-
|
155
165
|
configure_components
|
156
166
|
|
157
167
|
Karafka::App.initialized!
|
@@ -188,12 +198,6 @@ module Karafka
|
|
188
198
|
producer_config.kafka = AttributesMap.producer(config.kafka.dup)
|
189
199
|
producer_config.logger = config.logger
|
190
200
|
end
|
191
|
-
|
192
|
-
return unless Karafka.pro?
|
193
|
-
|
194
|
-
# Runs the pro loader that includes all the pro components
|
195
|
-
require 'karafka/pro/loader'
|
196
|
-
Pro::Loader.setup(config)
|
197
201
|
end
|
198
202
|
end
|
199
203
|
end
|
data/lib/karafka/version.rb
CHANGED
data/lib/karafka.rb
CHANGED
@@ -100,5 +100,14 @@ loader.eager_load
|
|
100
100
|
# nor included here
|
101
101
|
::Karafka::Routing::Features::Base.load_all
|
102
102
|
|
103
|
+
# We need to detect and require (not setup) Pro components during the gem load, because we need
|
104
|
+
# to make pro components available in case anyone wants to use them as a base to their own
|
105
|
+
# custom components. Otherwise inheritance would not work.
|
106
|
+
Karafka::Licenser.detect do
|
107
|
+
require 'karafka/pro/loader'
|
108
|
+
|
109
|
+
Karafka::Pro::Loader.require_all
|
110
|
+
end
|
111
|
+
|
103
112
|
# Load railtie after everything else is ready so we know we can rely on it.
|
104
113
|
require 'karafka/railtie'
|
data.tar.gz.sig
CHANGED
Binary file
|