karafka 2.2.6 → 2.2.8.beta1

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.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.github/workflows/ci.yml +3 -0
  4. data/CHANGELOG.md +18 -0
  5. data/Gemfile.lock +5 -7
  6. data/bin/karafka +2 -3
  7. data/config/locales/errors.yml +7 -4
  8. data/config/locales/pro_errors.yml +3 -0
  9. data/docker-compose.yml +3 -1
  10. data/karafka.gemspec +1 -2
  11. data/lib/karafka/base_consumer.rb +8 -1
  12. data/lib/karafka/cli/base.rb +45 -34
  13. data/lib/karafka/cli/console.rb +5 -4
  14. data/lib/karafka/cli/help.rb +24 -0
  15. data/lib/karafka/cli/info.rb +2 -2
  16. data/lib/karafka/cli/install.rb +4 -4
  17. data/lib/karafka/cli/server.rb +68 -33
  18. data/lib/karafka/cli/topics.rb +1 -1
  19. data/lib/karafka/cli.rb +23 -19
  20. data/lib/karafka/connection/client.rb +9 -4
  21. data/lib/karafka/connection/listener.rb +3 -3
  22. data/lib/karafka/connection/rebalance_manager.rb +36 -21
  23. data/lib/karafka/contracts/config.rb +2 -0
  24. data/lib/karafka/errors.rb +3 -0
  25. data/lib/karafka/instrumentation/callbacks/rebalance.rb +64 -0
  26. data/lib/karafka/instrumentation/notifications.rb +5 -1
  27. data/lib/karafka/instrumentation/vendors/appsignal/base.rb +30 -0
  28. data/lib/karafka/instrumentation/vendors/appsignal/client.rb +122 -0
  29. data/lib/karafka/instrumentation/vendors/appsignal/dashboard.json +222 -0
  30. data/lib/karafka/instrumentation/vendors/appsignal/errors_listener.rb +30 -0
  31. data/lib/karafka/instrumentation/vendors/appsignal/metrics_listener.rb +331 -0
  32. data/lib/karafka/instrumentation/vendors/datadog/metrics_listener.rb +2 -2
  33. data/lib/karafka/patches/rdkafka/bindings.rb +22 -39
  34. data/lib/karafka/patches/rdkafka/opaque.rb +36 -0
  35. data/lib/karafka/pro/loader.rb +2 -2
  36. data/lib/karafka/pro/processing/coordinator.rb +6 -7
  37. data/lib/karafka/pro/processing/filters/delayer.rb +1 -1
  38. data/lib/karafka/pro/processing/filters/inline_insights_delayer.rb +78 -0
  39. data/lib/karafka/pro/processing/strategies/vp/default.rb +20 -0
  40. data/lib/karafka/pro/routing/features/inline_insights/config.rb +32 -0
  41. data/lib/karafka/pro/routing/features/inline_insights/contracts/topic.rb +41 -0
  42. data/lib/karafka/pro/routing/features/inline_insights/topic.rb +52 -0
  43. data/lib/karafka/pro/routing/features/inline_insights.rb +26 -0
  44. data/lib/karafka/processing/executor.rb +7 -0
  45. data/lib/karafka/processing/expansions_selector.rb +22 -0
  46. data/lib/karafka/processing/inline_insights/consumer.rb +41 -0
  47. data/lib/karafka/processing/inline_insights/listener.rb +19 -0
  48. data/lib/karafka/processing/inline_insights/tracker.rb +128 -0
  49. data/lib/karafka/railtie.rb +14 -7
  50. data/lib/karafka/routing/features/base.rb +36 -1
  51. data/lib/karafka/routing/features/inline_insights/config.rb +15 -0
  52. data/lib/karafka/routing/features/inline_insights/contracts/topic.rb +27 -0
  53. data/lib/karafka/routing/features/inline_insights/topic.rb +31 -0
  54. data/lib/karafka/routing/features/inline_insights.rb +40 -0
  55. data/lib/karafka/routing/subscription_group.rb +6 -2
  56. data/lib/karafka/setup/attributes_map.rb +1 -0
  57. data/lib/karafka/setup/config.rb +11 -2
  58. data/lib/karafka/version.rb +1 -1
  59. data/lib/karafka.rb +1 -1
  60. data.tar.gz.sig +0 -0
  61. metadata +26 -19
  62. metadata.gz.sig +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 36fe50a9b0a758b9b916ca668c862085629bf09bcf16f7c0e8a340a9b7333abb
4
- data.tar.gz: 61d3f10df4e1545a1a4e0d8190eb6ee2a7b751636bb347cf2703a74149fc710c
3
+ metadata.gz: facd28537bbd9b1f5a7e6956c82b704a97efafdfdcea5ed9959991f129ba2ed4
4
+ data.tar.gz: 4b6ca5058a07fadf7c95fa96eb08ff7820b44d4bafc43ebdaf0a7fe16cb35fd2
5
5
  SHA512:
6
- metadata.gz: f12fb91f2e8e4e7dba766fbf32c79b734f5cd9f6fa63a66f80863a819dfd6d442024a97a4095bea84ef87bb0cb645ff431ba6d2f04f46d72864c377d61fc76a6
7
- data.tar.gz: 4235c1944c98f0bd6359b82b7eab68a69812d70665ab0436c9f67cc5011e4c8edfa2c194a6d65744a4d82f97710beca5ddb871b8671febf61e5c9f591a746bee
6
+ metadata.gz: fd8cda16faa8d1267b934d2ccc189e6981c21be8cc4fed60042776a6370c93481b99981117d2572a52ada12ea9268877e339a5007284aa2413135ace5a078241
7
+ data.tar.gz: e765bb3a3c6de52bd6dbd12a7268d18c03cb1454068dff19ebc49d1c5a7850058b8b0853e744c6a16f07bc7f3883bf8681df19a10c0babc70defca1dbdee2b19
checksums.yaml.gz.sig CHANGED
Binary file
@@ -71,6 +71,7 @@ jobs:
71
71
  fail-fast: false
72
72
  matrix:
73
73
  ruby:
74
+ - '3.3.0-preview2'
74
75
  - '3.2'
75
76
  # We run it against the oldest and the newest of a given major to make sure, that there
76
77
  # are no syntax-sugars that we would use that were introduced down the road
@@ -115,6 +116,7 @@ jobs:
115
116
  fail-fast: false
116
117
  matrix:
117
118
  ruby:
119
+ - '3.3.0-preview2'
118
120
  - '3.2'
119
121
  - '3.1'
120
122
  - '3.0'
@@ -166,6 +168,7 @@ jobs:
166
168
  fail-fast: false
167
169
  matrix:
168
170
  ruby:
171
+ - '3.3.0-preview2'
169
172
  - '3.2'
170
173
  - '3.1'
171
174
  - '3.0'
data/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # Karafka framework changelog
2
2
 
3
+ ## 2.2.8 (Unreleased)
4
+ - **[Feature]** Introduce Appsignal integration for errors and metrics tracking.
5
+ - [Improvement] Expose `#synchronize` for VPs to allow for locks when cross-VP consumers work is needed.
6
+ - [Improvement] Provide `#collapse_until!` direct consumer API to allow for collapsed virtual partitions consumer operations together with the Filtering API for advanced use-cases.
7
+ - [Refactor] Reorganize how rebalance events are propagated from `librdkafka` to Karafka. Replace `connection.client.rebalance_callback` with `rebalance.partitions_assigned` and `rebalance.partitions_revoked`. Introduce two extra events: `rebalance.partitions_assign` and `rebalance.partitions_revoke` to handle pre-rebalance future work.
8
+ - [Refactor] Remove `thor` as a CLI layer and rely on Ruby `OptParser`
9
+
10
+ ### Upgrade notes
11
+
12
+ 1. Unless you were using `connection.client.rebalance_callback` which was considered private, nothing.
13
+ 2. None of the CLI commands should change but `thor` has been removed so please report if you find any bugs.
14
+
15
+ ## 2.2.7 (2023-10-07)
16
+ - **[Feature]** Introduce Inline Insights to both OSS and Pro. Inline Insights allow you to get the Kafka insights/metrics from the consumer instance and use them to alter the processing flow. In Pro, there's an extra filter flow allowing to ensure, that the insights exist during consumption.
17
+ - [Enhancement] Make sure, that subscription groups ids are unique by including their consumer group id in them similar to how topics ids are handled (not a breaking change).
18
+ - [Enhancement] Expose `#attempt` method on a consumer to directly indicate number of attempt of processing given data.
19
+ - [Enhancement] Support Rails 7.1.
20
+
3
21
  ## 2.2.6 (2023-09-26)
4
22
  - [Enhancement] Retry `Karafka::Admin#read_watermark_offsets` fetching upon `not_leader_for_partition` that can occur mostly on newly created topics in KRaft and after crashes during leader selection.
5
23
 
data/Gemfile.lock CHANGED
@@ -1,9 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- karafka (2.2.6)
4
+ karafka (2.2.8.beta1)
5
5
  karafka-core (>= 2.2.2, < 2.3.0)
6
- thor (>= 0.20)
7
6
  waterdrop (>= 2.6.6, < 3.0.0)
8
7
  zeitwerk (~> 2.3)
9
8
 
@@ -37,9 +36,9 @@ GEM
37
36
  ffi (~> 1.15)
38
37
  mini_portile2 (~> 2.6)
39
38
  rake (> 12)
40
- karafka-web (0.7.4)
39
+ karafka-web (0.7.6)
41
40
  erubi (~> 1.4)
42
- karafka (>= 2.2.3, < 3.0.0)
41
+ karafka (>= 2.2.6, < 3.0.0)
43
42
  karafka-core (>= 2.2.2, < 3.0.0)
44
43
  roda (~> 3.68, >= 3.69)
45
44
  tilt (~> 2.0)
@@ -68,14 +67,13 @@ GEM
68
67
  simplecov_json_formatter (~> 0.1)
69
68
  simplecov-html (0.12.3)
70
69
  simplecov_json_formatter (0.1.4)
71
- thor (1.2.2)
72
- tilt (2.2.0)
70
+ tilt (2.3.0)
73
71
  tzinfo (2.0.6)
74
72
  concurrent-ruby (~> 1.0)
75
73
  waterdrop (2.6.7)
76
74
  karafka-core (>= 2.1.1, < 3.0.0)
77
75
  zeitwerk (~> 2.3)
78
- zeitwerk (2.6.11)
76
+ zeitwerk (2.6.12)
79
77
 
80
78
  PLATFORMS
81
79
  x86_64-linux
data/bin/karafka CHANGED
@@ -6,6 +6,5 @@ require 'karafka'
6
6
  # our bin/karafka cli
7
7
  ENV['KARAFKA_CLI'] = 'true'
8
8
 
9
- Karafka::Cli::Base.load
10
- Karafka::Cli.prepare
11
- Karafka::Cli.start
9
+ ::Karafka::Cli::Base.load
10
+ ::Karafka::Cli.start
@@ -16,9 +16,11 @@ en:
16
16
  max_wait_time_format: needs to be an integer bigger than 0
17
17
  kafka_format: needs to be a filled hash
18
18
  internal.processing.jobs_builder_format: cannot be nil
19
- internal.processing.scheduler: cannot be nil
20
- internal.processing.coordinator_class: cannot be nil
21
- internal.processing.partitioner_class: cannot be nil
19
+ internal.processing.scheduler_format: cannot be nil
20
+ internal.processing.coordinator_class_format: cannot be nil
21
+ internal.processing.partitioner_class_format: cannot be nil
22
+ internal.processing.strategy_selector_format: cannot be nil
23
+ internal.processing.expansions_selector_format: cannot be nil
22
24
  internal.active_job.dispatcher: cannot be nil
23
25
  internal.active_job.job_options_contract: cannot be nil
24
26
  internal.active_job.consumer_class: cannot be nil
@@ -59,8 +61,9 @@ en:
59
61
  initial_offset_format: needs to be either earliest or latest
60
62
  subscription_group_name_format: must be a non-empty string
61
63
  manual_offset_management.active_format: needs to be either true or false
62
- consumer_active_job_missing: ActiveJob needs to be available
63
64
  manual_offset_management_must_be_enabled: cannot be disabled for ActiveJob topics
65
+ inline_insights.active_format: needs to be either true or false
66
+ consumer_active_job_missing: ActiveJob needs to be available
64
67
  dead_letter_queue.max_retries_format: needs to be equal or bigger than 0
65
68
  dead_letter_queue.topic_format: 'needs to be a string with a Kafka accepted format'
66
69
  dead_letter_queue.active_format: needs to be either true or false
@@ -31,6 +31,9 @@ en:
31
31
  patterns.active_format: 'needs to be boolean'
32
32
  patterns.type_format: 'needs to be :matcher, :discovered or :regular'
33
33
 
34
+ inline_insights.active_format: 'needs to be boolean'
35
+ inline_insights.required_format: 'needs to be boolean'
36
+
34
37
  consumer_group:
35
38
  patterns_format: must be an array with hashes
36
39
  patterns_missing: needs to be present
data/docker-compose.yml CHANGED
@@ -3,7 +3,7 @@ version: '2'
3
3
  services:
4
4
  kafka:
5
5
  container_name: kafka
6
- image: confluentinc/cp-kafka:7.5.0
6
+ image: confluentinc/cp-kafka:7.5.1
7
7
 
8
8
  ports:
9
9
  - 9092:9092
@@ -21,3 +21,5 @@ services:
21
21
  KAFKA_CONTROLLER_QUORUM_VOTERS: 1@127.0.0.1:9093
22
22
  ALLOW_PLAINTEXT_LISTENER: 'yes'
23
23
  KAFKA_AUTO_CREATE_TOPICS_ENABLE: 'true'
24
+ KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
25
+ KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
data/karafka.gemspec CHANGED
@@ -22,7 +22,6 @@ Gem::Specification.new do |spec|
22
22
  DESC
23
23
 
24
24
  spec.add_dependency 'karafka-core', '>= 2.2.2', '< 2.3.0'
25
- spec.add_dependency 'thor', '>= 0.20'
26
25
  spec.add_dependency 'waterdrop', '>= 2.6.6', '< 3.0.0'
27
26
  spec.add_dependency 'zeitwerk', '~> 2.3'
28
27
 
@@ -38,7 +37,7 @@ Gem::Specification.new do |spec|
38
37
  spec.metadata = {
39
38
  'funding_uri' => 'https://karafka.io/#become-pro',
40
39
  'homepage_uri' => 'https://karafka.io',
41
- 'changelog_uri' => 'https://github.com/karafka/karafka/blob/master/CHANGELOG.md',
40
+ 'changelog_uri' => 'https://karafka.io/docs/Changelog-Karafka',
42
41
  'bug_tracker_uri' => 'https://github.com/karafka/karafka/issues',
43
42
  'source_code_uri' => 'https://github.com/karafka/karafka',
44
43
  'documentation_uri' => 'https://karafka.io/docs',
@@ -73,6 +73,7 @@ module Karafka
73
73
  # @private
74
74
  #
75
75
  # @return [Boolean] true if there was no exception, otherwise false.
76
+ #
76
77
  # @note We keep the seek offset tracking, and use it to compensate for async offset flushing
77
78
  # that may not yet kick in when error occurs. That way we pause always on the last processed
78
79
  # message.
@@ -252,7 +253,13 @@ module Karafka
252
253
  # different flow after there is an error, for example for resources cleanup, small manual
253
254
  # backoff or different instrumentation tracking.
254
255
  def retrying?
255
- coordinator.pause_tracker.attempt > 1
256
+ attempt > 1
257
+ end
258
+
259
+ # @return [Integer] attempt of processing given batch. 1 if this is the first attempt or higher
260
+ # in case it is a retry
261
+ def attempt
262
+ coordinator.pause_tracker.attempt
256
263
  end
257
264
 
258
265
  # Pauses the processing from the last offset to retry on given message
@@ -1,31 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Karafka
4
- class Cli < Thor
4
+ class Cli
5
5
  # Base class for all the command that we want to define
6
- # This base class provides a nicer interface to Thor and allows to easier separate single
7
- # independent commands
8
- # In order to define a new command you need to:
9
- # - specify its desc
10
- # - implement call method
11
- #
12
- # @example Create a dummy command
13
- # class Dummy < Base
14
- # self.desc = 'Dummy command'
15
- #
16
- # def call
17
- # puts 'I'm doing nothing!
18
- # end
19
- # end
6
+ # This base class provides an interface to easier separate single independent commands
20
7
  class Base
21
- include Thor::Shell
8
+ # @return [Hash] given command cli options
9
+ attr_reader :options
22
10
 
23
- # We can use it to call other cli methods via this object
24
- attr_reader :cli
25
-
26
- # @param cli [Karafka::Cli] current Karafka Cli instance
27
- def initialize(cli)
28
- @cli = cli
11
+ # Creates new CLI command instance
12
+ def initialize
13
+ # Parses the given command CLI options
14
+ @options = self.class.parse_options
29
15
  end
30
16
 
31
17
  # This method should implement proper cli action
@@ -64,26 +50,46 @@ module Karafka
64
50
 
65
51
  # Allows to set description of a given cli command
66
52
  # @param desc [String] Description of a given cli command
67
- def desc(desc)
53
+ def desc(desc = nil)
68
54
  @desc ||= desc
69
55
  end
70
56
 
71
- # This method will bind a given Cli command into Karafka Cli
72
- # This method is a wrapper to way Thor defines its commands
73
- # @param cli_class [Karafka::Cli] Karafka cli_class
74
- def bind_to(cli_class)
75
- cli_class.desc name, @desc
57
+ # Allows to set aliases for a given cli command
58
+ # @param args [Array] list of aliases that we can use to run given cli command
59
+ def aliases(*args)
60
+ @aliases ||= []
61
+ @aliases << args.map(&:to_s)
62
+ end
63
+
64
+ # Parses the CLI options
65
+ # @return [Hash] hash with parsed values
66
+ def parse_options
67
+ options = {}
76
68
 
77
- (@options || []).each { |option| cli_class.option(*option) }
69
+ OptionParser.new do |opts|
70
+ (@options || []).each do |option|
71
+ # Creates aliases for backwards compatibility
72
+ names = option[3].flat_map { |name| [name, name.tr('_', '-')] }
73
+ names.map! { |name| "#{name} value1,value2,valueN" } if option[2] == Array
74
+ names.uniq!
78
75
 
79
- context = self
76
+ opts.on(
77
+ *[names, option[2], option[1]].flatten
78
+ ) { |value| options[option[0]] = value }
79
+ end
80
+ end.parse!
80
81
 
81
- cli_class.send :define_method, name do |*args|
82
- context.new(self).call(*args)
83
- end
82
+ options
84
83
  end
85
84
 
86
- private
85
+ # @return [Array<Class>] available commands
86
+ def commands
87
+ ObjectSpace
88
+ .each_object(Class)
89
+ .select { |klass| klass.superclass == Karafka::Cli::Base }
90
+ .reject { |klass| klass.to_s.end_with?('::Base') }
91
+ .sort_by(&:name)
92
+ end
87
93
 
88
94
  # @return [String] downcased current class name that we use to define name for
89
95
  # given Cli command
@@ -92,6 +98,11 @@ module Karafka
92
98
  def name
93
99
  to_s.split('::').last.downcase
94
100
  end
101
+
102
+ # @return [Array<String>] names and aliases for command matching
103
+ def names
104
+ ((@aliases || []) << name).flatten.map(&:to_s)
105
+ end
95
106
  end
96
107
  end
97
108
  end
@@ -2,11 +2,12 @@
2
2
 
3
3
  module Karafka
4
4
  # Karafka framework Cli
5
- class Cli < Thor
5
+ class Cli
6
6
  # Console Karafka Cli action
7
7
  class Console < Base
8
- desc 'Start the Karafka console (short-cut alias: "c")'
9
- option aliases: 'c'
8
+ desc 'Starts the Karafka console (short-cut alias: "c")'
9
+
10
+ aliases :c
10
11
 
11
12
  class << self
12
13
  # @return [String] Console executing command for non-Rails setup
@@ -25,7 +26,7 @@ module Karafka
25
26
 
26
27
  # Start the Karafka console
27
28
  def call
28
- cli.info
29
+ Info.new.call
29
30
 
30
31
  command = ::Karafka.rails? ? self.class.rails_console : self.class.console
31
32
 
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Karafka
4
+ # Karafka framework Cli
5
+ class Cli
6
+ # Prints info with list of commands available
7
+ class Help < Base
8
+ desc 'Describes available commands'
9
+
10
+ # Print available commands
11
+ def call
12
+ # Find the longest command for alignment purposes
13
+ max_command_length = self.class.commands.map(&:name).map(&:size).max
14
+
15
+ puts 'Karafka commands:'
16
+
17
+ # Print each command formatted with its description
18
+ self.class.commands.each do |command|
19
+ puts " #{command.name.ljust(max_command_length)} # #{command.desc}"
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -2,10 +2,10 @@
2
2
 
3
3
  module Karafka
4
4
  # Karafka framework Cli
5
- class Cli < Thor
5
+ class Cli
6
6
  # Info Karafka Cli action
7
7
  class Info < Base
8
- desc 'Print configuration details and other options of your application'
8
+ desc 'Prints configuration details and other options of your application'
9
9
 
10
10
  # Nice karafka banner
11
11
  BANNER = <<~BANNER
@@ -4,12 +4,12 @@ require 'erb'
4
4
 
5
5
  module Karafka
6
6
  # Karafka framework Cli
7
- class Cli < Thor
7
+ class Cli
8
8
  # Install Karafka Cli action
9
9
  class Install < Base
10
10
  include Helpers::Colorize
11
11
 
12
- desc 'Install all required things for Karafka application in current directory'
12
+ desc 'Installs all required things for Karafka application in current directory'
13
13
 
14
14
  # Directories created by default
15
15
  INSTALL_DIRS = %w[
@@ -26,9 +26,9 @@ module Karafka
26
26
  'example_consumer.rb.erb' => 'app/consumers/example_consumer.rb'
27
27
  }.freeze
28
28
 
29
- # @param args [Array] all the things that Thor CLI accepts
30
- def initialize(*args)
29
+ def initialize
31
30
  super
31
+
32
32
  dependencies = Bundler::LockfileParser.new(
33
33
  Bundler.read_file(
34
34
  Bundler.default_lockfile
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Karafka
4
4
  # Karafka framework Cli
5
- class Cli < Thor
5
+ class Cli
6
6
  # Server Karafka Cli action
7
7
  class Server < Base
8
8
  include Helpers::Colorize
@@ -12,36 +12,75 @@ module Karafka
12
12
 
13
13
  private_constant :SUPPORTED_TYPES
14
14
 
15
- desc 'Start the Karafka server (short-cut alias: "s")'
16
-
17
- option aliases: 's'
18
-
19
- # Thor does not work well with many aliases combinations, hence we remap the aliases
20
- # by ourselves in the code
21
- option :consumer_groups, type: :array, default: [], aliases: :g
22
- option :subscription_groups, type: :array, default: []
23
- option :topics, type: :array, default: []
24
-
25
- %i[
26
- include
27
- exclude
28
- ].each do |action|
29
- SUPPORTED_TYPES.each do |type|
30
- option(
31
- "#{action}_#{type}",
32
- type: :array,
33
- default: []
34
- )
35
- end
36
- end
15
+ desc 'Starts the Karafka server (short-cut alias: "s")'
16
+
17
+ aliases :s
18
+
19
+ option(
20
+ :consumer_groups,
21
+ 'Runs server only with specified consumer groups',
22
+ Array,
23
+ %w[
24
+ -g
25
+ --consumer_groups
26
+ --include_consumer_groups
27
+ ]
28
+ )
29
+
30
+ option(
31
+ :subscription_groups,
32
+ 'Runs server only with specified subscription groups',
33
+ Array,
34
+ %w[
35
+ --subscription_groups
36
+ --include_subscription_groups
37
+ ]
38
+ )
39
+
40
+ option(
41
+ :topics,
42
+ 'Runs server only with specified topics',
43
+ Array,
44
+ %w[
45
+ --topics
46
+ --include_topics
47
+ ]
48
+ )
49
+
50
+ option(
51
+ :exclude_consumer_groups,
52
+ 'Runs server without specified consumer groups',
53
+ Array,
54
+ %w[
55
+ --exclude_consumer_groups
56
+ ]
57
+ )
58
+
59
+ option(
60
+ :exclude_subscription_groups,
61
+ 'Runs server without specified subscription groups',
62
+ Array,
63
+ %w[
64
+ --exclude_subscription_groups
65
+ ]
66
+ )
67
+
68
+ option(
69
+ :exclude_topics,
70
+ 'Runs server without specified topics',
71
+ Array,
72
+ %w[
73
+ --exclude_topics
74
+ ]
75
+ )
37
76
 
38
77
  # Start the Karafka server
39
78
  def call
40
79
  # Print our banner and info in the dev mode
41
80
  print_marketing_info if Karafka::App.env.development?
42
81
 
43
- register_inclusions(cli)
44
- register_exclusions(cli)
82
+ register_inclusions
83
+ register_exclusions
45
84
 
46
85
  Karafka::Server.run
47
86
  end
@@ -49,26 +88,22 @@ module Karafka
49
88
  private
50
89
 
51
90
  # Registers things we want to include (if defined)
52
- # @param cli [Karafka::Cli] Thor cli handler
53
- def register_inclusions(cli)
91
+ def register_inclusions
54
92
  activities = ::Karafka::App.config.internal.routing.activity_manager
55
93
 
56
94
  SUPPORTED_TYPES.each do |type|
57
- v1 = cli.options[type] || []
58
- v2 = cli.options[:"include_#{type}"] || []
59
- names = v1 + v2
95
+ names = options[type] || []
60
96
 
61
97
  names.each { |name| activities.include(type, name) }
62
98
  end
63
99
  end
64
100
 
65
101
  # Registers things we want to exclude (if defined)
66
- # @param cli [Karafka::Cli] Thor cli handler
67
- def register_exclusions(cli)
102
+ def register_exclusions
68
103
  activities = ::Karafka::App.config.internal.routing.activity_manager
69
104
 
70
105
  activities.class::SUPPORTED_TYPES.each do |type|
71
- names = cli.options[:"exclude_#{type}"] || []
106
+ names = options[:"exclude_#{type}"] || []
72
107
 
73
108
  names.each { |name| activities.exclude(type, name) }
74
109
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Karafka
4
- class Cli < Thor
4
+ class Cli
5
5
  # CLI actions related to Kafka cluster topics management
6
6
  class Topics < Base
7
7
  include Helpers::Colorize
data/lib/karafka/cli.rb CHANGED
@@ -5,31 +5,35 @@ module Karafka
5
5
  #
6
6
  # If you want to add/modify command that belongs to CLI, please review all commands
7
7
  # available in cli/ directory inside Karafka source code.
8
- #
9
- # @note Whole Cli is built using Thor
10
- # @see https://github.com/erikhuda/thor
11
- class Cli < Thor
12
- package_name 'Karafka'
13
-
8
+ class Cli
14
9
  class << self
15
- # Loads all Cli commands into Thor framework.
16
- # This method should be executed before we run Karafka::Cli.start, otherwise we won't
17
- # have any Cli commands available.
18
- def prepare
19
- cli_commands.each do |action|
20
- action.bind_to(self)
10
+ # Starts the CLI
11
+ def start
12
+ # Command we want to run, like install, server, etc
13
+ command_name = ARGV[0]
14
+ # Action for action-based commands like topics migrate
15
+ action = ARGV[1].to_s.start_with?('-') ? false : ARGV[1]
16
+
17
+ command = commands.find { |cmd| cmd.names.include?(command_name) }
18
+
19
+ if command
20
+ # Only actionable commands require command as an argument
21
+ args = action ? [action] : []
22
+
23
+ command.new.call(*args)
24
+ else
25
+ raise(
26
+ Karafka::Errors::UnrecognizedCommandError,
27
+ "Unrecognized command \"#{command_name}\""
28
+ )
21
29
  end
22
30
  end
23
31
 
24
32
  private
25
33
 
26
- # @return [Array<Class>] Array with Cli action classes that can be used as commands
27
- def cli_commands
28
- constants
29
- .map! { |object| const_get(object) }
30
- .keep_if do |object|
31
- object.instance_of?(Class) && (object < Cli::Base)
32
- end
34
+ # @return [Array<Class>] command classes
35
+ def commands
36
+ Base.commands
33
37
  end
34
38
  end
35
39
  end
@@ -43,7 +43,11 @@ module Karafka
43
43
  @closed = false
44
44
  @subscription_group = subscription_group
45
45
  @buffer = RawMessagesBuffer.new
46
- @rebalance_manager = RebalanceManager.new
46
+ @rebalance_manager = RebalanceManager.new(@subscription_group.id)
47
+ @rebalance_callback = Instrumentation::Callbacks::Rebalance.new(
48
+ @subscription_group.id,
49
+ @subscription_group.consumer_group.id
50
+ )
47
51
  @kafka = build_consumer
48
52
  # There are few operations that can happen in parallel from the listener threads as well
49
53
  # as from the workers. They are not fully thread-safe because they may be composed out of
@@ -498,7 +502,8 @@ module Karafka
498
502
  def build_consumer
499
503
  ::Rdkafka::Config.logger = ::Karafka::App.config.logger
500
504
  config = ::Rdkafka::Config.new(@subscription_group.kafka)
501
- config.consumer_rebalance_listener = @rebalance_manager
505
+ config.consumer_rebalance_listener = @rebalance_callback
506
+
502
507
  consumer = config.consumer
503
508
  @name = consumer.name
504
509
 
@@ -507,7 +512,7 @@ module Karafka
507
512
  @subscription_group.id,
508
513
  Instrumentation::Callbacks::Statistics.new(
509
514
  @subscription_group.id,
510
- @subscription_group.consumer_group_id,
515
+ @subscription_group.consumer_group.id,
511
516
  @name
512
517
  )
513
518
  )
@@ -517,7 +522,7 @@ module Karafka
517
522
  @subscription_group.id,
518
523
  Instrumentation::Callbacks::Error.new(
519
524
  @subscription_group.id,
520
- @subscription_group.consumer_group_id,
525
+ @subscription_group.consumer_group.id,
521
526
  @name
522
527
  )
523
528
  )