karafka 2.2.6 → 2.2.8.beta1

Sign up to get free protection for your applications and to get access to all the features.
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
  )