karafka 2.1.13 → 2.2.0

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 (60) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +35 -0
  4. data/Gemfile.lock +1 -1
  5. data/config/locales/errors.yml +4 -0
  6. data/config/locales/pro_errors.yml +17 -0
  7. data/lib/karafka/admin.rb +21 -33
  8. data/lib/karafka/connection/client.rb +1 -1
  9. data/lib/karafka/contracts/config.rb +24 -0
  10. data/lib/karafka/pro/contracts/base.rb +23 -0
  11. data/lib/karafka/pro/contracts/server_cli_options.rb +111 -0
  12. data/lib/karafka/pro/loader.rb +4 -1
  13. data/lib/karafka/pro/routing/features/active_job/builder.rb +45 -0
  14. data/lib/karafka/pro/routing/features/active_job.rb +26 -0
  15. data/lib/karafka/pro/routing/features/dead_letter_queue/contracts/topic.rb +53 -0
  16. data/lib/karafka/pro/routing/features/delaying/contracts/topic.rb +41 -0
  17. data/lib/karafka/pro/routing/features/expiring/contracts/topic.rb +41 -0
  18. data/lib/karafka/pro/routing/features/filtering/contracts/topic.rb +44 -0
  19. data/lib/karafka/pro/routing/features/long_running_job/{contract.rb → contracts/topic.rb} +14 -11
  20. data/lib/karafka/pro/routing/features/{filtering/contract.rb → patterns/builder.rb} +13 -16
  21. data/lib/karafka/pro/routing/features/patterns/config.rb +54 -0
  22. data/lib/karafka/pro/routing/features/patterns/consumer_group.rb +68 -0
  23. data/lib/karafka/pro/routing/features/patterns/contracts/consumer_group.rb +62 -0
  24. data/lib/karafka/pro/routing/features/patterns/contracts/pattern.rb +46 -0
  25. data/lib/karafka/pro/routing/features/patterns/contracts/topic.rb +41 -0
  26. data/lib/karafka/pro/routing/features/patterns/detector.rb +68 -0
  27. data/lib/karafka/pro/routing/features/patterns/pattern.rb +81 -0
  28. data/lib/karafka/pro/routing/features/{delaying/contract.rb → patterns/patterns.rb} +11 -14
  29. data/lib/karafka/pro/routing/features/patterns/topic.rb +50 -0
  30. data/lib/karafka/pro/routing/features/patterns/topics.rb +53 -0
  31. data/lib/karafka/pro/routing/features/patterns.rb +33 -0
  32. data/lib/karafka/pro/routing/features/pausing/contracts/topic.rb +51 -0
  33. data/lib/karafka/pro/routing/features/throttling/contracts/topic.rb +44 -0
  34. data/lib/karafka/pro/routing/features/virtual_partitions/contracts/topic.rb +55 -0
  35. data/lib/karafka/routing/consumer_group.rb +1 -1
  36. data/lib/karafka/routing/features/active_job/contracts/topic.rb +44 -0
  37. data/lib/karafka/routing/features/active_job/proxy.rb +14 -0
  38. data/lib/karafka/routing/features/base/expander.rb +8 -2
  39. data/lib/karafka/routing/features/base.rb +4 -2
  40. data/lib/karafka/routing/features/dead_letter_queue/contracts/topic.rb +46 -0
  41. data/lib/karafka/routing/features/declaratives/contracts/topic.rb +33 -0
  42. data/lib/karafka/routing/features/manual_offset_management/contracts/topic.rb +27 -0
  43. data/lib/karafka/routing/router.rb +0 -11
  44. data/lib/karafka/routing/subscription_group.rb +9 -0
  45. data/lib/karafka/routing/topic.rb +5 -0
  46. data/lib/karafka/server.rb +9 -4
  47. data/lib/karafka/setup/config.rb +45 -0
  48. data/lib/karafka/version.rb +1 -1
  49. data.tar.gz.sig +0 -0
  50. metadata +32 -15
  51. metadata.gz.sig +0 -0
  52. data/lib/karafka/pro/routing/features/dead_letter_queue/contract.rb +0 -50
  53. data/lib/karafka/pro/routing/features/expiring/contract.rb +0 -38
  54. data/lib/karafka/pro/routing/features/pausing/contract.rb +0 -48
  55. data/lib/karafka/pro/routing/features/throttling/contract.rb +0 -41
  56. data/lib/karafka/pro/routing/features/virtual_partitions/contract.rb +0 -52
  57. data/lib/karafka/routing/features/active_job/contract.rb +0 -41
  58. data/lib/karafka/routing/features/dead_letter_queue/contract.rb +0 -42
  59. data/lib/karafka/routing/features/declaratives/contract.rb +0 -30
  60. data/lib/karafka/routing/features/manual_offset_management/contract.rb +0 -24
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This Karafka component is a Pro component under a commercial license.
4
+ # This Karafka component is NOT licensed under LGPL.
5
+ #
6
+ # All of the commercial components are present in the lib/karafka/pro directory of this
7
+ # repository and their usage requires commercial license agreement.
8
+ #
9
+ # Karafka has also commercial-friendly license, commercial support and commercial components.
10
+ #
11
+ # By sending a pull request to the pro components, you are agreeing to transfer the copyright of
12
+ # your code to Maciej Mensfeld.
13
+
14
+ module Karafka
15
+ module Pro
16
+ module Routing
17
+ module Features
18
+ class Filtering < Base
19
+ # Namespace for filtering feature contracts
20
+ module Contracts
21
+ # Contract to validate configuration of the filtering feature
22
+ class Topic < Karafka::Contracts::Base
23
+ configure do |config|
24
+ config.error_messages = YAML.safe_load(
25
+ File.read(
26
+ File.join(Karafka.gem_root, 'config', 'locales', 'pro_errors.yml')
27
+ )
28
+ ).fetch('en').fetch('validations').fetch('topic')
29
+ end
30
+
31
+ nested(:filtering) do
32
+ required(:active) { |val| [true, false].include?(val) }
33
+
34
+ required(:factories) do |val|
35
+ val.is_a?(Array) && val.all? { |factory| factory.respond_to?(:call) }
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -16,18 +16,21 @@ module Karafka
16
16
  module Routing
17
17
  module Features
18
18
  class LongRunningJob < Base
19
- # Rules around long-running job settings
20
- class Contract < Contracts::Base
21
- configure do |config|
22
- config.error_messages = YAML.safe_load(
23
- File.read(
24
- File.join(Karafka.gem_root, 'config', 'locales', 'pro_errors.yml')
25
- )
26
- ).fetch('en').fetch('validations').fetch('topic')
27
- end
19
+ # Namespace for LRJ contracts
20
+ module Contracts
21
+ # Rules around long-running job settings
22
+ class Topic < Karafka::Contracts::Base
23
+ configure do |config|
24
+ config.error_messages = YAML.safe_load(
25
+ File.read(
26
+ File.join(Karafka.gem_root, 'config', 'locales', 'pro_errors.yml')
27
+ )
28
+ ).fetch('en').fetch('validations').fetch('topic')
29
+ end
28
30
 
29
- nested(:long_running_job) do
30
- required(:active) { |val| [true, false].include?(val) }
31
+ nested(:long_running_job) do
32
+ required(:active) { |val| [true, false].include?(val) }
33
+ end
31
34
  end
32
35
  end
33
36
  end
@@ -15,22 +15,19 @@ module Karafka
15
15
  module Pro
16
16
  module Routing
17
17
  module Features
18
- class Filtering < Base
19
- # Contract to validate configuration of the filtering feature
20
- class Contract < Contracts::Base
21
- configure do |config|
22
- config.error_messages = YAML.safe_load(
23
- File.read(
24
- File.join(Karafka.gem_root, 'config', 'locales', 'pro_errors.yml')
25
- )
26
- ).fetch('en').fetch('validations').fetch('topic')
27
- end
28
-
29
- nested(:filtering) do
30
- required(:active) { |val| [true, false].include?(val) }
31
-
32
- required(:factories) do |val|
33
- val.is_a?(Array) && val.all? { |factory| factory.respond_to?(:call) }
18
+ class Patterns < Base
19
+ # Expansions for the routing builder
20
+ module Builder
21
+ # Allows us to define the simple routing pattern matching
22
+ #
23
+ # @param regexp_or_name [Symbol, String, Regexp] name of the pattern or regexp for
24
+ # automatic-based named patterns
25
+ # @param regexp [Regexp, nil] nil if we use auto-generated name based on the regexp or
26
+ # the regexp if we used named patterns
27
+ # @param block [Proc]
28
+ def pattern(regexp_or_name, regexp = nil, &block)
29
+ consumer_group('app') do
30
+ pattern(regexp_or_name, regexp, &block)
34
31
  end
35
32
  end
36
33
  end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This Karafka component is a Pro component under a commercial license.
4
+ # This Karafka component is NOT licensed under LGPL.
5
+ #
6
+ # All of the commercial components are present in the lib/karafka/pro directory of this
7
+ # repository and their usage requires commercial license agreement.
8
+ #
9
+ # Karafka has also commercial-friendly license, commercial support and commercial components.
10
+ #
11
+ # By sending a pull request to the pro components, you are agreeing to transfer the copyright of
12
+ # your code to Maciej Mensfeld.
13
+
14
+ module Karafka
15
+ module Pro
16
+ module Routing
17
+ module Features
18
+ # Holds pattern info reference
19
+ # Type is set to:
20
+ # `:regular` - in case patterns are not used and topic is just a regular existing topic
21
+ # matched directly based on the name
22
+ # `:discovered` - in case it is a real topic on which we started to listed
23
+ # `:matcher` - represents a regular expression used by librdkafka
24
+ class Patterns < Base
25
+ # Config for pattern based topic
26
+ # Only pattern related topics are active in this context
27
+ Config = Struct.new(
28
+ :active,
29
+ :type,
30
+ :pattern,
31
+ keyword_init: true
32
+ ) do
33
+ alias_method :active?, :active
34
+
35
+ # @return [Boolean] is this a matcher topic
36
+ def matcher?
37
+ type == :matcher
38
+ end
39
+
40
+ # @return [Boolean] is this a discovered topic
41
+ def discovered?
42
+ type == :discovered
43
+ end
44
+
45
+ # @return [Boolean] is this a regular topic
46
+ def regular?
47
+ type == :regular
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This Karafka component is a Pro component under a commercial license.
4
+ # This Karafka component is NOT licensed under LGPL.
5
+ #
6
+ # All of the commercial components are present in the lib/karafka/pro directory of this
7
+ # repository and their usage requires commercial license agreement.
8
+ #
9
+ # Karafka has also commercial-friendly license, commercial support and commercial components.
10
+ #
11
+ # By sending a pull request to the pro components, you are agreeing to transfer the copyright of
12
+ # your code to Maciej Mensfeld.
13
+
14
+ module Karafka
15
+ module Pro
16
+ module Routing
17
+ module Features
18
+ class Patterns < Base
19
+ # Expansion of the consumer groups routing component to work with patterns
20
+ module ConsumerGroup
21
+ # @param args [Object] whatever consumer group accepts
22
+ def initialize(*args)
23
+ super
24
+ @patterns = Patterns.new([])
25
+ end
26
+
27
+ # @return [::Karafka::Pro::Routing::Features::Patterns::Patterns] created patterns
28
+ def patterns
29
+ @patterns
30
+ end
31
+
32
+ # Creates the pattern for topic matching with appropriate virtual topic
33
+ # @param regexp_or_name [Symbol, String, Regexp] name of the pattern or regexp for
34
+ # automatic-based named patterns
35
+ # @param regexp [Regexp, nil] nil if we use auto-generated name based on the regexp or
36
+ # the regexp if we used named patterns
37
+ # @param block [Proc] appropriate underlying topic settings
38
+ def pattern=(regexp_or_name, regexp = nil, &block)
39
+ # This code allows us to have a nice nameless (automatic-named) patterns that do not
40
+ # have to be explicitly named. However if someone wants to use names for exclusions
41
+ # it can be done by providing both
42
+ if regexp_or_name.is_a?(Regexp)
43
+ name = nil
44
+ regexp = regexp_or_name
45
+ else
46
+ name = regexp_or_name
47
+ end
48
+
49
+ pattern = Pattern.new(name, regexp, block)
50
+ virtual_topic = public_send(:topic=, pattern.name, &block)
51
+ # Indicate the nature of this topic (matcher)
52
+ virtual_topic.patterns(active: true, type: :matcher, pattern: pattern)
53
+ pattern.topic = virtual_topic
54
+ @patterns << pattern
55
+ end
56
+
57
+ # @return [Hash] consumer group with patterns injected
58
+ def to_h
59
+ super.merge(
60
+ patterns: patterns.map(&:to_h)
61
+ ).freeze
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This Karafka component is a Pro component under a commercial license.
4
+ # This Karafka component is NOT licensed under LGPL.
5
+ #
6
+ # All of the commercial components are present in the lib/karafka/pro directory of this
7
+ # repository and their usage requires commercial license agreement.
8
+ #
9
+ # Karafka has also commercial-friendly license, commercial support and commercial components.
10
+ #
11
+ # By sending a pull request to the pro components, you are agreeing to transfer the copyright of
12
+ # your code to Maciej Mensfeld.
13
+
14
+ module Karafka
15
+ module Pro
16
+ module Routing
17
+ module Features
18
+ class Patterns < Base
19
+ module Contracts
20
+ # Contract to validate configuration of the filtering feature
21
+ class ConsumerGroup < Karafka::Contracts::Base
22
+ configure do |config|
23
+ config.error_messages = YAML.safe_load(
24
+ File.read(
25
+ File.join(Karafka.gem_root, 'config', 'locales', 'pro_errors.yml')
26
+ )
27
+ ).fetch('en').fetch('validations').fetch('consumer_group')
28
+
29
+ required(:patterns) { |val| val.is_a?(Array) && val.all? { |el| el.is_a?(Hash) } }
30
+
31
+ virtual do |data, errors|
32
+ next unless errors.empty?
33
+
34
+ validator = Pattern.new
35
+
36
+ data[:patterns].each do |pattern|
37
+ validator.validate!(pattern)
38
+ end
39
+
40
+ nil
41
+ end
42
+
43
+ # Make sure, that there are no same regular expressions with different names
44
+ # in a single consumer group
45
+ virtual do |data, errors|
46
+ next unless errors.empty?
47
+
48
+ regexp_strings = data[:patterns].map { |pattern| pattern.fetch(:regexp_string) }
49
+
50
+ next if regexp_strings.empty?
51
+ next if regexp_strings.uniq.size == regexp_strings.size
52
+
53
+ [[%i[patterns], :regexps_not_unique]]
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This Karafka component is a Pro component under a commercial license.
4
+ # This Karafka component is NOT licensed under LGPL.
5
+ #
6
+ # All of the commercial components are present in the lib/karafka/pro directory of this
7
+ # repository and their usage requires commercial license agreement.
8
+ #
9
+ # Karafka has also commercial-friendly license, commercial support and commercial components.
10
+ #
11
+ # By sending a pull request to the pro components, you are agreeing to transfer the copyright of
12
+ # your code to Maciej Mensfeld.
13
+
14
+ module Karafka
15
+ module Pro
16
+ module Routing
17
+ module Features
18
+ class Patterns < Base
19
+ # Namespace for patterns related contracts
20
+ module Contracts
21
+ # Contract used to validate pattern data
22
+ class Pattern < Karafka::Contracts::Base
23
+ configure do |config|
24
+ config.error_messages = YAML.safe_load(
25
+ File.read(
26
+ File.join(Karafka.gem_root, 'config', 'locales', 'pro_errors.yml')
27
+ )
28
+ ).fetch('en').fetch('validations').fetch('pattern')
29
+
30
+ required(:regexp) { |val| val.is_a?(Regexp) }
31
+
32
+ required(:regexp_string) do |val|
33
+ val.is_a?(String) && val.start_with?('^') && val.size >= 2
34
+ end
35
+
36
+ required(:name) do |val|
37
+ val.is_a?(String) && Karafka::Contracts::TOPIC_REGEXP.match?(val)
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This Karafka component is a Pro component under a commercial license.
4
+ # This Karafka component is NOT licensed under LGPL.
5
+ #
6
+ # All of the commercial components are present in the lib/karafka/pro directory of this
7
+ # repository and their usage requires commercial license agreement.
8
+ #
9
+ # Karafka has also commercial-friendly license, commercial support and commercial components.
10
+ #
11
+ # By sending a pull request to the pro components, you are agreeing to transfer the copyright of
12
+ # your code to Maciej Mensfeld.
13
+
14
+ module Karafka
15
+ module Pro
16
+ module Routing
17
+ module Features
18
+ class Patterns < Base
19
+ # Namespace for patterns feature contracts
20
+ module Contracts
21
+ # Contract to validate configuration of the patterns feature
22
+ class Topic < Karafka::Contracts::Base
23
+ configure do |config|
24
+ config.error_messages = YAML.safe_load(
25
+ File.read(
26
+ File.join(Karafka.gem_root, 'config', 'locales', 'pro_errors.yml')
27
+ )
28
+ ).fetch('en').fetch('validations').fetch('topic')
29
+ end
30
+
31
+ nested(:patterns) do
32
+ required(:active) { |val| [true, false].include?(val) }
33
+ required(:type) { |val| %i[matcher discovered regular].include?(val) }
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This Karafka component is a Pro component under a commercial license.
4
+ # This Karafka component is NOT licensed under LGPL.
5
+ #
6
+ # All of the commercial components are present in the lib/karafka/pro directory of this
7
+ # repository and their usage requires commercial license agreement.
8
+ #
9
+ # Karafka has also commercial-friendly license, commercial support and commercial components.
10
+ #
11
+ # By sending a pull request to the pro components, you are agreeing to transfer the copyright of
12
+ # your code to Maciej Mensfeld.
13
+
14
+ module Karafka
15
+ module Pro
16
+ module Routing
17
+ module Features
18
+ class Patterns < Base
19
+ # Detects if a given topic matches any of the patterns and if so, injects it into the
20
+ # given subscription group routing
21
+ #
22
+ # @note This is NOT thread-safe and should run in a thread-safe context that warranties
23
+ # that there won't be any race conditions
24
+ class Detector
25
+ # Checks if the provided topic matches any of the patterns and when detected, expands
26
+ # the routing with it.
27
+ #
28
+ # @param sg_topics [Array<Karafka::Routing::Topic>] given subscription group routing
29
+ # topics.
30
+ # @param new_topic [String] new topic that we have detected
31
+ def expand(sg_topics, new_topic)
32
+ sg_topics
33
+ .map(&:patterns)
34
+ .select(&:active?)
35
+ .select(&:matcher?)
36
+ .map(&:pattern)
37
+ .then { |pts| pts.empty? ? return : pts }
38
+ .then { |pts| Patterns.new(pts) }
39
+ .find(new_topic)
40
+ .then { |pattern| pattern || return }
41
+ .then { |pattern| install(pattern, new_topic, sg_topics) }
42
+ end
43
+
44
+ private
45
+
46
+ # Adds the discovered topic into the routing
47
+ #
48
+ # @param pattern [Karafka::Pro::Routing::Features::Patterns::Pattern] matched pattern
49
+ # @param discovered_topic [String] topic that we discovered that should be part of the
50
+ # routing from now on.
51
+ # @param sg_topics [Array<Karafka::Routing::Topic>]
52
+ def install(pattern, discovered_topic, sg_topics)
53
+ consumer_group = pattern.topic.consumer_group
54
+
55
+ # Build new topic and register within the consumer group
56
+ topic = consumer_group.public_send(:topic=, discovered_topic, &pattern.config)
57
+ topic.patterns(active: true, type: :discovered)
58
+
59
+ # Inject into subscription group topics array always, so everything is reflected
60
+ # there but since it is not active, will not be picked
61
+ sg_topics << topic
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This Karafka component is a Pro component under a commercial license.
4
+ # This Karafka component is NOT licensed under LGPL.
5
+ #
6
+ # All of the commercial components are present in the lib/karafka/pro directory of this
7
+ # repository and their usage requires commercial license agreement.
8
+ #
9
+ # Karafka has also commercial-friendly license, commercial support and commercial components.
10
+ #
11
+ # By sending a pull request to the pro components, you are agreeing to transfer the copyright of
12
+ # your code to Maciej Mensfeld.
13
+
14
+ module Karafka
15
+ module Pro
16
+ module Routing
17
+ module Features
18
+ class Patterns < Base
19
+ # Karafka topic pattern object
20
+ # It represents a topic that is not yet materialized and that contains a name that is a
21
+ # regexp and not a "real" value. Underneath we define a dynamic topic, that is not
22
+ # active, that can be a subject to normal flow validations, etc.
23
+ class Pattern
24
+ # Pattern regexp
25
+ attr_accessor :regexp
26
+
27
+ # Each pattern has its own "topic" that we use as a routing reference that we define
28
+ # with non-existing topic for the routing to correctly pick it up for operations
29
+ # Virtual topic name for initial subscription
30
+ attr_reader :name
31
+
32
+ # Associated created virtual topic reference
33
+ attr_accessor :topic
34
+
35
+ # Config for real-topic configuration during injection
36
+ attr_reader :config
37
+
38
+ # @param name [String, Symbol, nil] name or the regexp for building the topic name or
39
+ # nil if we want to make it based on the regexp content
40
+ # @param regexp [Regexp] regular expression to match topics
41
+ # @param config [Proc] config for topic bootstrap
42
+ def initialize(name, regexp, config)
43
+ @regexp = regexp
44
+ # This name is also used as the underlying matcher topic name
45
+ #
46
+ # It can be used provided by the user in case user wants to use exclusions of topics
47
+ # or we can generate it if irrelevant.
48
+ #
49
+ # We generate it based on the regexp so within the same consumer group they are
50
+ # always unique (checked by topic validations)
51
+ #
52
+ # This will not prevent users from creating a different regexps matching the same
53
+ # topic but this minimizes simple mistakes
54
+ #
55
+ # This sub-part of sh1 should be unique enough and short-enough to use it here
56
+ digest = Digest::SHA1.hexdigest(regexp.source)[8..16]
57
+ @name = name ? name.to_s : "karafka-pattern-#{digest}"
58
+ @config = config
59
+ end
60
+
61
+ # @return [String] defined regexp representation as a string that is compatible with
62
+ # librdkafka expectations. We use it as a subscription name for initial patterns
63
+ # subscription start.
64
+ def regexp_string
65
+ "^#{regexp.source}"
66
+ end
67
+
68
+ # @return [Hash] hash representation of this routing pattern
69
+ def to_h
70
+ {
71
+ regexp: regexp,
72
+ name: name,
73
+ regexp_string: regexp_string
74
+ }.freeze
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
@@ -15,20 +15,17 @@ module Karafka
15
15
  module Pro
16
16
  module Routing
17
17
  module Features
18
- class Delaying < Base
19
- # Contract to validate configuration of the expiring feature
20
- class Contract < Contracts::Base
21
- configure do |config|
22
- config.error_messages = YAML.safe_load(
23
- File.read(
24
- File.join(Karafka.gem_root, 'config', 'locales', 'pro_errors.yml')
25
- )
26
- ).fetch('en').fetch('validations').fetch('topic')
27
- end
28
-
29
- nested(:delaying) do
30
- required(:active) { |val| [true, false].include?(val) }
31
- required(:delay) { |val| val.nil? || (val.is_a?(Integer) && val.positive?) }
18
+ class Patterns < Base
19
+ # Representation of groups of topics
20
+ class Patterns < ::Karafka::Routing::Topics
21
+ # Finds first pattern matching given topic name
22
+ #
23
+ # @param topic_name [String] topic name that may match a pattern
24
+ # @return [Karafka::Routing::Pattern, nil] pattern or nil if not found
25
+ # @note Please keep in mind, that there may be many patterns matching given topic name
26
+ # and we always pick the first one (defined first)
27
+ def find(topic_name)
28
+ @accumulator.find { |pattern| pattern.regexp =~ topic_name }
32
29
  end
33
30
  end
34
31
  end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This Karafka component is a Pro component under a commercial license.
4
+ # This Karafka component is NOT licensed under LGPL.
5
+ #
6
+ # All of the commercial components are present in the lib/karafka/pro directory of this
7
+ # repository and their usage requires commercial license agreement.
8
+ #
9
+ # Karafka has also commercial-friendly license, commercial support and commercial components.
10
+ #
11
+ # By sending a pull request to the pro components, you are agreeing to transfer the copyright of
12
+ # your code to Maciej Mensfeld.
13
+
14
+ module Karafka
15
+ module Pro
16
+ module Routing
17
+ module Features
18
+ class Patterns < Base
19
+ # Patterns feature topic extensions
20
+ module Topic
21
+ # @return [String] subscription name or the regexp string representing matching of
22
+ # new topics that should be detected.
23
+ def subscription_name
24
+ patterns.active? && patterns.matcher? ? patterns.pattern.regexp_string : super
25
+ end
26
+
27
+ # @param active [Boolean] is this topic active member of patterns
28
+ # @param type [Symbol] type of topic taking part in pattern matching
29
+ # @param pattern [Regexp] regular expression for matching
30
+ def patterns(active: false, type: :regular, pattern: nil)
31
+ @patterns ||= Config.new(active: active, type: type, pattern: pattern)
32
+ end
33
+
34
+ # @return [Boolean] is this topic a member of patterns
35
+ def patterns?
36
+ patterns.active?
37
+ end
38
+
39
+ # @return [Hash] topic with all its native configuration options plus patterns
40
+ def to_h
41
+ super.merge(
42
+ patterns: patterns.to_h
43
+ ).freeze
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end